Initial commit

This commit is contained in:
zhongjin
2020-06-15 10:58:47 +08:00
commit 4f1dfe7564
8590 changed files with 1516878 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
var _ = require('underscore');
var CoreView = require('backbone/core-view');
var TabPaneViewRouted = require('./tab-pane-view-routed.js');
var TabPaneCollection = require('./tab-pane-collection');
var IconView = require('./tab-pane-icon-view');
/**
* Creates a tab pane representing editor's left-vertical menu, where the tab items are large icons,
* and the content on the right.
*
* Example usage:
* {
* icon: 'my-icon',
* createContentView: CoreView(),
* selected: false
* }
* @param {Array} paneItems
* @param {Object} options
* @return {Object} instance of a Backbone view
*/
module.exports = function (paneItems, options) {
options = options || {};
var tabPaneItemIconOptions = options.tabPaneItemIconOptions;
var items = paneItems.map(function (paneItem) {
['icon', 'createContentView', 'tooltip'].forEach(function (check) {
if (!paneItem[check]) {
throw new Error(check + ' should be provided');
}
});
return {
selected: paneItem.selected,
name: paneItem.name,
route: paneItem.route,
icon: paneItem.icon,
onClick: paneItem.onClick,
tooltip: paneItem.tooltip,
createButtonView: function () {
return new IconView(_.extend({ model: this }, tabPaneItemIconOptions));
},
createContentView: function () {
return paneItem.createContentView && paneItem.createContentView() || new CoreView();
}
};
});
var collection = new TabPaneCollection(items);
var tabPaneOptions = options.tabPaneOptions;
return new TabPaneViewRouted(
_.extend(
{ collection: collection },
tabPaneOptions
)
);
};

View File

@@ -0,0 +1,63 @@
var _ = require('underscore');
var CoreView = require('backbone/core-view');
var TabPaneView = require('./tab-pane-view.js');
var TabPaneCollection = require('./tab-pane-collection');
var MixedLabelView = require('./tab-pane-mixed-view');
var ColorView = require('./tab-pane-color-view');
/**
* Creates a tab pane, where the menu consists of text labels.
*
* Example usage:
* {
* label: 'My label',
* createContentView: CoreView(),
* selected: false
* }
*
* @param {Array} paneItems
* @param {Object} options
* @return {Object} instance of CoreView
*/
module.exports = function (paneItems, options) {
options = options || {};
var tabPaneItemLabelOptions = options.tabPaneItemLabelOptions;
var items = paneItems.map(function (paneItem) {
['label', 'createContentView'].forEach(function (check) {
if (!paneItem[check]) {
throw new Error(check + ' should be provided');
}
});
return {
name: paneItem.name,
selected: paneItem.selected,
label: paneItem.label,
color: paneItem.color,
kind: paneItem.kind,
selectedChild: paneItem.selectedChild,
createButtonView: function () {
if (paneItem.type === 'color') {
return new ColorView(_.extend({ model: this }, tabPaneItemLabelOptions));
} else {
return new MixedLabelView(_.extend({ model: this, type: paneItem.type }, tabPaneItemLabelOptions));
}
},
createContentView: function () {
return paneItem.createContentView && paneItem.createContentView() || new CoreView();
}
};
});
var collection = new TabPaneCollection(items);
var tabPaneOptions = options.tabPaneOptions;
return new TabPaneView(
_.extend(
{ collection: collection },
tabPaneOptions
)
);
};

View File

