Initial commit
This commit is contained in:
@@ -0,0 +1,234 @@
|
||||
var CoreView = require('backbone/core-view');
|
||||
var _ = require('underscore');
|
||||
var Ps = require('perfect-scrollbar');
|
||||
var emptyTemplate = require('./custom-list-empty.tpl');
|
||||
var addTemplate = require('./custom-list-add.tpl');
|
||||
var template = require('./custom-list.tpl');
|
||||
var Utils = require('builder/helpers/utils');
|
||||
|
||||
var ARROW_DOWN_KEY_CODE = 40;
|
||||
var ARROW_UP_KEY_CODE = 38;
|
||||
var ENTER_KEY_CODE = 13;
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
module: 'components:custom-list:custom-list-view',
|
||||
|
||||
options: {
|
||||
size: 3
|
||||
},
|
||||
|
||||
className: 'CDB-Text CDB-Size-medium CustomList-listWrapper',
|
||||
|
||||
tagName: 'div',
|
||||
|
||||
events: {
|
||||
'click .js-add-custom-value': '_onClickAddCustomValue',
|
||||
'mouseover': '_onMouseOver',
|
||||
'mouseout': '_onMouseOut'
|
||||
},
|
||||
|
||||
initialize: function (opts) {
|
||||
this.options = _.extend({}, this.options, opts);
|
||||
|
||||
this._onKeyDownBinded = this._onKeyDown.bind(this);
|
||||
this._needsMaxSize = true;
|
||||
|
||||
if (this.options.mouseOverAction) {
|
||||
this._mouseOverAction = this.options.mouseOverAction;
|
||||
}
|
||||
|
||||
if (this.options.mouseOutAction) {
|
||||
this._mouseOutAction = this.options.mouseOutAction;
|
||||
}
|
||||
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
this._removeArrowBinds();
|
||||
this._destroyCustomScroll();
|
||||
this.$el.empty();
|
||||
|
||||
var query = this.model.get('query');
|
||||
var items = this.collection.search(query);
|
||||
|
||||
this.$el.append(template());
|
||||
|
||||
var allowFreeTextInput = this.options.allowFreeTextInput;
|
||||
|
||||
if (allowFreeTextInput && query && !Utils.isBlank(query)) {
|
||||
if (!this.collection.containsValue(query)) {
|
||||
this.$el.prepend(
|
||||
addTemplate({
|
||||
query: query,
|
||||
typeLabel: this.options.typeLabel
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (items.size() > 0) {
|
||||
items.each(this._renderItem, this);
|
||||
this._applyArrowBinds();
|
||||
// Perfect-scroll needs to have the element in the DOM in order to
|
||||
// style/positionate the scroll properly, small trick
|
||||
setTimeout(this._applyCustomScroll.bind(this), 0);
|
||||
} else if (!allowFreeTextInput || Utils.isBlank(query)) {
|
||||
this.$el.append(
|
||||
emptyTemplate({
|
||||
query: query,
|
||||
typeLabel: this.options.typeLabel
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_renderItem: function (model) {
|
||||
if (model.get('hidden')) return;
|
||||
var ItemViewClass = this.options.itemView;
|
||||
|
||||
var itemView = new ItemViewClass({
|
||||
model: model,
|
||||
typeLabel: this.options.typeLabel,
|
||||
template: this.options.itemTemplate
|
||||
});
|
||||
this.$('.js-list').append(itemView.render().el);
|
||||
this.addView(itemView);
|
||||
|
||||
itemView.bind('customEvent', function (eventName, item) {
|
||||
this.trigger('customEvent', eventName, item, this);
|
||||
}, this);
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.model.bind('change:query', this._onQueryChanged, this);
|
||||
},
|
||||
|
||||
_applyArrowBinds: function () {
|
||||
document.addEventListener('keydown', this._onKeyDownBinded);
|
||||
},
|
||||
|
||||
_removeArrowBinds: function () {
|
||||
document.removeEventListener('keydown', this._onKeyDownBinded);
|
||||
},
|
||||
|
||||
_getSelected: function () {
|
||||
var selectedModel = this.collection.getSelectedItem();
|
||||
var selectedValue;
|
||||
|
||||
if (selectedModel) {
|
||||
selectedValue = selectedModel.getValue();
|
||||
return this.$("[data-val='" + selectedValue + "']");
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
_highlightSelected: function (item) {
|
||||
var itemHeight = item.outerHeight();
|
||||
item.addClass('is-highlighted');
|
||||
this.$('.js-list').scrollTop(item.index() * itemHeight);
|
||||
},
|
||||
|
||||
_onClickAddCustomValue: function (event) {
|
||||
this.killEvent(event);
|
||||
|
||||
var query = this.model.get('query');
|
||||
|
||||
var model = this.collection.add({
|
||||
val: query,
|
||||
label: '“' + query + '”',
|
||||
dirty: true
|
||||
});
|
||||
|
||||
this.collection.sortByKey('val');
|
||||
model.set('selected', true);
|
||||
},
|
||||
|
||||
_onKeyDown: function (event) {
|
||||
if (this.model.get('visible') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
var key = event.which;
|
||||
var $listItems = this.$('.js-listItem');
|
||||
var $highlighted = $listItems.filter('.is-highlighted');
|
||||
var $current;
|
||||
var model;
|
||||
|
||||
$highlighted.removeClass('is-highlighted');
|
||||
|
||||
if (key === ARROW_DOWN_KEY_CODE) {
|
||||
if (!$highlighted.length || $highlighted[0] === $listItems.last()[0]) {
|
||||
$current = $listItems.eq(0);
|
||||
} else {
|
||||
$current = $highlighted.next();
|
||||
}
|
||||
} else if (key === ARROW_UP_KEY_CODE) {
|
||||
if (!$highlighted.length || $highlighted[0] === $listItems.first()[0]) {
|
||||
$current = $listItems.last();
|
||||
} else {
|
||||
$current = $highlighted.prev();
|
||||
}
|
||||
} else if (key === ENTER_KEY_CODE) {
|
||||
event.preventDefault();
|
||||
if ($highlighted && $highlighted.length) {
|
||||
model = _.first(this.collection.where({ val: $highlighted.data('val') }));
|
||||
if (model) {
|
||||
model.set('selected', true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$current && this._highlightSelected($current);
|
||||
},
|
||||
|
||||
_onQueryChanged: function () {
|
||||
var prevQuery = this.collection.findWhere({ val: this.model.previous('query'), dirty: true });
|
||||
this.collection.remove(prevQuery);
|
||||
|
||||
this.render();
|
||||
},
|
||||
|
||||
_applyCustomScroll: function () {
|
||||
Ps.initialize(this._wrapperContainer().get(0), {
|
||||
wheelSpeed: 2,
|
||||
wheelPropagation: true,
|
||||
stopPropagationOnClick: false,
|
||||
minScrollbarLength: 20
|
||||
});
|
||||
},
|
||||
|
||||
_destroyCustomScroll: function () {
|
||||
if (this._wrapperContainer().length > 0) {
|
||||
Ps.destroy(this._wrapperContainer().get(0));
|
||||
}
|
||||
},
|
||||
|
||||
_wrapperContainer: function () {
|
||||
return this.$('.js-list');
|
||||
},
|
||||
|
||||
clean: function () {
|
||||
this._removeArrowBinds();
|
||||
this._destroyCustomScroll();
|
||||
CoreView.prototype.clean.apply(this);
|
||||
},
|
||||
|
||||
highlight: function () {
|
||||
var selected = this._getSelected();
|
||||
selected && this._highlightSelected(selected);
|
||||
},
|
||||
|
||||
_onMouseOver: function () {
|
||||
this._mouseOverAction && this._mouseOverAction();
|
||||
},
|
||||
|
||||
_onMouseOut: function () {
|
||||
this._mouseOutAction && this._mouseOutAction();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user