From ae57cf64608c1775ecb32512a3f5b5dae09dfed5 Mon Sep 17 00:00:00 2001 From: Kevin Brown Date: Wed, 27 Aug 2014 11:33:33 -0400 Subject: [PATCH] More work on rendering Switched all of the divs to spans, as the container should not be a block by default. --- dist/css/select2.css | 22 +++++++++ dist/js/select2.amd.full.js | 85 ++++++++++++++++++++++++++--------- dist/js/select2.amd.js | 85 ++++++++++++++++++++++++++--------- dist/js/select2.full.js | 85 ++++++++++++++++++++++++++--------- dist/js/select2.js | 85 ++++++++++++++++++++++++++--------- src/js/select2/core.js | 36 ++++++++++----- src/js/select2/data/select.js | 29 +++++++++++- src/js/select2/dropdown.js | 6 +-- src/js/select2/selection.js | 10 +++-- src/js/select2/utils.js | 4 +- src/scss/_dropdown.scss | 10 +++++ src/scss/_single.scss | 21 +++++++++ src/scss/core.scss | 13 +++++- 13 files changed, 390 insertions(+), 101 deletions(-) create mode 100644 src/scss/_dropdown.scss create mode 100644 src/scss/_single.scss diff --git a/dist/css/select2.css b/dist/css/select2.css index 69f9ed7a..bf8d73a0 100644 --- a/dist/css/select2.css +++ b/dist/css/select2.css @@ -1,3 +1,25 @@ +.select2-container { + box-sizing: border-box; + display: inline-block; + margin: 0; + position: relative; + vertical-align: middle; } + +.select2-container .selection .single-select { + background-color: #eee; + border: 1px solid #aaa; + border-radius: 4px; + box-sizing: border-box; + cursor: pointer; + display: block; + height: 28px; } + .select2-container .selection .single-select .rendered-selection { + color: #444; + display: block; + line-height: 28px; + overflow: hidden; + text-overflow: ellipsis; } + .s2-container { margin: 0; position: relative; diff --git a/dist/js/select2.amd.full.js b/dist/js/select2.amd.full.js index d069ffd0..c322316d 100644 --- a/dist/js/select2.amd.full.js +++ b/dist/js/select2.amd.full.js @@ -34,8 +34,10 @@ define('select2/utils',[], function () { }; Observable.prototype.trigger = function (event) { + var slice = Array.prototype.slice; + if (event in this.listeners) { - this.invoke(this.listeners[event], util.shift(arguments)); + this.invoke(this.listeners[event], slice.call(arguments, 1)); } if ("*" in this.listeners) { @@ -63,7 +65,7 @@ define('select2/data/select',[ Utils.Extend(SelectAdapter, Utils.Observable); - SelectAdapter.prototype.current = function () { + SelectAdapter.prototype.current = function (callback) { var data = []; var self = this; @@ -75,7 +77,24 @@ define('select2/data/select',[ data.push(option); }); - return data; + callback(data); + }; + + SelectAdapter.prototype.query = function (params, callback) { + var data = []; + var self = this; + + this.$element.find("option").each(function () { + var $option = $(this); + + var option = self.item($option); + + if (self.matches(params, option)) { + data.push(option); + } + }); + + callback(data); }; SelectAdapter.prototype.item = function ($option) { @@ -87,6 +106,14 @@ define('select2/data/select',[ return data; }; + SelectAdapter.prototype.matches = function (params, data) { + if (data.text.indexOf(params.term) > -1) { + return true; + } + + return false; + } + return SelectAdapter; }); @@ -122,9 +149,9 @@ define('select2/dropdown',[ Dropdown.prototype.render = function () { var $dropdown = $( - '
' + - '
' + - '
' + '' + + '' + + '' ); return $dropdown; @@ -139,15 +166,17 @@ define('select2/selection',[ function Selection ($element, options) { this.$element = $element; this.options = options; + + Selection.__super__.constructor.call(this); } Utils.Extend(Selection, Utils.Observable); Selection.prototype.render = function () { var $selection = $( - '
' + - '
' + - '
' + '' + + '' + + '' ); this.$selection = $selection; @@ -158,7 +187,7 @@ define('select2/selection',[ Selection.prototype.bind = function ($container) { var self = this; - $container.on('click', function (evt) { + this.$selection.on('click', function (evt) { self.trigger("toggle", { originalEvent: evt }); @@ -216,6 +245,8 @@ define('select2/core',[ this.$element = $element; this.options = new Options(options); + Select2.__super__.constructor.call(this); + // Set up containers and adapters this.data = new this.options.dataAdapter($element, options); @@ -224,6 +255,8 @@ define('select2/core',[ $container.insertAfter(this.$element); + $container.width($element.width()); + this.selection = new this.options.selectionAdapter($element, options); var $selectionContainer = $container.find(".selection"); @@ -233,9 +266,10 @@ define('select2/core',[ this.dropdown = new this.options.dropdownAdapter($element, options); + var $dropdownContainer = $container.find(".dropdown"); var $dropdown = this.dropdown.render(); - $dropdown.insertAfter($container); + $dropdownContainer.append($dropdown); this.results = new this.options.resultsAdapter($element, options); @@ -244,26 +278,37 @@ define('select2/core',[ $resultsContainer.append($results); + // Bind events + + this.selection.bind($container); + // Set the initial state - var initialData = this.data.current(); - - this.selection.update(initialData); - var self = this; + this.data.current(function (initialData) { + self.selection.update(initialData); + }); + this.$element.on("change", function () { - self.selection.update(self.data.current()); - }) + self.data.current(function (data) { + self.selection.update(data); + }); + }); + + this.selection.on("toggle", function () { + $container.toggleClass("open"); + }); }; Utils.Extend(Select2, Utils.Observable); Select2.prototype.render = function () { var $container = $( - '
' + - '
' + - '
' + '' + + '' + + '' + + '' ); return $container; diff --git a/dist/js/select2.amd.js b/dist/js/select2.amd.js index d069ffd0..c322316d 100644 --- a/dist/js/select2.amd.js +++ b/dist/js/select2.amd.js @@ -34,8 +34,10 @@ define('select2/utils',[], function () { }; Observable.prototype.trigger = function (event) { + var slice = Array.prototype.slice; + if (event in this.listeners) { - this.invoke(this.listeners[event], util.shift(arguments)); + this.invoke(this.listeners[event], slice.call(arguments, 1)); } if ("*" in this.listeners) { @@ -63,7 +65,7 @@ define('select2/data/select',[ Utils.Extend(SelectAdapter, Utils.Observable); - SelectAdapter.prototype.current = function () { + SelectAdapter.prototype.current = function (callback) { var data = []; var self = this; @@ -75,7 +77,24 @@ define('select2/data/select',[ data.push(option); }); - return data; + callback(data); + }; + + SelectAdapter.prototype.query = function (params, callback) { + var data = []; + var self = this; + + this.$element.find("option").each(function () { + var $option = $(this); + + var option = self.item($option); + + if (self.matches(params, option)) { + data.push(option); + } + }); + + callback(data); }; SelectAdapter.prototype.item = function ($option) { @@ -87,6 +106,14 @@ define('select2/data/select',[ return data; }; + SelectAdapter.prototype.matches = function (params, data) { + if (data.text.indexOf(params.term) > -1) { + return true; + } + + return false; + } + return SelectAdapter; }); @@ -122,9 +149,9 @@ define('select2/dropdown',[ Dropdown.prototype.render = function () { var $dropdown = $( - '
' + - '
' + - '
' + '' + + '' + + '' ); return $dropdown; @@ -139,15 +166,17 @@ define('select2/selection',[ function Selection ($element, options) { this.$element = $element; this.options = options; + + Selection.__super__.constructor.call(this); } Utils.Extend(Selection, Utils.Observable); Selection.prototype.render = function () { var $selection = $( - '
' + - '
' + - '
' + '' + + '' + + '' ); this.$selection = $selection; @@ -158,7 +187,7 @@ define('select2/selection',[ Selection.prototype.bind = function ($container) { var self = this; - $container.on('click', function (evt) { + this.$selection.on('click', function (evt) { self.trigger("toggle", { originalEvent: evt }); @@ -216,6 +245,8 @@ define('select2/core',[ this.$element = $element; this.options = new Options(options); + Select2.__super__.constructor.call(this); + // Set up containers and adapters this.data = new this.options.dataAdapter($element, options); @@ -224,6 +255,8 @@ define('select2/core',[ $container.insertAfter(this.$element); + $container.width($element.width()); + this.selection = new this.options.selectionAdapter($element, options); var $selectionContainer = $container.find(".selection"); @@ -233,9 +266,10 @@ define('select2/core',[ this.dropdown = new this.options.dropdownAdapter($element, options); + var $dropdownContainer = $container.find(".dropdown"); var $dropdown = this.dropdown.render(); - $dropdown.insertAfter($container); + $dropdownContainer.append($dropdown); this.results = new this.options.resultsAdapter($element, options); @@ -244,26 +278,37 @@ define('select2/core',[ $resultsContainer.append($results); + // Bind events + + this.selection.bind($container); + // Set the initial state - var initialData = this.data.current(); - - this.selection.update(initialData); - var self = this; + this.data.current(function (initialData) { + self.selection.update(initialData); + }); + this.$element.on("change", function () { - self.selection.update(self.data.current()); - }) + self.data.current(function (data) { + self.selection.update(data); + }); + }); + + this.selection.on("toggle", function () { + $container.toggleClass("open"); + }); }; Utils.Extend(Select2, Utils.Observable); Select2.prototype.render = function () { var $container = $( - '
' + - '
' + - '
' + '' + + '' + + '' + + '' ); return $container; diff --git a/dist/js/select2.full.js b/dist/js/select2.full.js index 6091a5fc..fd43a972 100644 --- a/dist/js/select2.full.js +++ b/dist/js/select2.full.js @@ -9571,8 +9571,10 @@ define('select2/utils',[], function () { }; Observable.prototype.trigger = function (event) { + var slice = Array.prototype.slice; + if (event in this.listeners) { - this.invoke(this.listeners[event], util.shift(arguments)); + this.invoke(this.listeners[event], slice.call(arguments, 1)); } if ("*" in this.listeners) { @@ -9600,7 +9602,7 @@ define('select2/data/select',[ Utils.Extend(SelectAdapter, Utils.Observable); - SelectAdapter.prototype.current = function () { + SelectAdapter.prototype.current = function (callback) { var data = []; var self = this; @@ -9612,7 +9614,24 @@ define('select2/data/select',[ data.push(option); }); - return data; + callback(data); + }; + + SelectAdapter.prototype.query = function (params, callback) { + var data = []; + var self = this; + + this.$element.find("option").each(function () { + var $option = $(this); + + var option = self.item($option); + + if (self.matches(params, option)) { + data.push(option); + } + }); + + callback(data); }; SelectAdapter.prototype.item = function ($option) { @@ -9624,6 +9643,14 @@ define('select2/data/select',[ return data; }; + SelectAdapter.prototype.matches = function (params, data) { + if (data.text.indexOf(params.term) > -1) { + return true; + } + + return false; + } + return SelectAdapter; }); @@ -9659,9 +9686,9 @@ define('select2/dropdown',[ Dropdown.prototype.render = function () { var $dropdown = $( - '
' + - '
' + - '
' + '' + + '' + + '' ); return $dropdown; @@ -9676,15 +9703,17 @@ define('select2/selection',[ function Selection ($element, options) { this.$element = $element; this.options = options; + + Selection.__super__.constructor.call(this); } Utils.Extend(Selection, Utils.Observable); Selection.prototype.render = function () { var $selection = $( - '
' + - '
' + - '
' + '' + + '' + + '' ); this.$selection = $selection; @@ -9695,7 +9724,7 @@ define('select2/selection',[ Selection.prototype.bind = function ($container) { var self = this; - $container.on('click', function (evt) { + this.$selection.on('click', function (evt) { self.trigger("toggle", { originalEvent: evt }); @@ -9753,6 +9782,8 @@ define('select2/core',[ this.$element = $element; this.options = new Options(options); + Select2.__super__.constructor.call(this); + // Set up containers and adapters this.data = new this.options.dataAdapter($element, options); @@ -9761,6 +9792,8 @@ define('select2/core',[ $container.insertAfter(this.$element); + $container.width($element.width()); + this.selection = new this.options.selectionAdapter($element, options); var $selectionContainer = $container.find(".selection"); @@ -9770,9 +9803,10 @@ define('select2/core',[ this.dropdown = new this.options.dropdownAdapter($element, options); + var $dropdownContainer = $container.find(".dropdown"); var $dropdown = this.dropdown.render(); - $dropdown.insertAfter($container); + $dropdownContainer.append($dropdown); this.results = new this.options.resultsAdapter($element, options); @@ -9781,26 +9815,37 @@ define('select2/core',[ $resultsContainer.append($results); + // Bind events + + this.selection.bind($container); + // Set the initial state - var initialData = this.data.current(); - - this.selection.update(initialData); - var self = this; + this.data.current(function (initialData) { + self.selection.update(initialData); + }); + this.$element.on("change", function () { - self.selection.update(self.data.current()); - }) + self.data.current(function (data) { + self.selection.update(data); + }); + }); + + this.selection.on("toggle", function () { + $container.toggleClass("open"); + }); }; Utils.Extend(Select2, Utils.Observable); Select2.prototype.render = function () { var $container = $( - '
' + - '
' + - '
' + '' + + '' + + '' + + '' ); return $container; diff --git a/dist/js/select2.js b/dist/js/select2.js index de65e56a..c7badc4e 100644 --- a/dist/js/select2.js +++ b/dist/js/select2.js @@ -462,8 +462,10 @@ define('select2/utils',[], function () { }; Observable.prototype.trigger = function (event) { + var slice = Array.prototype.slice; + if (event in this.listeners) { - this.invoke(this.listeners[event], util.shift(arguments)); + this.invoke(this.listeners[event], slice.call(arguments, 1)); } if ("*" in this.listeners) { @@ -491,7 +493,7 @@ define('select2/data/select',[ Utils.Extend(SelectAdapter, Utils.Observable); - SelectAdapter.prototype.current = function () { + SelectAdapter.prototype.current = function (callback) { var data = []; var self = this; @@ -503,7 +505,24 @@ define('select2/data/select',[ data.push(option); }); - return data; + callback(data); + }; + + SelectAdapter.prototype.query = function (params, callback) { + var data = []; + var self = this; + + this.$element.find("option").each(function () { + var $option = $(this); + + var option = self.item($option); + + if (self.matches(params, option)) { + data.push(option); + } + }); + + callback(data); }; SelectAdapter.prototype.item = function ($option) { @@ -515,6 +534,14 @@ define('select2/data/select',[ return data; }; + SelectAdapter.prototype.matches = function (params, data) { + if (data.text.indexOf(params.term) > -1) { + return true; + } + + return false; + } + return SelectAdapter; }); @@ -550,9 +577,9 @@ define('select2/dropdown',[ Dropdown.prototype.render = function () { var $dropdown = $( - '
' + - '
' + - '
' + '' + + '' + + '' ); return $dropdown; @@ -567,15 +594,17 @@ define('select2/selection',[ function Selection ($element, options) { this.$element = $element; this.options = options; + + Selection.__super__.constructor.call(this); } Utils.Extend(Selection, Utils.Observable); Selection.prototype.render = function () { var $selection = $( - '
' + - '
' + - '
' + '' + + '' + + '' ); this.$selection = $selection; @@ -586,7 +615,7 @@ define('select2/selection',[ Selection.prototype.bind = function ($container) { var self = this; - $container.on('click', function (evt) { + this.$selection.on('click', function (evt) { self.trigger("toggle", { originalEvent: evt }); @@ -644,6 +673,8 @@ define('select2/core',[ this.$element = $element; this.options = new Options(options); + Select2.__super__.constructor.call(this); + // Set up containers and adapters this.data = new this.options.dataAdapter($element, options); @@ -652,6 +683,8 @@ define('select2/core',[ $container.insertAfter(this.$element); + $container.width($element.width()); + this.selection = new this.options.selectionAdapter($element, options); var $selectionContainer = $container.find(".selection"); @@ -661,9 +694,10 @@ define('select2/core',[ this.dropdown = new this.options.dropdownAdapter($element, options); + var $dropdownContainer = $container.find(".dropdown"); var $dropdown = this.dropdown.render(); - $dropdown.insertAfter($container); + $dropdownContainer.append($dropdown); this.results = new this.options.resultsAdapter($element, options); @@ -672,26 +706,37 @@ define('select2/core',[ $resultsContainer.append($results); + // Bind events + + this.selection.bind($container); + // Set the initial state - var initialData = this.data.current(); - - this.selection.update(initialData); - var self = this; + this.data.current(function (initialData) { + self.selection.update(initialData); + }); + this.$element.on("change", function () { - self.selection.update(self.data.current()); - }) + self.data.current(function (data) { + self.selection.update(data); + }); + }); + + this.selection.on("toggle", function () { + $container.toggleClass("open"); + }); }; Utils.Extend(Select2, Utils.Observable); Select2.prototype.render = function () { var $container = $( - '
' + - '
' + - '
' + '' + + '' + + '' + + '' ); return $container; diff --git a/src/js/select2/core.js b/src/js/select2/core.js index 45fc0e3f..1957c567 100644 --- a/src/js/select2/core.js +++ b/src/js/select2/core.js @@ -7,6 +7,8 @@ define([ this.$element = $element; this.options = new Options(options); + Select2.__super__.constructor.call(this); + // Set up containers and adapters this.data = new this.options.dataAdapter($element, options); @@ -15,6 +17,8 @@ define([ $container.insertAfter(this.$element); + $container.width($element.width()); + this.selection = new this.options.selectionAdapter($element, options); var $selectionContainer = $container.find(".selection"); @@ -24,9 +28,10 @@ define([ this.dropdown = new this.options.dropdownAdapter($element, options); + var $dropdownContainer = $container.find(".dropdown"); var $dropdown = this.dropdown.render(); - $dropdown.insertAfter($container); + $dropdownContainer.append($dropdown); this.results = new this.options.resultsAdapter($element, options); @@ -35,26 +40,37 @@ define([ $resultsContainer.append($results); + // Bind events + + this.selection.bind($container); + // Set the initial state - var initialData = this.data.current(); - - this.selection.update(initialData); - var self = this; + this.data.current(function (initialData) { + self.selection.update(initialData); + }); + this.$element.on("change", function () { - self.selection.update(self.data.current()); - }) + self.data.current(function (data) { + self.selection.update(data); + }); + }); + + this.selection.on("toggle", function () { + $container.toggleClass("open"); + }); }; Utils.Extend(Select2, Utils.Observable); Select2.prototype.render = function () { var $container = $( - '
' + - '
' + - '
' + '' + + '' + + '' + + '' ); return $container; diff --git a/src/js/select2/data/select.js b/src/js/select2/data/select.js index fdda9a2a..56422985 100644 --- a/src/js/select2/data/select.js +++ b/src/js/select2/data/select.js @@ -7,7 +7,7 @@ define([ Utils.Extend(SelectAdapter, Utils.Observable); - SelectAdapter.prototype.current = function () { + SelectAdapter.prototype.current = function (callback) { var data = []; var self = this; @@ -19,7 +19,24 @@ define([ data.push(option); }); - return data; + callback(data); + }; + + SelectAdapter.prototype.query = function (params, callback) { + var data = []; + var self = this; + + this.$element.find("option").each(function () { + var $option = $(this); + + var option = self.item($option); + + if (self.matches(params, option)) { + data.push(option); + } + }); + + callback(data); }; SelectAdapter.prototype.item = function ($option) { @@ -31,5 +48,13 @@ define([ return data; }; + SelectAdapter.prototype.matches = function (params, data) { + if (data.text.indexOf(params.term) > -1) { + return true; + } + + return false; + } + return SelectAdapter; }); diff --git a/src/js/select2/dropdown.js b/src/js/select2/dropdown.js index 339093f0..9897f7d1 100644 --- a/src/js/select2/dropdown.js +++ b/src/js/select2/dropdown.js @@ -9,9 +9,9 @@ define([ Dropdown.prototype.render = function () { var $dropdown = $( - '
' + - '
' + - '
' + '' + + '' + + '' ); return $dropdown; diff --git a/src/js/select2/selection.js b/src/js/select2/selection.js index f4301e05..0f8d62d5 100644 --- a/src/js/select2/selection.js +++ b/src/js/select2/selection.js @@ -4,15 +4,17 @@ define([ function Selection ($element, options) { this.$element = $element; this.options = options; + + Selection.__super__.constructor.call(this); } Utils.Extend(Selection, Utils.Observable); Selection.prototype.render = function () { var $selection = $( - '
' + - '
' + - '
' + '' + + '' + + '' ); this.$selection = $selection; @@ -23,7 +25,7 @@ define([ Selection.prototype.bind = function ($container) { var self = this; - $container.on('click', function (evt) { + this.$selection.on('click', function (evt) { self.trigger("toggle", { originalEvent: evt }); diff --git a/src/js/select2/utils.js b/src/js/select2/utils.js index 908c92e9..37e9d73b 100644 --- a/src/js/select2/utils.js +++ b/src/js/select2/utils.js @@ -34,8 +34,10 @@ define([], function () { }; Observable.prototype.trigger = function (event) { + var slice = Array.prototype.slice; + if (event in this.listeners) { - this.invoke(this.listeners[event], util.shift(arguments)); + this.invoke(this.listeners[event], slice.call(arguments, 1)); } if ("*" in this.listeners) { diff --git a/src/scss/_dropdown.scss b/src/scss/_dropdown.scss new file mode 100644 index 00000000..9e82ca6b --- /dev/null +++ b/src/scss/_dropdown.scss @@ -0,0 +1,10 @@ +.select2-container { + .dropdown { + background-color: white; + border: 1px solid #aaa; + } + + &.open .dropdown { + // + } +} diff --git a/src/scss/_single.scss b/src/scss/_single.scss new file mode 100644 index 00000000..df27dfb9 --- /dev/null +++ b/src/scss/_single.scss @@ -0,0 +1,21 @@ +.select2-container { + .selection .single-select { + background-color: #eee; + border: 1px solid #aaa; + border-radius: 4px; + box-sizing: border-box; + + cursor: pointer; + display: block; + + height: 28px; + + .rendered-selection { + color: #444; + display: block; + line-height: 28px; + overflow: hidden; + text-overflow: ellipsis; + } + } +} diff --git a/src/scss/core.scss b/src/scss/core.scss index bde8cf5c..35c27f55 100644 --- a/src/scss/core.scss +++ b/src/scss/core.scss @@ -1,3 +1,14 @@ +.select2-container { + box-sizing: border-box; + + display: inline-block; + margin: 0; + position: relative; + vertical-align: middle; +} + +@import "single"; + .s2-container { margin: 0; position: relative; @@ -93,4 +104,4 @@ .s2-hidden { display: none; -} \ No newline at end of file +}