@@ -0,0 +1,59 @@
var _ = require('underscore');
var CoreView = require('backbone/core-view');
var TabPaneView = require('./tab-pane-view.js');
var TabPaneCollection = require('./tab-pane-collection');
var RadioLabelView = require('./tab-pane-radio-label-view');
/**
* Creates a tab pane, where the menu consists of radio inputs with labels.
*
* Example usage:
* {
* label: 'My label',
* createContentView: CoreView(),
* selected: false
* }
*
* @param {Array} paneItems
* @param {Object} options
* @return {Object} instance of CoreView
*/
module.exports = function (paneItems, options) {
options = options || {};
var tabPaneItemLabelOptions = options.tabPaneItemLabelOptions;
var items = paneItems.map(function (paneItem) {
['label', 'createContentView'].forEach(function (check) {
if (!paneItem[check]) {
throw new Error(check + ' should be provided');
}
});
return {
name: paneItem.name,
selected: paneItem.selected,
disabled: paneItem.disabled,
tooltip: paneItem.tooltip,
tooltipGravity: paneItem.tooltipGravity,
label: paneItem.label,
selectedChild: paneItem.selectedChild,
createButtonView: function () {
return new RadioLabelView(_.extend({ model: this }, tabPaneItemLabelOptions));
},
createContentView: function () {
return paneItem.createContentView && paneItem.createContentView() || new CoreView();
}
};
});
var collection = new TabPaneCollection(items);
var tabPaneOptions = options.tabPaneOptions;
return new TabPaneView(
_.extend(
{ collection: collection },
tabPaneOptions
)
);
};

View File

@@ -0,0 +1,55 @@
var _ = require('underscore');
var cdb = require('internal-carto.js');
var TabPaneView = require('./tab-pane-view.js');
var TabPaneCollection = require('./tab-pane-collection');
var TemplateView = require('./tab-pane-template-view');
/**
* Creates a tab pane, where the menu consists of text labels.
*
* Example usage:
* {
* label: 'My label',
* createContentView: cdb.core.View(),
* selected: false
* }
*
* @param {Array} paneItems
* @param {Object} options
* @return {Object} instance of cdb.core.View
*/
module.exports = function (paneItems, options) {
options = options || {};
var tabPaneTemplateOptions = options.tabPaneTemplateOptions;
var items = paneItems.map(function (paneItem) {
['label', 'name', 'createContentView'].forEach(function (check) {
if (!paneItem[check]) {
throw new Error(check + ' should be provided');
}
});
return {
name: paneItem.name,
selected: paneItem.selected,
label: paneItem.label,
createButtonView: function () {
return new TemplateView(_.extend({ model: this }, tabPaneTemplateOptions));
},
createContentView: function () {
return paneItem.createContentView && paneItem.createContentView() || new cdb.core.View();
}
};
});
var collection = new TabPaneCollection(items);
var tabPaneOptions = options.tabPaneOptions;
return new TabPaneView(
_.extend(
{ collection: collection },
tabPaneOptions
)
);
};

View File

@@ -0,0 +1,60 @@
var _ = require('underscore');
var CoreView = require('backbone/core-view');
var TabPaneViewRouted = require('./tab-pane-view-routed');
var TabPaneCollection = require('./tab-pane-collection');
var LabelView = require('./tab-pane-label-view');
/**
* Creates a tab pane, where the menu consists of text labels.
*
* Example usage:
* {
* label: 'My label',
* createContentView: CoreView(),
* selected: false
* }
*
* @param {Array} paneItems
* @param {Object} options
* @return {Object} instance of CoreView
*/
module.exports = function (paneItems, options) {
options = options || {};
var tabPaneItemLabelOptions = options.tabPaneItemLabelOptions;
var items = paneItems.map(function (paneItem) {
['label', 'createContentView'].forEach(function (check) {
if (!paneItem[check]) {
throw new Error(check + ' should be provided');
}
});
return {
name: paneItem.name,
selected: paneItem.selected,
disabled: paneItem.disabled,
tooltip: paneItem.tooltip,
layerId: paneItem.layerId,
label: paneItem.label,
onClick: paneItem.onClick,
selectedChild: paneItem.selectedChild,
createButtonView: function () {
return new LabelView(_.extend({ model: this }, tabPaneItemLabelOptions));
},
createContentView: function () {
return paneItem.createContentView && paneItem.createContentView() || new CoreView();
}
};
});
var collection = new TabPaneCollection(items, options);
var tabPaneOptions = options.tabPaneOptions;
return new TabPaneViewRouted(
_.extend(
{ collection: collection },
tabPaneOptions
)
);
};

View File

