').addClass("multiple"),this.textField=this.el.find("textarea"),this.textField.attr("placeholder",this.opts.placeholder),t.isArray(this.opts.selected)&&t.each(this.opts.selected,function(t){return function(e,i){return t.addSelected(i)}}(this)),this.el},i.prototype._bind=function(){return i.__super__._bind.call(this),this.el.on("mousedown",".selected-item",function(e){return function(i){var r;return r=t(i.currentTarget),e.triggerHandler("itemClick",[r,r.data("item")]),!1}}(this))},i.prototype._onBackspacePress=function(t){if(!this.getValue())return t.preventDefault(),this.el.find(".selected-item:last").mousedown()},i.prototype._onInputChange=function(){return this.triggerHandler("change",[this.getValue()])},i.prototype._autoresize=function(){},i.prototype._setPlaceholder=function(t){return null==t&&(t=!0),t?this.textField.attr("placeholder",this.opts.placeholder):this.textField.removeAttr("placeholder")},i.prototype.setSelected=function(t){return null==t&&(t=!1),t?this.addSelected(selected):this.clear()},i.prototype.addSelected=function(e){var r;if(e instanceof o||(e=this.dataProvider.getItem(e)),e)return this.selected||(this.selected=[]),this.selected.push(e),r=t(i._itemTpl).attr("data-value",e.value).data("item",e),r.find(".item-label").text(e.name),r.insertBefore(this.textField),this.setValue(""),this._setPlaceholder(!1),e},i.prototype.removeSelected=function(e){if(e instanceof o||(e=this.dataProvider.getItem(e)),e)return this.selected&&(t.each(this.selected,function(t){return function(i,r){if(r.value===e.value)return t.selected.splice(i,1),!1}}(this)),0===this.selected.length&&(this.selected=!1,this._setPlaceholder(!0))),this.el.find(".selected-item[data-value='"+e.value+"']").remove(),this.setValue(""),e},i.prototype.clear=function(){return this.setValue(""),this.selected=!1,this._setPlaceholder(!0),this.el.find(".selected-item").remove()},i}(n),i.exports=s},{"./input.coffee":2,"./models/item.coffee":5}],7:[function(i,r,n){var o,s,l,u,p=function(t,e){function i(){this.constructor=t}for(var r in e)a.call(e,r)&&(t[r]=e[r]);return i.prototype=e.prototype,t.prototype=new i,t.__super__=e.prototype,t},a={}.hasOwnProperty;o=i("./models/data-provider.coffee"),s=i("./models/group.coffee"),l=i("./models/item.coffee"),u=function(e){function i(){return i.__super__.constructor.apply(this,arguments)}return p(i,e),i._itemTpl='
',i.prototype.opts={el:null,groups:[],onItemRender:null,localse:{}},i.prototype._init=function(){return this.el=t(this.opts.el),this.groups=this.opts.groups,this._render(),this._bind()},i.prototype._renderItem=function(e){var r;return r=t(i._itemTpl).data("item",e),r.find(".label").text(e.name),e.data.hint&&r.find(".hint").text(e.data.hint),r.attr("data-value",e.value),this.el.append(r),t.isFunction(this.opts.onItemRender)&&this.opts.onItemRender.call(this,r,e),r},i.prototype._render=function(){var e;return this.el.empty(),e=1===this.groups.length&&this.groups[0].name===s.defaultName,0===this.groups.length||e&&0===this.groups[0].items.length?t('
').text(this.opts.locales.noResults).appendTo(this.el):e?t.each(this.groups[0].items,function(t){return function(e,i){return t._renderItem(i)}}(this)):t.each(this.groups,function(e){return function(i,r){return t('
').text(r.name).appendTo(e.el),t.each(r.items,function(t,i){return e._renderItem(i)})}}(this)),this.el},i.prototype._bind=function(){return this.el.on("mousedown",".select-item",function(e){return function(i){var r;return r=t(i.currentTarget),e.triggerHandler("itemClick",[r,r.data("item")]),!1}}(this))},i.prototype._scrollToHighlighted=function(){var t;if(t=this.el.find(".select-item.highlighted"),t.length>0)return this.el.scrollTop(t.position().top)},i.prototype.setGroups=function(t){return this.setHighlighted(!1),this.setLoading(!1),this.setActive(!1),this.groups=t,this._render(),t},i.prototype.setHighlighted=function(t){return null==t&&(t=!1),t?(t instanceof l||(t=this.dataProvider.getItem(t)),this.el.find(".select-item[data-value='"+t.value+"']").addClass("highlighted").siblings().removeClass("highlighted")):this.el.find(".select-item.highlighted").removeClass("highlighted"),this.highlighted=t,t},i.prototype.highlightNextItem=function(){var t;if(t=this.highlighted?this.el.find(".select-item[data-value='"+this.highlighted.value+"']").nextAll(".select-item:first"):this.el.find(".select-item:first"),t.length>0)return this.setHighlighted(t.data("item"))},i.prototype.highlightPrevItem=function(){var t;if(t=this.highlighted?this.el.find(".select-item[data-value='"+this.highlighted.value+"']").prevAll(".select-item:first"):this.el.find(".select-item:first"),t.length>0)return this.setHighlighted(t.data("item"))},i.prototype.setLoading=function(e){return null==e&&(e=!0),this.loading=e,e?(this.el.find(".loading").length>0||t('
').text(this.opts.locales.loading).appendTo(this.el),this.el.addClass("loading")):(this.el.removeClass("loading"),this.el.find(".loading").remove()),this.setActive(e),e},i.prototype.setActive=function(t){return null==t&&(t=!0),this.active=t,this.el.toggleClass("active",t),t?(this._scrollToHighlighted(),this.triggerHandler("show")):this.triggerHandler("hide"),t},i.prototype.setPosition=function(t){return t&&this.el.css(t),this},i}(e),r.exports=u},{"./models/data-provider.coffee":3,"./models/group.coffee":4,"./models/item.coffee":5}],"simple-select":[function(i,r,n){var o,s,l,u,p,a,h,c,d=function(t,e){function i(){this.constructor=t}for(var r in e)f.call(e,r)&&(t[r]=e[r]);return i.prototype=e.prototype,t.prototype=new i,t.__super__=e.prototype,t},f={}.hasOwnProperty;o=i("./models/data-provider.coffee"),s=i("./models/group.coffee"),p=i("./models/item.coffee"),l=i("./html-select.coffee"),u=i("./input.coffee"),a=i("./multiple-input.coffee"),h=i("./popover.coffee"),c=function(e){function i(){return i.__super__.constructor.apply(this,arguments)}return d(i,e),i.prototype.opts={el:null,remote:!1,cls:"",onItemRender:null,placeholder:"",allowInput:!1,noWrap:!1,locales:null},i.locales={loading:"Loading...",noResults:"No results found"},i._tpl='
',i.prototype._init=function(){var e,r,n,s;if(this.el=t(this.opts.el),!(this.el.length>0))throw new Error("simple select: option el is required");if(null!=(s=this.el.data("simpleSelect"))&&s.destroy(),this.locales=t.extend({},i.locales,this.opts.locales),this.multiple=this.el.is("[multiple]"),this._render(),this.dataProvider=new o({remote:this.opts.remote,selectEl:this.el}),this.htmlSelect=new l({el:this.el}),n=this.opts.placeholder?this.opts.placeholder:(e=this.htmlSelect.getBlankOption())?e.text():"",this.multiple?(this.input=new a({el:this.wrapper.find(".input"),placeholder:n,selected:this.htmlSelect.getValue()}),r=this.dataProvider.excludeItems(this.input.selected)):(this.input=new u({el:this.wrapper.find(".input"),placeholder:n,noWrap:this.opts.noWrap,selected:this.htmlSelect.getValue()}),r=this.dataProvider.groups),this.popover=new h({el:this.wrapper.find(".popover"),groups:r,onItemRender:this.opts.onItemRender,locales:this.locales}),this._bind(),this.el.prop("disabled"))return this.disable()},i.prototype._render=function(){return this.el.hide().data("simpleSelect",this),this.wrapper=t(i._tpl).data("simpleSelect",this).addClass(this.opts.cls).insertBefore(this.el)},i.prototype._bind=function(){return this.dataProvider.on("filter",function(t){return function(e,i,r){return t.multiple&&t.input.selected&&(i=t.dataProvider.excludeItems(t.input.selected,i)),t.popover.setGroups(i),t.popover.setActive(!(t.dataProvider.remote&&!r))}}(this)),this.dataProvider.on("beforeFetch",function(t){return function(e){return t.popover.setLoading(!0)}}(this)).on("fetch",function(t){return function(e){return t.popover.setLoading(!1)}}(this)),this.popover.on("itemClick",function(t){return function(e,i,r){return t.selectItem(r)}}(this)),this.popover.on("show",function(t){return function(e){return t._setPopoverPosition(),!t.multiple&&t.input.selected?t.popover.setHighlighted(t.input.selected):t.popover.highlightNextItem()}}(this)),this.input.on("itemClick",function(t){return function(e,i,r){return t.unselectItem(r)}}(this)),this.input.on("clearClick",function(t){return function(e){return t.clear()}}(this)),this.input.on("expandClick",function(t){return function(e){return t.popover.setActive(!0)}}(this)),this.input.on("arrowPress",function(t){return function(e,i){if(t.popover.active)return"up"===i?t.popover.highlightPrevItem():t.popover.highlightNextItem()}}(this)),this.input.on("enterPress",function(t){return function(e){return t.popover.active?(t.popover.highlighted?t.selectItem(t.popover.highlighted):t.multiple||t._setUserInput(),t.popover.setActive(!1)):t.el.closest("form").submit()}}(this)),this.input.on("change",function(t){return function(e,i){return t.multiple||t._syncValue(),t.dataProvider.filter(i),t._setPopoverPosition()}}(this)),this.input.on("focus",function(t){return function(e){if(!t.dataProvider.remote||t.input.getValue()&&!t.input.selected)return t.popover.setActive(!0)}}(this)),this.input.on("blur",function(t){return function(e){var i,r;return t.multiple||t.input.selected||(r=t.input.getValue(),(i=t.dataProvider.getItemByName(r))?t.selectItem(i):t._setUserInput(r)),t.popover.setActive(!1)}}(this))},i.prototype._setUserInput=function(t){if(null==t&&(t=this.input.getValue()),this.opts.allowInput&&!this.multiple)return this.wrapper.siblings(this.opts.allowInput).val(t)},i.prototype._setPopoverPosition=function(){return this.popover.setPosition({top:this.input.el.outerHeight()+2,left:0})},i.prototype._syncValue=function(){var e,i,r,n;return r=this.multiple?this.input.selected||[]:this.input.selected?[this.input.selected]:[],e=this.htmlSelect.getValue()||[],t.isArray(e)||(e=[e]),this.dataProvider.remote&&(i=new s({items:r}),this.htmlSelect.setGroups([i])),n=r.map(function(t){return t.value}),r.length>0?this.htmlSelect.setValue(n):this.htmlSelect.setValue(""),e.join(",")!==n.join(",")&&this.triggerHandler("change",[this.input.selected]),r},i.prototype.selectItem=function(t){if(t instanceof p||(t=this.dataProvider.getItem(t)),t)return this.multiple?this.input.addSelected(t):this.input.setSelected(t),this.popover.setActive(!1),this.opts.remote?this.popover.setGroups([]):this.multiple||(this.popover.setGroups(this.dataProvider.getGroups()),this.popover.setHighlighted(t)),this._setUserInput(""),this._syncValue(),t},i.prototype.unselectItem=function(t){if(this.multiple&&(t instanceof p||(t=this.dataProvider.getItem(t)),t))return this.input.removeSelected(t),this._syncValue(),t},i.prototype.clear=function(){return this.input.clear(),this.popover.setActive(!1),this._setUserInput(""),this},i.prototype.focus=function(){return this.input.focus()},i.prototype.blur=function(){return this.input.blur()},i.prototype.disable=function(){return this.input.setDisabled(!0),this.htmlSelect.setDisabled(!0),this.wrapper.addClass("disabled"),this},i.prototype.enable=function(){return this.input.setDisabled(!1),this.htmlSelect.setDisabled(!1),this.wrapper.removeClass("disabled"),this},i.prototype.destroy=function(){return this.el.removeData("simpleSelect").insertAfter(this.wrapper).show(),this.wrapper.remove(),this},i}(e),r.exports=c},{"./html-select.coffee":1,"./input.coffee":2,"./models/data-provider.coffee":3,"./models/group.coffee":4,"./models/item.coffee":5,"./multiple-input.coffee":6,"./popover.coffee":7}]},{},[]);return i("simple-select")});
\ No newline at end of file
diff --git a/gulpfile.coffee b/gulpfile.coffee
new file mode 100644
index 0000000..84c576e
--- /dev/null
+++ b/gulpfile.coffee
@@ -0,0 +1,18 @@
+gulp = require 'gulp'
+compile = require './build/compile.coffee'
+test = require './build/test.coffee'
+publish = require './build/publish.coffee'
+coffeelint = require './build/helpers/coffeelint.coffee'
+
+lint = ->
+ gulp.src 'build/**/*.coffee'
+ .pipe coffeelint()
+
+gulp.task 'default', gulp.series lint, compile, test, (done) ->
+ gulp.watch 'build/**/*.coffee', lint
+
+ gulp.watch 'src/**/*.coffee', gulp.series compile.coffee, test
+ gulp.watch 'styles/**/*.scss', compile.sass
+ gulp.watch 'test/**/*.coffee', test
+
+ done()
diff --git a/karma.coffee b/karma.coffee
new file mode 100644
index 0000000..b9fdc72
--- /dev/null
+++ b/karma.coffee
@@ -0,0 +1,96 @@
+module.exports = (config) ->
+ config.set
+
+ # base path that will be used to resolve all patterns (eg. files, exclude)
+ basePath: ''
+
+
+ # frameworks to use
+ # available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+ frameworks: ['coffee-coverage', 'browserify', 'mocha', 'chai', 'sinon']
+
+
+ # list of files / patterns to load in the browser
+ files: [
+ 'node_modules/jquery/dist/jquery.js'
+ 'node_modules/simple-module/lib/module.js'
+ 'test/coverage-init.js'
+ 'src/simple-select.coffee'
+ 'test/**/*.coffee'
+ ]
+
+
+ # list of files to exclude
+ exclude: [
+ ]
+
+
+ # preprocess matching files before serving them to the browser
+ # available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+ preprocessors:
+ 'src/simple-select.coffee': ['browserify']
+ 'test/**/*.coffee': ['browserify']
+
+
+ browserify:
+ transform: [['browserify-coffee-coverage', {noInit: true, instrumentor: 'istanbul'}]]
+ extensions: ['.js', '.coffee']
+
+
+ coffeeCoverage:
+ framework:
+ initAllSources: true
+ sourcesBasePath: 'src'
+ dest: 'test/coverage-init.js'
+ instrumentor: 'istanbul'
+
+
+ coverageReporter:
+ dir: 'coverage'
+ subdir: '.'
+ reporters: [
+ { type: 'lcovonly' }
+ { type: 'text-summary' }
+ ]
+
+
+ # test results reporter to use
+ # possible values: 'dots', 'progress'
+ # available reporters: https://npmjs.org/browse/keyword/karma-reporter
+ reporters: ['coverage', 'mocha']
+
+
+ # web server port
+ port: 9876
+
+
+ # enable / disable colors in the output (reporters and logs)
+ colors: true
+
+
+ # level of logging
+ # possible values:
+ # - config.LOG_DISABLE
+ # - config.LOG_ERROR
+ # - config.LOG_WARN
+ # - config.LOG_INFO
+ # - config.LOG_DEBUG
+ logLevel: config.LOG_INFO
+
+
+ # enable / disable watching file and executing tests whenever any file changes
+ autoWatch: false
+
+
+ # start these browsers
+ # available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+ browsers: ['PhantomJS']
+
+
+ # Continuous Integration mode
+ # if true, Karma captures browsers, runs the tests and exits
+ singleRun: true
+
+ # Concurrency level
+ # how many browser should be started simultaneous
+ concurrency: Infinity
diff --git a/lib/select.js b/lib/select.js
deleted file mode 100644
index fea1def..0000000
--- a/lib/select.js
+++ /dev/null
@@ -1,549 +0,0 @@
-(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module unless amdModuleId is set
- define('simple-select', ["jquery","simple-module"], function (a0,b1) {
- return (root['select'] = factory(a0,b1));
- });
- } else if (typeof exports === 'object') {
- // Node. Does not work with strict CommonJS, but
- // only CommonJS-like environments that support module.exports,
- // like Node.
- module.exports = factory(require("jquery"),require("simple-module"));
- } else {
- root.simple = root.simple || {};
- root.simple['select'] = factory(jQuery,SimpleModule);
- }
-}(this, function ($, SimpleModule) {
-
-var Select, select,
- extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
- hasProp = {}.hasOwnProperty;
-
-Select = (function(superClass) {
- extend(Select, superClass);
-
- function Select() {
- return Select.__super__.constructor.apply(this, arguments);
- }
-
- Select.prototype.opts = {
- el: null,
- cls: "",
- onItemRender: $.noop,
- placeholder: "",
- allowInput: false,
- multiline: true
- };
-
- Select.i18n = {
- "zh-CN": {
- all_options: "所有选项",
- clear_selection: "清除选择",
- loading: "加载中..."
- },
- "en": {
- all_options: "All options",
- clear_selection: "Clear Selection",
- loading: "Loading..."
- }
- };
-
- Select._tpl = {
- textarea: "
",
- input: "
",
- item: "
",
- group: "
\n
"
- };
-
- Select.prototype._init = function() {
- var ref;
- if (!this.opts.el) {
- throw "simple select: option el is required";
- return;
- }
- if ((ref = this.opts.el.data("select")) != null) {
- ref.destroy();
- }
- this._render();
- this._bind();
- return this.autoresizeInput();
- };
-
- Select.prototype._render = function() {
- var inputTpl;
- Select._tpl.select = "
\n
\n ▾\n \n
\n ✕\n \n
\n
" + (this._t('loading')) + "
\n
\n
";
- this.el = $(this.opts.el).hide();
- this.el.data("select", this);
- this.select = $(Select._tpl.select).data("select", this).addClass(this.opts.cls).insertBefore(this.el);
- if (this.opts.multiline) {
- this.select.addClass('multiline');
- inputTpl = Select._tpl.textarea;
- } else {
- inputTpl = Select._tpl.input;
- }
- this.input = $(inputTpl).attr("placeholder", this.opts.placeholder || this.el.data('placeholder') || "").prependTo(this.select);
- this.list = this.select.find(".select-list");
- this.requireSelect = true;
- this._setGroupsItems();
- this.generateList();
- return this.select.toggleClass('require-select', this.requireSelect);
- };
-
- Select.prototype._setGroupsItems = function() {
- this.groups = false;
- return this.items = this.el.find("option").map((function(_this) {
- return function(i, option) {
- var $group, $option, groupLabel, item;
- $option = $(option);
- $group = $option.parent('optgroup');
- item = _this._item($option);
- if ($group.length !== 0) {
- if (_this.groups === false) {
- _this.groups = {};
- }
- groupLabel = $group.attr('label');
- if (!$.isArray(_this.groups[groupLabel])) {
- _this.groups[groupLabel] = [];
- }
- _this.groups[groupLabel].push(item);
- }
- return item;
- };
- })(this)).get();
- };
-
- Select.prototype._item = function($option) {
- var label, value;
- value = $option.attr('value');
- label = $option.text().trim();
- if (!value) {
- this.requireSelect = false;
- return;
- }
- return $.extend({
- label: label,
- _value: value
- }, $option.data());
- };
-
- Select.prototype._expand = function(expand) {
- if (expand === false) {
- this.input.removeClass("expanded");
- return this.list.hide();
- } else {
- this.input.addClass("expanded");
- if (this.items.length > 0) {
- this.list.show();
- }
- this.list.css("top", this.input.outerHeight() + 4);
- if (this._selectedIndex > -1) {
- return this._scrollToSelected();
- }
- }
- };
-
- Select.prototype._scrollToSelected = function() {
- var $selectedEl;
- if (this._selectedIndex < 0) {
- return;
- }
- $selectedEl = this.list.find(".select-item").eq(this._selectedIndex);
- return this.list.scrollTop($selectedEl.position().top);
- };
-
- Select.prototype._bind = function() {
- this.select.find(".link-clear").on("mousedown", (function(_this) {
- return function(e) {
- _this.clearSelection();
- return false;
- };
- })(this));
- this.select.find(".link-expand").on("mousedown", (function(_this) {
- return function(e) {
- _this._expand(!_this.input.hasClass("expanded"));
- if (!_this._focused) {
- _this.input.focus();
- }
- return false;
- };
- })(this));
- this.list.on("mousedown", (function(_this) {
- return function(e) {
- if (window.navigator.userAgent.toLowerCase().indexOf('msie') > -1) {
- _this._scrollMousedown = true;
- setTimeout(function() {
- return _this.input.focus();
- }, 0);
- }
- return false;
- };
- })(this)).on("mousedown", ".select-item", (function(_this) {
- return function(e) {
- var index;
- index = _this.list.find(".select-item").index($(e.currentTarget));
- _this.selectItem(index);
- _this.input.blur();
- return false;
- };
- })(this));
- this.input.on("keydown.select", (function(_this) {
- return function(e) {
- return _this._keydown(e);
- };
- })(this)).on("keyup.select", (function(_this) {
- return function(e) {
- return _this._keyup(e);
- };
- })(this)).on("blur.select", (function(_this) {
- return function(e) {
- return _this._blur(e);
- };
- })(this)).on("focus.select", (function(_this) {
- return function(e) {
- return _this._focus(e);
- };
- })(this));
- return this.select.on("mousedown", (function(_this) {
- return function(e) {
- return _this.input.focus();
- };
- })(this));
- };
-
- Select.prototype._keydown = function(e) {
- var $itemEls, $nextEl, $prevEl, $selectedEl, index;
- if (!(this.items && this.items.length)) {
- return;
- }
- if (this.triggerHandler(e) === false) {
- return;
- }
- if (e.which === 40 || e.which === 38) {
- if (!this.input.hasClass("expanded")) {
- this._expand();
- $itemEls = this.list.find(".select-item").show();
- if (this._selectedIndex < 0) {
- $itemEls.first().addClass("selected");
- }
- } else {
- $selectedEl = this.list.find(".select-item.selected");
- if (!$selectedEl.length) {
- this.list.find(".select-item:first").addClass("selected");
- return;
- }
- if (e.which === 38) {
- $prevEl = $selectedEl.prevAll(".select-item:visible:first");
- if ($prevEl.length) {
- $selectedEl.removeClass("selected");
- $prevEl.addClass("selected");
- }
- } else if (e.which === 40) {
- $nextEl = $selectedEl.nextAll(".select-item:visible:first");
- if ($nextEl.length) {
- $selectedEl.removeClass("selected");
- $nextEl.addClass("selected");
- }
- }
- }
- } else if (e.which === 13) {
- e.preventDefault();
- if (this.input.hasClass("expanded")) {
- $selectedEl = this.list.find(".select-item.selected");
- if ($selectedEl.length) {
- index = this.list.find(".select-item").index($selectedEl);
- this.selectItem(index);
- return false;
- }
- } else if (this._selectedIndex > -1) {
- this.selectItem(this._selectedIndex);
- }
- if (this.opts.allowInput) {
- this.input.blur();
- return false;
- }
- this.clearSelection();
- return false;
- } else if (e.which === 27) {
- e.preventDefault();
- this.input.blur();
- } else if (e.which === 8) {
- if (this.select.hasClass("selected")) {
- this.clearSelection();
- }
- if (!this.input.hasClass("expanded")) {
- this._expand();
- }
- }
- return this.autoresizeInput();
- };
-
- Select.prototype._keyup = function(e) {
- var $itemEls;
- if ($.inArray(e.which, [13, 40, 38, 9, 27]) > -1) {
- return false;
- }
- this.autoresizeInput();
- if (this._keydownTimer) {
- clearTimeout(this._keydownTimer);
- this._keydownTimer = null;
- }
- $itemEls = this.list.find(".select-item");
- return this._keydownTimer = setTimeout((function(_this) {
- return function() {
- var re, results, value;
- if (!_this.input.hasClass("expanded")) {
- _this._expand();
- }
- if (_this.select.hasClass("selected")) {
- _this.select.removeClass("selected");
- }
- value = $.trim(_this.input.val());
- if (!value) {
- if (_this.items.length > 0) {
- _this.list.show();
- }
- $itemEls.show().removeClass("selected");
- return;
- }
- try {
- re = new RegExp("(|\\s)" + value, "i");
- } catch (_error) {
- e = _error;
- re = new RegExp("", "i");
- }
- results = $itemEls.hide().removeClass("selected").filter(function() {
- return re.test($(this).data("key"));
- });
- if (results.length) {
- if (_this.items.length > 0) {
- _this.list.show();
- }
- return results.show().first().addClass("selected");
- } else {
- return _this.list.hide();
- }
- };
- })(this), 0);
- };
-
- Select.prototype._blur = function(e) {
- var matchIdx, value;
- if (this._scrollMousedown) {
- this._scrollMousedown = false;
- return false;
- }
- this.input.removeClass("expanded error");
- this.list.hide().find(".select-item").show().removeClass("selected");
- value = $.trim(this.input.val());
- if (!this.select.hasClass("selected")) {
- if (this.opts.allowInput) {
- this.el.val('');
- this.trigger('select', [
- {
- label: value,
- _value: -1
- }
- ]);
- } else if (value) {
- matchIdx = -1;
- $.each(this.items, function(i, item) {
- if (item.label === value) {
- matchIdx = i;
- return false;
- }
- });
- if (matchIdx >= 0) {
- this.selectItem(matchIdx);
- } else {
- this.selectItem(Math.max(this._selectedIndex || -1, 0));
- }
- } else if (this.requireSelect && this.items.length > 0) {
- this.selectItem(0);
- } else {
- this.el.val('');
- }
- }
- return this._focused = false;
- };
-
- Select.prototype._focus = function(e) {
- this._expand();
- if (this._selectedIndex > -1) {
- this.list.find(".select-item").eq(this._selectedIndex).addClass("selected");
- }
- setTimeout((function(_this) {
- return function() {
- return _this.input.select();
- };
- })(this), 0);
- return this._focused = true;
- };
-
- Select.prototype.generateList = function() {
- var $itemEl, idx, it, item, j, k, len, len1, ref, ref1, results1;
- this.list.empty();
- if (this.groups) {
- $.each(this.groups, (function(_this) {
- return function(groupLabel, items) {
- var $groupEl, $itemEl, item, j, len, results1;
- $groupEl = $(Select._tpl.group);
- $groupEl.text(groupLabel);
- _this.list.append($groupEl);
- results1 = [];
- for (j = 0, len = items.length; j < len; j++) {
- item = items[j];
- $itemEl = _this._itemEl(item);
- _this.list.append($itemEl);
- if ($.isFunction(_this.opts.onItemRender)) {
- results1.push(_this.opts.onItemRender.call(_this, $itemEl, item));
- } else {
- results1.push(void 0);
- }
- }
- return results1;
- };
- })(this));
- } else {
- ref = this.items;
- for (j = 0, len = ref.length; j < len; j++) {
- item = ref[j];
- $itemEl = this._itemEl(item);
- this.list.append($itemEl);
- if ($.isFunction(this.opts.onItemRender)) {
- this.opts.onItemRender.call(this, $itemEl, item);
- }
- }
- }
- ref1 = this.items;
- results1 = [];
- for (idx = k = 0, len1 = ref1.length; k < len1; idx = ++k) {
- it = ref1[idx];
- if (it._value === this.el.val()) {
- this.selectItem(idx);
- break;
- } else {
- results1.push(void 0);
- }
- }
- return results1;
- };
-
- Select.prototype._itemEl = function(item) {
- var $itemEl;
- $itemEl = $(Select._tpl.item).data(item);
- $itemEl.find(".label span").text(item.label);
- $itemEl.find(".hint").text(item.hint);
- return $itemEl;
- };
-
- Select.prototype.setItems = function(items, requireSelect) {
- var item, j, len;
- if (requireSelect == null) {
- requireSelect = true;
- }
- this.items = [];
- this.clearSelection();
- this.list.empty();
- this.el.empty();
- this.requireSelect = requireSelect;
- this.select.toggleClass('require-select', this.requireSelect);
- if (!this.requireSelect) {
- this.el.prepend('
');
- }
- if ($.isArray(items) && items.length > 0) {
- for (j = 0, len = items.length; j < len; j++) {
- item = items[j];
- this.el.append("
");
- }
- this._setGroupsItems();
- this.generateList();
- }
- if ($.type(items) === 'object') {
- $.each(items, (function(_this) {
- return function(groupLabel, items) {
- var $group, k, len1;
- $group = $("
");
- for (k = 0, len1 = items.length; k < len1; k++) {
- item = items[k];
- $group.append("
");
- }
- return _this.el.append($group);
- };
- })(this));
- this._setGroupsItems();
- return this.generateList();
- }
- };
-
- Select.prototype.selectItem = function(index) {
- var item;
- if (!this.items) {
- return;
- }
- if ($.isNumeric(index)) {
- if (index < 0) {
- return;
- }
- item = this.items[index];
- this.select.addClass("selected");
- this.input.val(item.label).removeClass("expanded error");
- this.list.hide().find(".select-item").eq(index).addClass("selected");
- this._selectedIndex = index;
- this.el.val(item._value);
- this.trigger("select", [item]);
- this.autoresizeInput();
- }
- if (this._selectedIndex > -1) {
- return this.items[this._selectedIndex];
- }
- };
-
- Select.prototype.clearSelection = function() {
- this.input.val("").removeClass("expanded error");
- this.select.removeClass("selected");
- this.list.hide().find(".select-item").show().removeClass("selected");
- this._selectedIndex = -1;
- this.el.val('');
- this.trigger("clear");
- return this.autoresizeInput();
- };
-
- Select.prototype.autoresizeInput = function() {
- if (!this.opts.multiline) {
- return;
- }
- return setTimeout((function(_this) {
- return function() {
- _this.input.css("height", 0);
- return _this.input.css("height", parseInt(_this.input.get(0).scrollHeight) + parseInt(_this.input.css("border-top-width")) + parseInt(_this.input.css("border-bottom-width")));
- };
- })(this), 0);
- };
-
- Select.prototype.disable = function() {
- this.input.prop("disabled", true);
- return this.select.find(".link-expand, .link-clear").hide();
- };
-
- Select.prototype.enable = function() {
- this.input.prop("disabled", false);
- return this.select.find(".link-expand, .link-clear").attr("style", "");
- };
-
- Select.prototype.destroy = function() {
- this.select.remove();
- this.el.removeData('select');
- return this.el.show();
- };
-
- return Select;
-
-})(SimpleModule);
-
-select = function(opts) {
- return new Select(opts);
-};
-
-return select;
-
-}));
diff --git a/package.json b/package.json
index d306f78..2e19542 100644
--- a/package.json
+++ b/package.json
@@ -1,28 +1,70 @@
{
"name": "simple-select",
- "version": "2.0.14",
- "description": "a simple select plugin based on Simple Module",
- "main": "lib/select.js",
+ "githubOwner": "mycolorway",
+ "version": "2.1.0",
+ "description": "Autocomplete select component",
+ "homepage": "http://mycolorway.github.io/simple-select",
"repository": {
"type": "git",
- "url": "git@github.com:mycolorway/simple-select.git"
+ "url": "https://github.com/mycolorway/simple-select.git"
},
- "author": "kshift",
+ "author": "farthinker",
"license": "MIT",
"bugs": {
"url": "https://github.com/mycolorway/simple-select/issues"
},
- "homepage": "https://github.com/mycolorway/simple-select",
+ "main": "dist/simple-select.js",
+ "scripts": {
+ "start": "gulp",
+ "test": "gulp test"
+ },
+ "umd": {
+ "name": "SimpleSelect",
+ "dependencies": {
+ "cjs": [
+ "jquery",
+ "simple-module"
+ ],
+ "global": [
+ "jQuery",
+ "SimpleModule"
+ ],
+ "params": [
+ "$",
+ "SimpleModule"
+ ]
+ }
+ },
"dependencies": {
- "jquery": "2.x",
- "simple-module": "~2.0.5"
+ "jquery": "~2.2.4",
+ "simple-module": "~2.0.6"
},
"devDependencies": {
- "grunt": "0.x",
- "grunt-contrib-watch": "0.x",
- "grunt-contrib-coffee": "0.x",
- "grunt-contrib-sass": "0.x",
- "grunt-contrib-jasmine": "0.x",
- "grunt-umd": "2.x"
+ "browserify": "^13.0.0",
+ "browserify-coffee-coverage": "^1.1.1",
+ "chai": "^3.5.0",
+ "coffee-script": "^1.10.0",
+ "coffeelint": "^1.15.0",
+ "coveralls": "^2.11.8",
+ "gulp": "github:gulpjs/gulp#4.0",
+ "gulp-util": "^3.0.7",
+ "istanbul": "^0.4.2",
+ "karma": "^1.1.1",
+ "karma-browserify": "^5.0.5",
+ "karma-chai": "^0.1.0",
+ "karma-coffee-coverage": "^1.1.2",
+ "karma-coverage": "^1.0.0",
+ "karma-mocha": "^1.0.1",
+ "karma-mocha-reporter": "^2.0.4",
+ "karma-phantomjs-launcher": "^1.0.0",
+ "karma-sinon": "^1.0.5",
+ "lodash": "^4.13.1",
+ "mocha": "^2.5.3",
+ "node-sass": "^3.8.0",
+ "phantomjs-prebuilt": "^2.1.7",
+ "sinon": "^1.17.5",
+ "through2": "^2.0.1",
+ "uglify-js": "^2.6.2",
+ "watchify": "^3.7.0"
}
}
diff --git a/spec/select-spec.coffee b/spec/select-spec.coffee
deleted file mode 100644
index 6bc023b..0000000
--- a/spec/select-spec.coffee
+++ /dev/null
@@ -1,181 +0,0 @@
-selectEl = null
-
-beforeEach ->
- selectEl = $("""
-
- """)
-
-afterEach ->
- $(".simple-select").each () ->
- $(@).data("select").destroy()
- $("select").remove()
-
-
-describe 'Simple Select', ->
-
- it 'should inherit from SimpleModule', ->
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
-
- expect(select instanceof SimpleModule).toBe(true)
-
- it "should see select if everything is ok", ->
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
-
- expect($("body .simple-select").length).toBe(1)
-
- it "should see throw error if no content", ->
- expect(simple.select).toThrow()
-
- it "should have three items if everything is ok", ->
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
-
- expect($("body .simple-select .select-item").length).toBe(3)
-
- it "should see one item if type some content", (done) ->
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
-
- $(".select-result").val("John").trigger("keyup")
- setTimeout ->
- target = $("body .simple-select .select-item:visible")
- expect(target.length and target.hasClass("selected")).toBe(true)
- done()
- , 10
-
- it "should set original select form element value according to select item", ->
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
-
- select.selectItem(1)
- expect(select.el.val()).toBe('1')
- select.clearSelection()
- expect(select.el.val()).toBe(null)
-
- it "should see 'select-list' if click 'link-expand'", ->
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
-
- $(".link-expand").trigger("mousedown")
- expect($("body .simple-select .select-list:visible").length).toBe(1)
-
- it "should have value if select item", ->
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
-
- $(".select-item:first").trigger("mousedown")
- expect($(".select-result").val().length).toBeGreaterThan(0)
-
- it "should remove selected' if click 'link-clear'", ->
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
-
- $(".select-item:first").trigger("mousedown")
- $(".link-clear").trigger("mousedown")
- expect($(".select-result").val().length).toBe(0)
-
- it "should work if use setItems to set items", ->
- $("""
-
- """).appendTo("body")
- select = simple.select
- el: $("#select-two")
-
- select.setItems [
- {
- label: "张三"
- key: "zhangsan zs 张三"
- id: "1"
- }
- {
- label: "李四"
- key: "lisi ls 李四"
- id: "2"
- }
- {
- label: "王麻子"
- key: "wangmazi wmz 王麻子"
- id: "3"
- }
- ]
-
- expect($("body .simple-select .select-item").length).toBe(3)
-
- it 'should not show option without value', ->
- selectEl.append('
')
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
-
- $(".link-expand").trigger("mousedown")
- expect($("body .simple-select .select-item:visible").length).toBe(3)
-
- it 'should always select default value if all options with value', ->
- selectEl.find('option[value=2]').prop('selected', true)
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
-
- expect(select.el.val()).toBe('2')
-
- select.clearSelection()
- select.input.blur()
-
- expect(select.el.val()).toBe('0')
-
- it 'should always select default value if one option without value', ->
- selectEl.append('
')
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
-
- select.clearSelection()
- select.input.blur()
-
- expect(select.requireSelect).toBe(false)
- expect(select.el.val()).toBe('')
-
- it "should keep reference in el", ->
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
- expect(selectEl.data('select')).toBe(select)
-
- it "should destroy reference in el after destroy", ->
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
- select.destroy()
- expect(selectEl.data('select')).not.toBe(select)
-
- it "should set placeholder by setting data-placeholder", ->
- hint = "some hint text"
- selectEl.data("placeholder", hint)
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
- expect(select.input.attr("placeholder")).toBe(hint)
-
- it "should override data-placeholder by setting placeholder in opt", ->
- hint = "some hint text"
- anotherHint = "another hint text"
- selectEl.data("placeholder", hint)
- selectEl.appendTo("body")
- select = simple.select
- el: $("#select-one")
- placeholder: anotherHint
- expect(select.input.attr("placeholder")).toBe(anotherHint)
diff --git a/spec/select-spec.js b/spec/select-spec.js
deleted file mode 100644
index ec51bb3..0000000
--- a/spec/select-spec.js
+++ /dev/null
@@ -1,196 +0,0 @@
-(function() {
- var selectEl;
-
- selectEl = null;
-
- beforeEach(function() {
- return selectEl = $("
");
- });
-
- afterEach(function() {
- $(".simple-select").each(function() {
- return $(this).data("select").destroy();
- });
- return $("select").remove();
- });
-
- describe('Simple Select', function() {
- it('should inherit from SimpleModule', function() {
- var select;
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- return expect(select instanceof SimpleModule).toBe(true);
- });
- it("should see select if everything is ok", function() {
- var select;
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- return expect($("body .simple-select").length).toBe(1);
- });
- it("should see throw error if no content", function() {
- return expect(simple.select).toThrow();
- });
- it("should have three items if everything is ok", function() {
- var select;
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- return expect($("body .simple-select .select-item").length).toBe(3);
- });
- it("should see one item if type some content", function(done) {
- var select;
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- $(".select-result").val("John").trigger("keyup");
- return setTimeout(function() {
- var target;
- target = $("body .simple-select .select-item:visible");
- expect(target.length && target.hasClass("selected")).toBe(true);
- return done();
- }, 10);
- });
- it("should set original select form element value according to select item", function() {
- var select;
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- select.selectItem(1);
- expect(select.el.val()).toBe('1');
- select.clearSelection();
- return expect(select.el.val()).toBe(null);
- });
- it("should see 'select-list' if click 'link-expand'", function() {
- var select;
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- $(".link-expand").trigger("mousedown");
- return expect($("body .simple-select .select-list:visible").length).toBe(1);
- });
- it("should have value if select item", function() {
- var select;
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- $(".select-item:first").trigger("mousedown");
- return expect($(".select-result").val().length).toBeGreaterThan(0);
- });
- it("should remove selected' if click 'link-clear'", function() {
- var select;
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- $(".select-item:first").trigger("mousedown");
- $(".link-clear").trigger("mousedown");
- return expect($(".select-result").val().length).toBe(0);
- });
- it("should work if use setItems to set items", function() {
- var select;
- $("
").appendTo("body");
- select = simple.select({
- el: $("#select-two")
- });
- select.setItems([
- {
- label: "张三",
- key: "zhangsan zs 张三",
- id: "1"
- }, {
- label: "李四",
- key: "lisi ls 李四",
- id: "2"
- }, {
- label: "王麻子",
- key: "wangmazi wmz 王麻子",
- id: "3"
- }
- ]);
- return expect($("body .simple-select .select-item").length).toBe(3);
- });
- it('should not show option without value', function() {
- var select;
- selectEl.append('
');
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- $(".link-expand").trigger("mousedown");
- return expect($("body .simple-select .select-item:visible").length).toBe(3);
- });
- it('should always select default value if all options with value', function() {
- var select;
- selectEl.find('option[value=2]').prop('selected', true);
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- expect(select.el.val()).toBe('2');
- select.clearSelection();
- select.input.blur();
- return expect(select.el.val()).toBe('0');
- });
- it('should always select default value if one option without value', function() {
- var select;
- selectEl.append('
');
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- select.clearSelection();
- select.input.blur();
- expect(select.requireSelect).toBe(false);
- return expect(select.el.val()).toBe('');
- });
- it("should keep reference in el", function() {
- var select;
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- return expect(selectEl.data('select')).toBe(select);
- });
- it("should destroy reference in el after destroy", function() {
- var select;
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- select.destroy();
- return expect(selectEl.data('select')).not.toBe(select);
- });
- it("should set placeholder by setting data-placeholder", function() {
- var hint, select;
- hint = "some hint text";
- selectEl.data("placeholder", hint);
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one")
- });
- return expect(select.input.attr("placeholder")).toBe(hint);
- });
- return it("should override data-placeholder by setting placeholder in opt", function() {
- var anotherHint, hint, select;
- hint = "some hint text";
- anotherHint = "another hint text";
- selectEl.data("placeholder", hint);
- selectEl.appendTo("body");
- select = simple.select({
- el: $("#select-one"),
- placeholder: anotherHint
- });
- return expect(select.input.attr("placeholder")).toBe(anotherHint);
- });
- });
-
-}).call(this);
diff --git a/src/html-select.coffee b/src/html-select.coffee
new file mode 100644
index 0000000..63d75da
--- /dev/null
+++ b/src/html-select.coffee
@@ -0,0 +1,56 @@
+Group = require './models/group.coffee'
+
+class HtmlSelect extends SimpleModule
+
+ opts:
+ el: null
+ groups: null
+
+ _init: ->
+ @el = $ @opts.el
+ @groups = @opts.groups
+ @_render() if @groups
+
+ _renderOption: (item, $parent = @el) ->
+ $ '