@@ -0,0 +1,58 @@
var _ = require('underscore');
var CoreView = require('backbone/core-view');
var TabPaneView = require('./tab-pane-view.js');
var TabPaneCollection = require('./tab-pane-collection');
var LabelView = require('./tab-pane-label-view');
/**
* Creates a tab pane, where the menu consists of text labels.
*
* Example usage:
* {
* label: 'My label',
* createContentView: CoreView(),
* selected: false
* }
*
* @param {Array} paneItems
* @param {Object} options
* @return {Object} instance of CoreView
*/
module.exports = function (paneItems, options) {
options = options || {};
var tabPaneItemLabelOptions = options.tabPaneItemLabelOptions;
var items = paneItems.map(function (paneItem) {
['label', 'createContentView'].forEach(function (check) {
if (!paneItem[check]) {
throw new Error(check + ' should be provided');
}
});
return {
name: paneItem.name,
selected: paneItem.selected,
disabled: paneItem.disabled,
tooltip: paneItem.tooltip,
label: paneItem.label,
selectedChild: paneItem.selectedChild,
createButtonView: function () {
return new LabelView(_.extend({ model: this }, tabPaneItemLabelOptions));
},
createContentView: function () {
return paneItem.createContentView && paneItem.createContentView() || new CoreView();
}
};
});
var collection = new TabPaneCollection(items);
var tabPaneOptions = options.tabPaneOptions;
return new TabPaneView(
_.extend(
{ collection: collection },
tabPaneOptions
)
);
};

View File

@@ -0,0 +1,80 @@
var Backbone = require('backbone');
var _ = require('underscore');
module.exports = Backbone.Collection.extend({
constructor: function (models, options) {
options = _.extend(options || {}, { silent: false });
Backbone.Collection.prototype.constructor.call(this, models, options);
},
initialize: function (models, options) {
this._disabledTabs = options.disabledTabs;
this._initBinds();
this._setSelected();
},
_initBinds: function () {
this.bind('reset', this._setSelected, this);
this.bind('change:selected', this._onSelectedChange, this);
},
getSelected: function () {
return this.find(function (model) {
return model.get('selected');
});
},
getDefault: function () {
return this.find(function (model) {
return model.get('name') === this.getDefaultName();
}, this);
},
getDisabledTabs: function () {
return this._disabledTabs || [];
},
getDefaultName: function () {
return this._defaultTab;
},
isDisabledTab: function (name) {
var disabledTab = this.find(function (model) {
return model.get('disabled') && model.get('name') === name;
});
return !!disabledTab;
},
_setSelected: function () {
var isSelected = this.getSelected();
if (!isSelected && this.size() > 0) {
this.at(0).set('selected', true);
}
},
_onSelectedChange: function (itemModel, isSelected) {
if (!isSelected) {
return;
}
this.each(function (model) {
if (model !== itemModel) {
model.set('selected', false);
}
}, this);
},
select: function (name, value) {
var model = this.find(function (m) {
return m.get(name) === value;
}, this);
if (model) {
model.set('selected', true);
}
}
});

View File

@@ -0,0 +1,27 @@
var CoreView = require('backbone/core-view');
var template = require('./tab-pane-color.tpl');
/**
* Label component
*/
module.exports = CoreView.extend({
className: 'Label',
initialize: function () {
if (!this.model) {
throw new Error('A model should be provided');
}
this.model.bind('change:label', this.render, this);
},
render: function () {
this.clearSubViews();
this.$el.html(template({
color: this.model.get('label'),
selectedChild: this.model.get('selectedChild') || ''
}));
return this;
}
});

View File

@@ -0,0 +1 @@
<div class="ColorBar ColorBar--inline" style="background-color: <%- color %>;"></div> <% if (selectedChild) { %> <span class="CDB-NavSubmenu-status js-NavSubmenu-status u-hintTextColor"><%- selectedChild %></span><% } %>

View File

@@ -0,0 +1,7 @@
<% if (type === 'text') { %>
<%- label %><% if (selectedChild) { %> <span class="CDB-NavSubmenu-status js-NavSubmenu-status u-hintTextColor"><%- selectedChild %></span><% } %>
<% } else if (kind === 'custom-marker') { %>
<div class='Editor-categoryImagesTag CDB-Text CDB-FontSize-small u-altTextColor is-semibold u-upperCase'><%- _t('form-components.editors.fill.input-color.img') %></div>
<% } else { %>
<div class="Tab-paneLabelImageContainer js-image-container"></div>
<% } %>

View File

@@ -0,0 +1,28 @@
var CoreView = require('backbone/core-view');
var Template = require('./tab-pane-icon.tpl');
/**
* Icon component
*/
module.exports = CoreView.extend({
tagName: 'i',
className: 'CDB-IconFont',
initialize: function (options) {
if (!this.model) {
throw new Error('A model should be provided');
}
this.template = this.options.template || Template;
},
render: function () {
this.$el.html(this.template({
icon: this.model.get('icon')
}));
return this;
}
});

View File

@@ -0,0 +1 @@
<i class="CDB-IconFont CDB-IconFont-<%- icon %>"></i>

View File

@@ -0,0 +1,11 @@
var _ = require('underscore');
var TabPaneItemView = require('./tab-pane-item-view.js');
module.exports = TabPaneItemView.extend({
_onButtonClicked: function (event) {
event.preventDefault();
if (this.model.get('disabled')) return;
_.isFunction(this.model.get('onClick')) && this.model.get('onClick')();
}
});

View File

@@ -0,0 +1,91 @@
var CoreView = require('backbone/core-view');
var _ = require('underscore');
var TipsyTooltipView = require('builder/components/tipsy-tooltip-view');
/**
* TabPaneItem component
*/
module.exports = CoreView.extend({
module: 'components:tab-pane:tab-pane-item-view',
tagName: 'button',
className: function () {
var classes = [this.options.klassName];
if (this.model.get('selected')) {
classes.push('is-selected');
}
if (this.model.get('disabled')) {
classes.push('is-disabled');
}
return classes.join(' ');
},
events: {
'click': '_onButtonClicked'
},
initialize: function () {
if (!this.model) {
throw new Error('A model should be provided');
}
this.model.bind('change:selected', this._onChangeSelected, this);
},
render: function () {
this.clearSubViews();
this._initViews();
return this;
},
_initViews: function () {
this._initButton();
this._initTooltip();
},
_initButton: function () {
var view = this.model.get('createButtonView').call(this.model);
this.addView(view);
this.$el.append(view.render().$el);
},
_initTooltip: function () {
var tooltip = this.model.get('tooltip');
if (tooltip) {
var buttonTooltip = new TipsyTooltipView({
el: this.$el,
title: function () {
return _t(tooltip);
},
gravity: this.model.get('tooltipGravity') || 'w'
});
this._buttonTooltip = buttonTooltip;
this.addView(buttonTooltip);
}
},
_onChangeSelected: function () {
var isSelected = !!this.model.get('selected');
if (!isSelected) {
this._buttonTooltip && this._buttonTooltip.hideTipsy();
}
this.$el.toggleClass('is-selected', isSelected);
},
_onButtonClicked: function (event) {
event.preventDefault();
if (this.model.get('disabled')) return;
this.model.set('selected', true);
_.isFunction(this.model.get('onClick')) && this.model.get('onClick')();
},
clean: function () {
this._buttonTooltip && this._buttonTooltip.clean();
}
});

View File

@@ -0,0 +1,26 @@
var CoreView = require('backbone/core-view');
var template = require('./tab-pane-label.tpl');
/**
* Label component
*/
module.exports = CoreView.extend({
className: 'Label',
initialize: function () {
if (!this.model) {
throw new Error('A model should be provided');
}
this.model.on('change:label', this.render, this);
},
render: function () {
this.$el.html(template({
label: this.model.get('label'),
selectedChild: this.model.get('selectedChild') || ''
}));
return this;
}
});

View File

@@ -0,0 +1 @@
<%- label %><% if (selectedChild) { %> <span class="CDB-NavSubmenu-status js-NavSubmenu-status u-hintTextColor"><%- selectedChild %></span><% } %>

View File

@@ -0,0 +1,62 @@
var template = require('./tab-pane-file.tpl');
var CoreView = require('backbone/core-view');
var ImageLoaderView = require('builder/components/img-loader-view');
/**
* File component
*/
module.exports = CoreView.extend({
tagName: 'i',
className: 'CDB-IconFont',
initialize: function (options) {
if (!this.model) throw new Error('A model should be provided');
this.model.bind('change:label', this.render, this);
this.model.bind('change:color', this._updateColor, this);
},
render: function () {
this.clearSubViews();
var labelType = this._getLabelType();
this.$el.html(template({
type: labelType,
label: this.model.get('label'),
kind: this.model.get('kind'),
selectedChild: this.model.get('selectedChild') || ''
}));
if (labelType === 'file') {
this._loadImages();
}
return this;
},
_loadImages: function () {
this.iconView = new ImageLoaderView({
imageClass: 'Tab-paneLabelImage',
imageUrl: this._getImageURL(),
color: this.model.get('color')
});
this.addView(this.iconView);
this.$('.js-image-container').append(this.iconView.render().el);
},
_updateColor: function () {
this.iconView && this.iconView.updateImageColor(this.model.get('color'));
},
_getLabelType: function () {
var label = this.model.get('label');
return label && label.match(/^http/) ? 'file' : 'text';
},
_getImageURL: function () {
return this.model.get('label');
}
});

View File

@@ -0,0 +1,32 @@
var CoreView = require('backbone/core-view');
var template = require('./tab-pane-radio-label.tpl');
/**
* Label component with a Radio button
*/
module.exports = CoreView.extend({
className: 'Label',
initialize: function () {
if (!this.model) {
throw new Error('A model should be provided');
}
this.model.on('change:label', this.render, this);
this.model.on('change:selected', this.render, this);
},
render: function () {
this.$el.html(template({
customId: this.model.cid + this.model.get('name'),
label: this.model.get('label'),
name: this.model.get('name'),
help: this.model.get('help') || '',
selected: this.model.get('selected'),
selectedChild: this.model.get('selectedChild') || ''
}));
return this;
}
});

View File

@@ -0,0 +1,6 @@
<input id="<%- customId %>" class="CDB-Radio" type="radio" value="<%- name %>" <% if (selected) { %> checked <% } %> />
<span class="u-iBlock CDB-Radio-face"></span>
<label for="<%- customId %>" class="u-iBlock u-lSpace CDB-Text CDB-Size-medium <% if (help) { %>js-help<% } %>" <% if (help) { %> data-tooltip="<%- help %>"<% } %> >
<%- label %>
</label>
<% if (selectedChild) { %> <span class="CDB-NavSubmenu-status js-NavSubmenu-status u-hintTextColor"><%- selectedChild %></span><% } %>

View File

@@ -0,0 +1,19 @@
var cdb = require('internal-carto.js');
/**
* Icon component
*/
module.exports = cdb.core.View.extend({
initialize: function (options) {
if (!this.model) throw new Error('A model should be provided');
if (!options.template) throw new Error('A template should be provided');
this.template = options.template;
},
render: function () {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});

View File

@@ -0,0 +1 @@
<i class="<%- name %>"></i> <%- label %>

View File

@@ -0,0 +1,52 @@
var _ = require('underscore');
var TabPaneView = require('./tab-pane-view.js');
var TabPaneViewItemRouted = require('./tab-pane-item-view-routed.js');
var Router = require('builder/routes/router');
module.exports = TabPaneView.extend({
initialize: function (options) {
TabPaneView.prototype.initialize.call(this, options);
this._initialRoute = false;
this.onRouteChange = options.onRouteChange;
this.onRouteChange && this.listenTo(Router.getRouteModel(), 'change:currentRoute', this.onRouteChange);
this.onRouteChange && this._setInitialRoute(Router.getRouteModel());
},
_renderTabPaneItemView: function (model) {
var tabPaneItemView = new TabPaneViewItemRouted(_.extend({ model: model }, this._tabPaneItemOptions));
this.addView(tabPaneItemView);
this.$('.js-menu').append(tabPaneItemView.render().el);
},
_setInitialRoute: function (routeModel) {
this._initialRoute = true;
this.onRouteChange(routeModel);
},
_renderTabPaneContentView: function (model) {
var selectedView = TabPaneView.prototype._renderTabPaneContentView.call(this, model);
var currentRoute = Router.getCurrentRoute();
var routeName = _.last(currentRoute.split('/'));
var tabName = model.get('name');
if (this._initialRoute) {
var parsed = selectedView.handleRoute && selectedView.handleRoute(Router.getRouteModel());
if (parsed === false) {
Router.replaceWithRoot();
}
if (this.collection.isDisabledTab(routeName) && tabName !== routeName) {
var newRoute = currentRoute.replace(routeName, tabName);
Router.replaceState(newRoute);
}
this._initialRoute = false;
} else {
selectedView.handleRoute && selectedView.handleRoute(Router.getRouteModel());
}
return selectedView;
}
});

View File

@@ -0,0 +1,115 @@
var _ = require('underscore');
var CoreView = require('backbone/core-view');
var TabPaneItem = require('./tab-pane-item-view.js');
var Template = require('./tab-pane.tpl');
/**
* TabPane component
*/
module.exports = CoreView.extend({
className: 'Tab-pane',
events: {
'mouseover': '_onMouseOver'
},
initialize: function (options) {
if (!this.collection) {
throw new Error('A TabPaneCollection should be provided');
}
this._tabPaneItemOptions = this.options.tabPaneItemOptions;
this._createContentKey = this.options.createContentKey || 'createContentView';
this.template = this.options.template || Template;
if (this.options.mouseOverAction) {
this._mouseOverAction = this.options.mouseOverAction;
}
this.collection.bind('change:selected', this._renderSelected, this);
},
render: function () {
this.clearSubViews();
this.$el.empty();
this.$el.html(this.template(this.options));
this._renderCollection();
var model = this.getSelectedTabPane();
if (model) {
this._renderSelected(model, true);
}
return this;
},
getTabPaneCollection: function () {
return this.collection;
},
getSelectedTabPane: function () {
return this.collection.getSelected();
},
getTabPane: function (name) {
return _.first(this.collection.where({ name: name }));
},
getSelectedTabPaneName: function () {
var selectedTab = this.getSelectedTabPane();
return selectedTab ? selectedTab.get('name') : null;
},
setSelectedTabPaneByName: function (name) {
return this.collection.select('name', name);
},
_renderSelected: function (model, isSelected) {
if (isSelected) {
if (this._selectedView) {
this._selectedView.clean();
this.removeView(this._selectedView);
}
this._selectedView = this._renderTabPaneContentView(model);
}
},
_renderCollection: function () {
this.collection.each(function (paneModel) {
if (paneModel.get('createButtonView')) {
this._renderTabPaneItemView(paneModel);
}
}, this);
},
_renderTabPaneItemView: function (model) {
var tabPaneItemView = new TabPaneItem(_.extend({ model: model }, this._tabPaneItemOptions));
this.addView(tabPaneItemView);
this.$('.js-menu').append(tabPaneItemView.render().el);
},
_renderTabPaneContentView: function (model) {
var tabPaneContentView = model.get(this._createContentKey).call(model);
if (tabPaneContentView) {
this.addView(tabPaneContentView);
this.$('.js-content').append(tabPaneContentView.render().el);
if (typeof tabPaneContentView.afterRender === 'function') {
tabPaneContentView.afterRender();
}
}
return tabPaneContentView;
},
changeStyleMenu: function (m) {
this.$('.js-theme').toggleClass('is-dark', m.isEditing());
},
_onMouseOver: function () {
this._mouseOverAction && this._mouseOverAction();
}
});

View File

@@ -0,0 +1,2 @@
<div class="js-menu"></div>
<div class="Tab-paneContent js-content"></div>