summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--module/web/static/css/default/dashboard.less12
-rw-r--r--module/web/static/css/select2.css32
-rw-r--r--module/web/static/js/config.js2
-rw-r--r--module/web/static/js/libs/require-2.1.5.js (renamed from module/web/static/js/libs/require-2.1.2.js)96
-rw-r--r--module/web/static/js/libs/select2-3.3.1.js (renamed from module/web/static/js/libs/select2-3.2.js)601
-rw-r--r--module/web/static/js/views/filterView.js17
-rw-r--r--module/web/templates/default/base.html4
7 files changed, 487 insertions, 277 deletions
diff --git a/module/web/static/css/default/dashboard.less b/module/web/static/css/default/dashboard.less
index e2cc739c6..2a4adf0e7 100644
--- a/module/web/static/css/default/dashboard.less
+++ b/module/web/static/css/default/dashboard.less
@@ -279,6 +279,18 @@ FANCY CHECKBOXES
Actionbar
*/
+.form-search {
+ position: relative;
+
+ .dropdown-menu {
+ min-width: 100%;
+ position: absolute;
+ right: 0;
+ left: auto;
+ }
+
+}
+
li.finished > a, li.finished:hover > a {
background-color: @green;
color: @light;
diff --git a/module/web/static/css/select2.css b/module/web/static/css/select2.css
index d8b43d876..1ff2abb1b 100644
--- a/module/web/static/css/select2.css
+++ b/module/web/static/css/select2.css
@@ -1,5 +1,5 @@
/*
-Version: @@ver@@ Timestamp: @@timestamp@@
+Version: 3.3.1 Timestamp: Wed Feb 20 09:57:22 PST 2013
*/
.select2-container {
position: relative;
@@ -48,6 +48,13 @@ Version: @@ver@@ Timestamp: @@timestamp@@
-moz-background-clip: padding;
background-clip: padding-box;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+
background-color: #fff;
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.5, white));
background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 50%);
@@ -133,7 +140,6 @@ Version: @@ver@@ Timestamp: @@timestamp@@
-webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
-moz-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
- -o-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
}
@@ -148,7 +154,6 @@ Version: @@ver@@ Timestamp: @@timestamp@@
-webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
-moz-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
- -o-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
}
@@ -256,16 +261,13 @@ Version: @@ver@@ Timestamp: @@timestamp@@
-webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
-moz-box-shadow: 0 0 5px rgba(0,0,0,.3);
- -o-box-shadow: 0 0 5px rgba(0,0,0,.3);
box-shadow: 0 0 5px rgba(0,0,0,.3);
}
.select2-dropdown-open .select2-choice {
- border: 1px solid #aaa;
border-bottom-color: transparent;
-webkit-box-shadow: 0 1px 0 #fff inset;
-moz-box-shadow: 0 1px 0 #fff inset;
- -o-box-shadow: 0 1px 0 #fff inset;
box-shadow: 0 1px 0 #fff inset;
-webkit-border-bottom-left-radius: 0;
@@ -303,6 +305,7 @@ Version: @@ver@@ Timestamp: @@timestamp@@
position: relative;
overflow-x: hidden;
overflow-y: auto;
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
}
.select2-results ul.select2-result-sub {
@@ -331,6 +334,13 @@ Version: @@ver@@ Timestamp: @@timestamp@@
padding: 3px 7px 4px;
margin: 0;
cursor: pointer;
+
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
}
.select2-results .select2-highlighted {
@@ -444,7 +454,6 @@ disabled look for disabled choices in the results dropdown
-webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
-moz-box-shadow: 0 0 5px rgba(0,0,0,.3);
- -o-box-shadow: 0 0 5px rgba(0,0,0,.3);
box-shadow: 0 0 5px rgba(0,0,0,.3);
}
.select2-container-multi .select2-choices li {
@@ -458,7 +467,6 @@ disabled look for disabled choices in the results dropdown
}
.select2-container-multi .select2-choices .select2-search-field input {
- height: 15px;
padding: 5px;
margin: 1px 0;
@@ -469,7 +477,6 @@ disabled look for disabled choices in the results dropdown
border: 0;
-webkit-box-shadow: none;
-moz-box-shadow: none;
- -o-box-shadow: none;
box-shadow: none;
background: transparent !important;
}
@@ -504,6 +511,13 @@ disabled look for disabled choices in the results dropdown
-moz-background-clip: padding;
background-clip: padding-box;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+
background-color: #e4e4e4;
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0 );
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
diff --git a/module/web/static/js/config.js b/module/web/static/js/config.js
index 86704740c..474a77dc3 100644
--- a/module/web/static/js/config.js
+++ b/module/web/static/js/config.js
@@ -10,7 +10,7 @@ require.config({
transit: "libs/jquery.transit-0.9.9",
animate: "libs/jquery.animate-enhanced-0.99",
omniwindow: "libs/jquery.omniwindow",
- select2: "libs/select2-3.2",
+ select2: "libs/select2-3.3.1",
bootstrap: "libs/bootstrap-2.3",
underscore: "libs/lodash-1.0.1",
diff --git a/module/web/static/js/libs/require-2.1.2.js b/module/web/static/js/libs/require-2.1.5.js
index 0e7b81bc4..062516acd 100644
--- a/module/web/static/js/libs/require-2.1.2.js
+++ b/module/web/static/js/libs/require-2.1.5.js
@@ -1,18 +1,18 @@
/** vim: et:ts=4:sw=4:sts=4
- * @license RequireJS 2.1.2 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
+ * @license RequireJS 2.1.5 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
//Not using strict: uneven strict support in browsers, #392, and causes
//problems with requirejs.exec()/transpiler plugins that may not be strict.
/*jslint regexp: true, nomen: true, sloppy: true */
-/*global window, navigator, document, importScripts, jQuery, setTimeout, opera */
+/*global window, navigator, document, importScripts, setTimeout, opera */
var requirejs, require, define;
(function (global) {
var req, s, head, baseElement, dataMain, src,
interactiveScript, currentlyAddingScript, mainScript, subPath,
- version = '2.1.2',
+ version = '2.1.5',
commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
jsSuffixRegExp = /\.js$/,
@@ -21,7 +21,6 @@ var requirejs, require, define;
ostring = op.toString,
hasOwn = op.hasOwnProperty,
ap = Array.prototype,
- aps = ap.slice,
apsp = ap.splice,
isBrowser = !!(typeof window !== 'undefined' && navigator && document),
isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
@@ -192,15 +191,21 @@ var requirejs, require, define;
var inCheckLoaded, Module, context, handlers,
checkLoadedTimeoutId,
config = {
+ //Defaults. Do not set a default for map
+ //config to speed up normalize(), which
+ //will run faster if there is no default.
waitSeconds: 7,
baseUrl: './',
paths: {},
pkgs: {},
shim: {},
- map: {},
config: {}
},
registry = {},
+ //registry of just enabled modules, to speed
+ //cycle breaking code when lots of modules
+ //are registered, but not activated.
+ enabledRegistry = {},
undefEvents = {},
defQueue = [],
defined = {},
@@ -296,7 +301,7 @@ var requirejs, require, define;
}
//Apply map config if available.
- if (applyMap && (baseParts || starMap) && map) {
+ if (applyMap && map && (baseParts || starMap)) {
nameParts = name.split('/');
for (i = nameParts.length; i > 0; i -= 1) {
@@ -577,6 +582,7 @@ var requirejs, require, define;
function cleanRegistry(id) {
//Clean up machinery used for waiting modules.
delete registry[id];
+ delete enabledRegistry[id];
}
function breakCycle(mod, traced, processed) {
@@ -625,7 +631,7 @@ var requirejs, require, define;
inCheckLoaded = true;
//Figure out the state of all the modules.
- eachProp(registry, function (mod) {
+ eachProp(enabledRegistry, function (mod) {
map = mod.map;
modId = map.id;
@@ -806,7 +812,7 @@ var requirejs, require, define;
},
/**
- * Checks is the module is ready to define itself, and if so,
+ * Checks if the module is ready to define itself, and if so,
* define it.
*/
check: function () {
@@ -884,7 +890,7 @@ var requirejs, require, define;
}
//Clean up
- delete registry[id];
+ cleanRegistry(id);
this.defined = true;
}
@@ -918,8 +924,7 @@ var requirejs, require, define;
name = this.map.name,
parentName = this.map.parentMap ? this.map.parentMap.name : null,
localRequire = context.makeRequire(map.parentMap, {
- enableBuildCallback: true,
- skipMap: true
+ enableBuildCallback: true
});
//If current map is not normalized, wait for that
@@ -1017,8 +1022,11 @@ var requirejs, require, define;
try {
req.exec(text);
} catch (e) {
- throw new Error('fromText eval for ' + moduleName +
- ' failed: ' + e);
+ return onError(makeError('fromtexteval',
+ 'fromText eval for ' + id +
+ ' failed: ' + e,
+ e,
+ [id]));
}
if (hasInteractive) {
@@ -1048,6 +1056,7 @@ var requirejs, require, define;
},
enable: function () {
+ enabledRegistry[this.map.id] = this;
this.enabled = true;
//Set flag mentioning that the module is enabling,
@@ -1207,6 +1216,7 @@ var requirejs, require, define;
Module: Module,
makeModuleMap: makeModuleMap,
nextTick: req.nextTick,
+ onError: onError,
/**
* Set a configuration for the context.
@@ -1233,6 +1243,9 @@ var requirejs, require, define;
eachProp(cfg, function (value, prop) {
if (objs[prop]) {
if (prop === 'map') {
+ if (!config.map) {
+ config.map = {};
+ }
mixin(config[prop], value, true, true);
} else {
mixin(config[prop], value, true);
@@ -1344,7 +1357,7 @@ var requirejs, require, define;
//Synchronous access to one module. If require.get is
//available (as in the Node adapter), prefer that.
if (req.get) {
- return req.get(context, deps, relMap);
+ return req.get(context, deps, relMap, localRequire);
}
//Normalize module name, if it contains . or ..
@@ -1395,16 +1408,20 @@ var requirejs, require, define;
* plain URLs like nameToUrl.
*/
toUrl: function (moduleNamePlusExt) {
- var index = moduleNamePlusExt.lastIndexOf('.'),
- ext = null;
-
- if (index !== -1) {
+ var ext,
+ index = moduleNamePlusExt.lastIndexOf('.'),
+ segment = moduleNamePlusExt.split('/')[0],
+ isRelative = segment === '.' || segment === '..';
+
+ //Have a file extension alias, and it is not the
+ //dots from a relative path.
+ if (index !== -1 && (!isRelative || index > 1)) {
ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
}
return context.nameToUrl(normalize(moduleNamePlusExt,
- relMap && relMap.id, true), ext);
+ relMap && relMap.id, true), ext, true);
},
defined: function (id) {
@@ -1449,10 +1466,11 @@ var requirejs, require, define;
/**
* Called to enable a module if it is still in the registry
- * awaiting enablement. parent module is passed in for context,
- * used by the optimizer.
+ * awaiting enablement. A second arg, parent, the parent module,
+ * is passed in for context, when this method is overriden by
+ * the optimizer. Not shown here to keep code compact.
*/
- enable: function (depMap, parent) {
+ enable: function (depMap) {
var mod = getOwn(registry, depMap.id);
if (mod) {
getModule(depMap).enable();
@@ -1522,7 +1540,7 @@ var requirejs, require, define;
* it is assumed to have already been normalized. This is an
* internal API, not a public one. Use toUrl for the public API.
*/
- nameToUrl: function (moduleName, ext) {
+ nameToUrl: function (moduleName, ext, skipExt) {
var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,
parentPath;
@@ -1571,7 +1589,7 @@ var requirejs, require, define;
//Join the path parts together, then figure out if baseUrl is needed.
url = syms.join('/');
- url += (ext || (/\?/.test(url) ? '' : '.js'));
+ url += (ext || (/\?/.test(url) || skipExt ? '' : '.js'));
url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
}
@@ -1810,7 +1828,7 @@ var requirejs, require, define;
node.attachEvent('onreadystatechange', context.onScriptLoad);
//It would be great to add an error handler here to catch
//404s in IE9+. However, onreadystatechange will fire before
- //the error handler, so that does not help. If addEvenListener
+ //the error handler, so that does not help. If addEventListener
//is used, then IE will fire error before load, but we cannot
//use that pathway given the connect.microsoft.com issue
//mentioned above about not doing the 'script execute,
@@ -1839,16 +1857,24 @@ var requirejs, require, define;
return node;
} else if (isWebWorker) {
- //In a web worker, use importScripts. This is not a very
- //efficient use of importScripts, importScripts will block until
- //its script is downloaded and evaluated. However, if web workers
- //are in play, the expectation that a build has been done so that
- //only one script needs to be loaded anyway. This may need to be
- //reevaluated if other use cases become common.
- importScripts(url);
-
- //Account for anonymous modules
- context.completeLoad(moduleName);
+ try {
+ //In a web worker, use importScripts. This is not a very
+ //efficient use of importScripts, importScripts will block until
+ //its script is downloaded and evaluated. However, if web workers
+ //are in play, the expectation that a build has been done so that
+ //only one script needs to be loaded anyway. This may need to be
+ //reevaluated if other use cases become common.
+ importScripts(url);
+
+ //Account for anonymous modules
+ context.completeLoad(moduleName);
+ } catch (e) {
+ context.onError(makeError('importscripts',
+ 'importScripts failed for ' +
+ moduleName + ' at ' + url,
+ e,
+ [moduleName]));
+ }
}
};
diff --git a/module/web/static/js/libs/select2-3.2.js b/module/web/static/js/libs/select2-3.3.1.js
index d41f090d7..8be2c7e9f 100644
--- a/module/web/static/js/libs/select2-3.2.js
+++ b/module/web/static/js/libs/select2-3.3.1.js
@@ -1,7 +1,7 @@
/*
Copyright 2012 Igor Vaynberg
-Version: @@ver@@ Timestamp: @@timestamp@@
+Version: 3.3.1 Timestamp: Wed Feb 20 09:57:22 PST 2013
This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
General Public License version 2 (the "GPL License"). You may choose either license to govern your
@@ -103,7 +103,9 @@ the specific language governing permissions and limitations under the Apache Lic
function indexOf(value, array) {
var i = 0, l = array.length;
- for (; i < l; i = i + 1) if (value === array[i]) return i;
+ for (; i < l; i = i + 1) {
+ if (equal(value, array[i])) return i;
+ }
return -1;
}
@@ -113,7 +115,12 @@ the specific language governing permissions and limitations under the Apache Lic
* @param b
*/
function equal(a, b) {
- return a===b;
+ if (a === b) return true;
+ if (a === undefined || b === undefined) return false;
+ if (a === null || b === null) return false;
+ if (a.constructor === String) return a === b+'';
+ if (b.constructor === String) return b === a+'';
+ return false;
}
/**
@@ -211,6 +218,34 @@ the specific language governing permissions and limitations under the Apache Lic
});
}
+ function focus($el) {
+ if ($el[0] === document.activeElement) return;
+
+ /* set the focus in a 0 timeout - that way the focus is set after the processing
+ of the current event has finished - which seems like the only reliable way
+ to set focus */
+ window.setTimeout(function() {
+ var el=$el[0], pos=$el.val().length, range;
+
+ $el.focus();
+
+ /* after the focus is set move the caret to the end, necessary when we val()
+ just before setting focus */
+ if(el.setSelectionRange)
+ {
+ el.setSelectionRange(pos, pos);
+ }
+ else if (el.createTextRange) {
+ range = el.createTextRange();
+ range.collapse(true);
+ range.moveEnd('character', pos);
+ range.moveStart('character', pos);
+ range.select();
+ }
+
+ }, 0);
+ }
+
function killEvent(event) {
event.preventDefault();
event.stopPropagation();
@@ -243,6 +278,32 @@ the specific language governing permissions and limitations under the Apache Lic
return sizer.width();
}
+ function syncCssClasses(dest, src, adapter) {
+ var classes, replacements = [], adapted;
+
+ classes = dest.attr("class");
+ if (typeof classes === "string") {
+ $(classes.split(" ")).each2(function() {
+ if (this.indexOf("select2-") === 0) {
+ replacements.push(this);
+ }
+ });
+ }
+ classes = src.attr("class");
+ if (typeof classes === "string") {
+ $(classes.split(" ")).each2(function() {
+ if (this.indexOf("select2-") !== 0) {
+ adapted = adapter(this);
+ if (typeof adapted === "string" && adapted.length > 0) {
+ replacements.push(this);
+ }
+ }
+ });
+ }
+ dest.attr("class", replacements.join(" "));
+ }
+
+
function markMatch(text, term, markup, escapeMarkup) {
var match=text.toUpperCase().indexOf(term.toUpperCase()),
tl=term.length;
@@ -279,7 +340,9 @@ the specific language governing permissions and limitations under the Apache Lic
var timeout, // current scheduled but not yet executed request
requestSequence = 0, // sequence used to drop out-of-order responses
handler = null,
- quietMillis = options.quietMillis || 100;
+ quietMillis = options.quietMillis || 100,
+ ajaxUrl = options.url,
+ self = this;
return function (query) {
window.clearTimeout(timeout);
@@ -287,31 +350,40 @@ the specific language governing permissions and limitations under the Apache Lic
requestSequence += 1; // increment the sequence
var requestNumber = requestSequence, // this request's sequence number
data = options.data, // ajax data function
- url = options.url, // ajax url string or function
+ url = ajaxUrl, // ajax url string or function
transport = options.transport || $.ajax,
- traditional = options.traditional || false,
- type = options.type || 'GET'; // set type of request (GET or POST)
+ type = options.type || 'GET', // set type of request (GET or POST)
+ params = {};
- data = data ? data.call(this, query.term, query.page, query.context) : null;
- url = (typeof url === 'function') ? url.call(this, query.term, query.page, query.context) : url;
+ data = data ? data.call(self, query.term, query.page, query.context) : null;
+ url = (typeof url === 'function') ? url.call(self, query.term, query.page, query.context) : url;
if( null !== handler) { handler.abort(); }
- handler = transport.call(null, {
+ if (options.params) {
+ if ($.isFunction(options.params)) {
+ $.extend(params, options.params.call(self));
+ } else {
+ $.extend(params, options.params);
+ }
+ }
+
+ $.extend(params, {
url: url,
dataType: options.dataType,
data: data,
type: type,
- traditional: traditional,
+ cache: false,
success: function (data) {
if (requestNumber < requestSequence) {
return;
}
- // TODO 3.0 - replace query.page with query so users have access to term, page, etc.
+ // TODO - replace query.page with query so users have access to term, page, etc.
var results = options.results(data, query.page);
query.callback(results);
}
});
+ handler = transport.call(self, params);
}, quietMillis);
};
}
@@ -333,22 +405,33 @@ the specific language governing permissions and limitations under the Apache Lic
function local(options) {
var data = options, // data elements
dataText,
+ tmp,
text = function (item) { return ""+item.text; }; // function used to retrieve the text portion of a data item that is matched against the search
- if (!$.isArray(data)) {
- text = data.text;
+ if ($.isArray(data)) {
+ tmp = data;
+ data = { results: tmp };
+ }
+
+ if ($.isFunction(data) === false) {
+ tmp = data;
+ data = function() { return tmp; };
+ }
+
+ var dataItem = data();
+ if (dataItem.text) {
+ text = dataItem.text;
// if text is not a function we assume it to be a key name
if (!$.isFunction(text)) {
- dataText = data.text; // we need to store this in a separate variable because in the next step data gets reset and data.text is no longer available
- text = function (item) { return item[dataText]; };
+ dataText = data.text; // we need to store this in a separate variable because in the next step data gets reset and data.text is no longer available
+ text = function (item) { return item[dataText]; };
}
- data = data.results;
}
return function (query) {
var t = query.term, filtered = { results: [] }, process;
if (t === "") {
- query.callback({results: data});
+ query.callback(data());
return;
}
@@ -372,7 +455,7 @@ the specific language governing permissions and limitations under the Apache Lic
}
};
- $(data).each2(function(i, datum) { process(datum, filtered.results); });
+ $(data().results).each2(function(i, datum) { process(datum, filtered.results); });
query.callback(filtered);
};
}
@@ -526,28 +609,7 @@ the specific language governing permissions and limitations under the Apache Lic
// cache the body so future lookups are cheap
this.body = thunk(function() { return opts.element.closest("body"); });
- // create the dropdown mask if doesnt already exist
- mask = $("#select2-drop-mask");
- if (mask.length == 0) {
- mask = $(document.createElement("div"));
- mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask");
- mask.hide();
- mask.appendTo(this.body());
- mask.bind("mousedown touchstart", function (e) {
- var dropdown = $("#select2-drop"), self;
- if (dropdown.length > 0) {
- self=dropdown.data("select2");
- if (self.opts.selectOnBlur) {
- self.selectHighlighted({noFocus: true});
- }
- self.close();
- }
- });
- }
-
- if (opts.element.attr("class") !== undefined) {
- this.container.addClass(opts.element.attr("class").replace(/validate\[[\S ]+] ?/, ''));
- }
+ syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
this.container.css(evaluate(opts.containerCss));
this.container.addClass(evaluate(opts.containerCssClass));
@@ -558,7 +620,7 @@ the specific language governing permissions and limitations under the Apache Lic
this.opts.element
.data("select2", this)
.addClass("select2-offscreen")
- .bind("focus.select2", function() { $(this).select2("focus")})
+ .bind("focus.select2", function() { $(this).select2("focus"); })
.attr("tabIndex", "-1")
.before(this.container);
this.container.data("select2", this);
@@ -577,10 +639,9 @@ the specific language governing permissions and limitations under the Apache Lic
// initialize the container
this.initContainer();
- this.initContainerWidth();
installFilteredMouseMove(this.results);
- this.dropdown.delegate(resultsSelector, "mousemove-filtered", this.bind(this.highlightUnderEvent));
+ this.dropdown.delegate(resultsSelector, "mousemove-filtered touchstart touchmove touchend", this.bind(this.highlightUnderEvent));
installDebouncedScroll(80, this.results);
this.dropdown.delegate(resultsSelector, "scroll-debounced", this.bind(this.loadMoreIfNeeded));
@@ -600,18 +661,15 @@ the specific language governing permissions and limitations under the Apache Lic
}
installKeyUpChangeEvent(search);
- search.bind("keyup-change", this.bind(this.updateResults));
- search.bind("focus", function () { search.addClass("select2-focused"); if (search.val() === " ") search.val(""); });
+ search.bind("keyup-change input paste", this.bind(this.updateResults));
+ search.bind("focus", function () { search.addClass("select2-focused"); });
search.bind("blur", function () { search.removeClass("select2-focused");});
this.dropdown.delegate(resultsSelector, "mouseup", this.bind(function (e) {
if ($(e.target).closest(".select2-result-selectable").length > 0) {
this.highlightUnderEvent(e);
this.selectHighlighted(e);
- } else {
- this.focusSearch();
}
- killEvent(e);
}));
// trap all mouse events from leaving the dropdown. sometimes there may be a modal that is listening
@@ -642,9 +700,10 @@ the specific language governing permissions and limitations under the Apache Lic
select2.container.remove();
select2.dropdown.remove();
select2.opts.element
+ .removeClass("select2-offscreen")
.removeData("select2")
.unbind(".select2")
- .attr("tabIndex", this.elementTabIndex)
+ .attr({"tabIndex": this.elementTabIndex})
.show();
}
},
@@ -698,7 +757,7 @@ the specific language governing permissions and limitations under the Apache Lic
label=$(document.createElement("div"));
label.addClass("select2-result-label");
- formatted=opts.formatResult(result, label, query);
+ formatted=opts.formatResult(result, label, query, self.opts.escapeMarkup);
if (formatted!==undefined) {
label.html(formatted);
}
@@ -771,7 +830,7 @@ the specific language governing permissions and limitations under the Apache Lic
});
// this is needed because inside val() we construct choices from options and there id is hardcoded
opts.id=function(e) { return e.id; };
- opts.formatResultCssClass = function(data) { return data.css; }
+ opts.formatResultCssClass = function(data) { return data.css; };
} else {
if (!("query" in opts)) {
@@ -780,7 +839,7 @@ the specific language governing permissions and limitations under the Apache Lic
if (ajaxUrl && ajaxUrl.length > 0) {
opts.ajax.url = ajaxUrl;
}
- opts.query = ajax(opts.ajax);
+ opts.query = ajax.call(opts.element, opts.ajax);
} else if ("data" in opts) {
opts.query = local(opts.data);
} else if ("tags" in opts) {
@@ -788,17 +847,19 @@ the specific language governing permissions and limitations under the Apache Lic
if (opts.createSearchChoice === undefined) {
opts.createSearchChoice = function (term) { return {id: term, text: term}; };
}
- opts.initSelection = function (element, callback) {
- var data = [];
- $(splitVal(element.val(), opts.separator)).each(function () {
- var id = this, text = this, tags=opts.tags;
- if ($.isFunction(tags)) tags=tags();
- $(tags).each(function() { if (equal(this.id, id)) { text = this.text; return false; } });
- data.push({id: id, text: text});
- });
-
- callback(data);
- };
+ if (opts.initSelection === undefined) {
+ opts.initSelection = function (element, callback) {
+ var data = [];
+ $(splitVal(element.val(), opts.separator)).each(function () {
+ var id = this, text = this, tags=opts.tags;
+ if ($.isFunction(tags)) tags=tags();
+ $(tags).each(function() { if (equal(this.id, id)) { text = this.text; return false; } });
+ data.push({id: id, text: text});
+ });
+
+ callback(data);
+ };
+ }
}
}
}
@@ -823,8 +884,13 @@ the specific language governing permissions and limitations under the Apache Lic
}));
sync = this.bind(function () {
- var enabled = this.opts.element.attr("disabled") !== "disabled";
- var readonly = this.opts.element.attr("readonly") === "readonly";
+
+ var enabled, readonly, self = this;
+
+ // sync enabled state
+
+ enabled = this.opts.element.attr("disabled") !== "disabled";
+ readonly = this.opts.element.attr("readonly") === "readonly";
enabled = enabled && !readonly;
@@ -835,6 +901,14 @@ the specific language governing permissions and limitations under the Apache Lic
this.disable();
}
}
+
+
+ syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
+ this.container.addClass(evaluate(this.opts.containerCssClass));
+
+ syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);
+ this.dropdown.addClass(evaluate(this.opts.dropdownCssClass));
+
});
// mozilla and IE
@@ -903,21 +977,21 @@ the specific language governing permissions and limitations under the Apache Lic
height = this.container.outerHeight(false),
width = this.container.outerWidth(false),
dropHeight = this.dropdown.outerHeight(false),
- viewPortRight = $(window).scrollLeft() + document.documentElement.clientWidth,
- viewportBottom = $(window).scrollTop() + document.documentElement.clientHeight,
+ viewPortRight = $(window).scrollLeft() + $(window).width(),
+ viewportBottom = $(window).scrollTop() + $(window).height(),
dropTop = offset.top + height,
dropLeft = offset.left,
enoughRoomBelow = dropTop + dropHeight <= viewportBottom,
enoughRoomAbove = (offset.top - dropHeight) >= this.body().scrollTop(),
- dropWidth = this.dropdown.outerWidth(false),
- enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight,
+ dropWidth = this.dropdown.outerWidth(false),
+ enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight,
aboveNow = this.dropdown.hasClass("select2-drop-above"),
bodyOffset,
above,
css;
- // console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow);
- // console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body().scrollTop(), "enough?", enoughRoomAbove);
+ //console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow);
+ //console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body().scrollTop(), "enough?", enoughRoomAbove);
// fix positioning when body has an offset and is not position: static
@@ -937,9 +1011,9 @@ the specific language governing permissions and limitations under the Apache Lic
if (!enoughRoomBelow && enoughRoomAbove) above = true;
}
- if (!enoughRoomOnRight) {
- dropLeft = offset.left + width - dropWidth;
- }
+ if (!enoughRoomOnRight) {
+ dropLeft = offset.left + width - dropWidth;
+ }
if (above) {
dropTop = offset.top - dropHeight;
@@ -966,7 +1040,7 @@ the specific language governing permissions and limitations under the Apache Lic
if (this.opened()) return false;
- event = $.Event("open");
+ event = $.Event("opening");
this.opts.element.trigger(event);
return !event.isDefaultPrevented();
},
@@ -1007,8 +1081,6 @@ the specific language governing permissions and limitations under the Apache Lic
this.clearDropdownAlignmentPreference();
- if (this.search.val() === " ") { this.search.val(""); }
-
this.container.addClass("select2-dropdown-open").addClass("select2-container-active");
@@ -1018,7 +1090,24 @@ the specific language governing permissions and limitations under the Apache Lic
this.updateResults(true);
+ // create the dropdown mask if doesnt already exist
mask = $("#select2-drop-mask");
+ if (mask.length == 0) {
+ mask = $(document.createElement("div"));
+ mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask");
+ mask.hide();
+ mask.appendTo(this.body());
+ mask.bind("mousedown touchstart", function (e) {
+ var dropdown = $("#select2-drop"), self;
+ if (dropdown.length > 0) {
+ self=dropdown.data("select2");
+ if (self.opts.selectOnBlur) {
+ self.selectHighlighted({noFocus: true});
+ }
+ self.close();
+ }
+ });
+ }
// ensure the mask is always right before the dropdown
if (this.dropdown.prev()[0] !== mask[0]) {
@@ -1042,12 +1131,13 @@ the specific language governing permissions and limitations under the Apache Lic
// attach listeners to events that can change the position of the container and thus require
// the position of the dropdown to be updated as well so it does not come unglued from the container
+ var that = this;
this.container.parents().add(window).each(function () {
$(this).bind(resize+" "+scroll+" "+orient, function (e) {
$("#select2-drop-mask").css({
width:document.documentElement.scrollWidth,
height:document.documentElement.scrollHeight});
- $("#select2-drop").data("select2").positionDropdown();
+ that.positionDropdown();
});
});
@@ -1071,7 +1161,7 @@ the specific language governing permissions and limitations under the Apache Lic
$("#select2-drop-mask").hide();
this.dropdown.removeAttr("id"); // only the active dropdown has the select2-drop id
this.dropdown.hide();
- this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active");
+ this.container.removeClass("select2-dropdown-open");
this.results.empty();
this.clearSearch();
@@ -1083,6 +1173,11 @@ the specific language governing permissions and limitations under the Apache Lic
},
+ //abstract
+ getMaximumSelectionSize: function() {
+ return evaluate(this.opts.maximumSelectionSize);
+ },
+
// abstract
ensureHighlightVisible: function () {
var results = this.results, children, index, child, hb, rb, y, more;
@@ -1150,7 +1245,9 @@ the specific language governing permissions and limitations under the Apache Lic
// abstract
highlight: function (index) {
- var choices = this.findHighlightableChoices();
+ var choices = this.findHighlightableChoices(),
+ choice,
+ data;
if (arguments.length === 0) {
return indexOf(choices.filter(".select2-highlighted")[0], choices.get());
@@ -1161,8 +1258,15 @@ the specific language governing permissions and limitations under the Apache Lic
this.results.find(".select2-highlighted").removeClass("select2-highlighted");
- $(choices[index]).addClass("select2-highlighted");
+ choice = $(choices[index]);
+ choice.addClass("select2-highlighted");
+
this.ensureHighlightVisible();
+
+ data = choice.data("select2-data");
+ if (data) {
+ this.opts.element.trigger({ type: "highlight", val: this.id(data), choice: data });
+ }
},
// abstract
@@ -1199,6 +1303,7 @@ the specific language governing permissions and limitations under the Apache Lic
if (below <= this.opts.loadMorePadding) {
more.addClass("select2-active");
this.opts.query({
+ element: this.opts.element,
term: term,
page: page,
context: context,
@@ -1219,6 +1324,7 @@ the specific language governing permissions and limitations under the Apache Lic
}
self.positionDropdown();
self.resultsPage = page;
+ self.context = data.context;
})});
}
},
@@ -1255,10 +1361,11 @@ the specific language governing permissions and limitations under the Apache Lic
postRender();
}
- if (opts.maximumSelectionSize >=1) {
+ var maxSelSize = this.getMaximumSelectionSize();
+ if (maxSelSize >=1) {
data = this.data();
- if ($.isArray(data) && data.length >= opts.maximumSelectionSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) {
- render("<li class='select2-selection-limit'>" + opts.formatSelectionTooBig(opts.maximumSelectionSize) + "</li>");
+ if ($.isArray(data) && data.length >= maxSelSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) {
+ render("<li class='select2-selection-limit'>" + opts.formatSelectionTooBig(maxSelSize) + "</li>");
return;
}
}
@@ -1291,7 +1398,9 @@ the specific language governing permissions and limitations under the Apache Lic
}
this.resultsPage = 1;
+
opts.query({
+ element: opts.element,
term: search.val(),
page: this.resultsPage,
context: null,
@@ -1304,7 +1413,6 @@ the specific language governing permissions and limitations under the Apache Lic
// save context, if any
this.context = (data.context===undefined) ? null : data.context;
-
// create a default choice and prepend it to the list
if (this.opts.createSearchChoice && search.val() !== "") {
def = this.opts.createSearchChoice.call(null, search.val(), data.results);
@@ -1350,28 +1458,15 @@ the specific language governing permissions and limitations under the Apache Lic
this.close();
this.container.removeClass("select2-container-active");
- this.dropdown.removeClass("select2-drop-active");
// synonymous to .is(':focus'), which is available in jquery >= 1.6
if (this.search[0] === document.activeElement) { this.search.blur(); }
this.clearSearch();
this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
- this.opts.element.triggerHandler("blur");
},
// abstract
focusSearch: function () {
- // need to do it here as well as in timeout so it works in IE
- this.search.show();
- this.search.focus();
-
- /* we do this in a timeout so that current event processing can complete before this code is executed.
- this makes sure the search field is focussed even if the current event would blur it */
- window.setTimeout(this.bind(function () {
- // reset the value so IE places the cursor at the end of the input box
- this.search.show();
- this.search.focus();
- this.search.val(this.search.val());
- }), 10);
+ focus(this.search);
},
// abstract
@@ -1388,14 +1483,6 @@ the specific language governing permissions and limitations under the Apache Lic
// abstract
getPlaceholder: function () {
-
- // if a placeholder is specified on a select without the first empty option ignore it
- if (this.select) {
- if (this.select.find("option").first().text() !== "") {
- return undefined;
- }
- }
-
return this.opts.element.attr("placeholder") ||
this.opts.element.attr("data-placeholder") || // jquery 1.4 compat
this.opts.element.data("placeholder") ||
@@ -1450,7 +1537,7 @@ the specific language governing permissions and limitations under the Apache Lic
var width = resolveContainerWidth.call(this);
if (width !== null) {
- this.container.attr("style", "width: "+width);
+ this.container.css("width", width);
}
}
});
@@ -1463,11 +1550,12 @@ the specific language governing permissions and limitations under the Apache Lic
var container = $(document.createElement("div")).attr({
"class": "select2-container"
}).html([
- " <a href='javascript:void(0)' onclick='return false;' class='select2-choice'>",
+ "<a href='javascript:void(0)' onclick='return false;' class='select2-choice' tabindex='-1'>",
" <span></span><abbr class='select2-search-choice-close' style='display:none;'></abbr>",
" <div><b></b></div>" ,
"</a>",
- " <div class='select2-drop select2-offscreen'>" ,
+ "<input class='select2-focusser select2-offscreen' type='text'/>",
+ "<div class='select2-drop' style='display:none'>" ,
" <div class='select2-search'>" ,
" <input type='text' autocomplete='off' class='select2-input'/>" ,
" </div>" ,
@@ -1478,34 +1566,59 @@ the specific language governing permissions and limitations under the Apache Lic
},
// single
+ disable: function() {
+ if (!this.enabled) return;
+
+ this.parent.disable.apply(this, arguments);
+
+ this.focusser.attr("disabled", "disabled");
+ },
+
+ // single
+ enable: function() {
+ if (this.enabled) return;
+
+ this.parent.enable.apply(this, arguments);
+
+ this.focusser.removeAttr("disabled");
+ },
+
+ // single
opening: function () {
- this.search.show();
this.parent.opening.apply(this, arguments);
- this.dropdown.removeClass("select2-offscreen");
+ this.focusser.attr("disabled", "disabled");
+
+ this.opts.element.trigger($.Event("open"));
},
// single
close: function () {
if (!this.opened()) return;
this.parent.close.apply(this, arguments);
- this.dropdown.removeAttr("style").addClass("select2-offscreen").insertAfter(this.selection).show();
+ this.focusser.removeAttr("disabled");
+ focus(this.focusser);
},
// single
focus: function () {
- this.close();
- this.selection.focus();
+ if (this.opened()) {
+ this.close();
+ } else {
+ this.focusser.removeAttr("disabled");
+ this.focusser.focus();
+ }
},
// single
isFocused: function () {
- return this.selection[0] === document.activeElement;
+ return this.container.hasClass("select2-container-active");
},
// single
cancel: function () {
this.parent.cancel.apply(this, arguments);
- this.selection.focus();
+ this.focusser.removeAttr("disabled");
+ this.focusser.focus();
},
// single
@@ -1516,8 +1629,12 @@ the specific language governing permissions and limitations under the Apache Lic
dropdown = this.dropdown,
clickingInside = false;
+ this.showSearch(this.opts.minimumResultsForSearch >= 0);
+
this.selection = selection = container.find(".select2-choice");
+ this.focusser = container.find(".select2-focusser");
+
this.search.bind("keydown", this.bind(function (e) {
if (!this.enabled) return;
@@ -1527,56 +1644,62 @@ the specific language governing permissions and limitations under the Apache Lic
return;
}
- if (this.opened()) {
- switch (e.which) {
- case KEY.UP:
- case KEY.DOWN:
- this.moveHighlight((e.which === KEY.UP) ? -1 : 1);
- killEvent(e);
- return;
- case KEY.TAB:
- case KEY.ENTER:
- this.selectHighlighted();
- killEvent(e);
- return;
- case KEY.ESC:
- this.cancel(e);
- killEvent(e);
- return;
- }
- } else {
-
- if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {
+ switch (e.which) {
+ case KEY.UP:
+ case KEY.DOWN:
+ this.moveHighlight((e.which === KEY.UP) ? -1 : 1);
+ killEvent(e);
return;
- }
-
- if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {
+ case KEY.TAB:
+ case KEY.ENTER:
+ this.selectHighlighted();
+ killEvent(e);
return;
- }
+ case KEY.ESC:
+ this.cancel(e);
+ killEvent(e);
+ return;
+ }
+ }));
+
+ this.focusser.bind("keydown", this.bind(function (e) {
+ if (!this.enabled) return;
+
+ if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {
+ return;
+ }
+ if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {
+ killEvent(e);
+ return;
+ }
+
+ if (e.which == KEY.DOWN || e.which == KEY.UP
+ || (e.which == KEY.ENTER && this.opts.openOnEnter)) {
this.open();
+ killEvent(e);
+ return;
+ }
- if (e.which === KEY.ENTER) {
- // do not propagate the event otherwise we open, and propagate enter which closes
- return;
+ if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE) {
+ if (this.opts.allowClear) {
+ this.clear();
}
+ killEvent(e);
+ return;
}
}));
- this.search.bind("focus", this.bind(function() {
- this.selection.attr("tabIndex", "-1");
- }));
- this.search.bind("blur", this.bind(function() {
- if (!this.opened()) this.container.removeClass("select2-container-active");
- window.setTimeout(this.bind(function() {
- // restore original tab index
- var ti=this.elementTabIndex || 0;
- if (ti) {
- this.selection.attr("tabIndex", ti);
- } else {
- this.selection.removeAttr("tabIndex");
- }
- }), 10);
+
+ installKeyUpChangeEvent(this.focusser);
+ this.focusser.bind("keyup-change input", this.bind(function(e) {
+ if (this.opened()) return;
+ this.open();
+ if (this.showSearchInput !== false) {
+ this.search.val(this.focusser.val());
+ }
+ this.focusser.val("");
+ killEvent(e);
}));
selection.delegate("abbr", "mousedown", this.bind(function (e) {
@@ -1584,7 +1707,6 @@ the specific language governing permissions and limitations under the Apache Lic
this.clear();
killEventImmediately(e);
this.close();
- this.triggerChange();
this.selection.focus();
}));
@@ -1593,69 +1715,47 @@ the specific language governing permissions and limitations under the Apache Lic
if (this.opened()) {
this.close();
- this.selection.focus();
} else if (this.enabled) {
this.open();
}
+ killEvent(e);
+
clickingInside = false;
}));
dropdown.bind("mousedown", this.bind(function() { this.search.focus(); }));
- selection.bind("focus", this.bind(function() {
- this.container.addClass("select2-container-active");
- // hide the search so the tab key does not focus on it
- this.search.attr("tabIndex", "-1");
+ selection.bind("focus", this.bind(function(e) {
+ killEvent(e);
}));
- selection.bind("blur", this.bind(function() {
+ this.focusser.bind("focus", this.bind(function(){
+ this.container.addClass("select2-container-active");
+ })).bind("blur", this.bind(function() {
if (!this.opened()) {
this.container.removeClass("select2-container-active");
}
- window.setTimeout(this.bind(function() { this.search.attr("tabIndex", this.elementTabIndex || 0); }), 10);
- }));
-
- selection.bind("keydown", this.bind(function(e) {
- if (!this.enabled) return;
-
- if (e.which == KEY.DOWN || e.which == KEY.UP
- || (e.which == KEY.ENTER && this.opts.openOnEnter)) {
- this.open();
- killEvent(e);
- return;
- }
-
- if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE) {
- if (this.opts.allowClear) {
- this.clear();
- }
- killEvent(e);
- return;
- }
- }));
- selection.bind("keypress", this.bind(function(e) {
- if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE || e.which == KEY.TAB || e.which == KEY.ENTER || e.which == 0) {
- return
- }
- var key = String.fromCharCode(e.which);
- this.search.val(key);
- this.open();
}));
+ this.search.bind("focus", this.bind(function(){
+ this.container.addClass("select2-container-active");
+ }))
+ this.initContainerWidth();
this.setPlaceholder();
- this.search.bind("focus", this.bind(function() {
- this.container.addClass("select2-container-active");
- }));
},
// single
clear: function() {
+ var data=this.selection.data("select2-data");
this.opts.element.val("");
this.selection.find("span").empty();
this.selection.removeData("select2-data");
this.setPlaceholder();
+
+ this.opts.element.trigger({ type: "removed", val: this.id(data), choice: data });
+ this.triggerChange({removed:data});
},
/**
@@ -1711,6 +1811,18 @@ the specific language governing permissions and limitations under the Apache Lic
},
// single
+ getPlaceholder: function() {
+ // if a placeholder is specified on a single select without the first empty option ignore it
+ if (this.select) {
+ if (this.select.find("option").first().text() !== "") {
+ return undefined;
+ }
+ }
+
+ return this.parent.getPlaceholder.apply(this, arguments);
+ },
+
+ // single
setPlaceholder: function () {
var placeholder = this.getPlaceholder();
@@ -1747,21 +1859,31 @@ the specific language governing permissions and limitations under the Apache Lic
// hide the search box if this is the first we got the results and there are a few of them
if (initial === true) {
- showSearchInput = this.showSearchInput = countResults(data.results) >= this.opts.minimumResultsForSearch;
- this.dropdown.find(".select2-search")[showSearchInput ? "removeClass" : "addClass"]("select2-search-hidden");
-
- //add "select2-with-searchbox" to the container if search box is shown
- $(this.dropdown, this.container)[showSearchInput ? "addClass" : "removeClass"]("select2-with-searchbox");
+ var min=this.opts.minimumResultsForSearch;
+ showSearchInput = min < 0 ? false : countResults(data.results) >= min;
+ this.showSearch(showSearchInput);
}
},
// single
+ showSearch: function(showSearchInput) {
+ this.showSearchInput = showSearchInput;
+
+ this.dropdown.find(".select2-search")[showSearchInput ? "removeClass" : "addClass"]("select2-search-hidden");
+ //add "select2-with-searchbox" to the container if search box is shown
+ $(this.dropdown, this.container)[showSearchInput ? "addClass" : "removeClass"]("select2-with-searchbox");
+ },
+
+ // single
onSelect: function (data, options) {
var old = this.opts.element.val();
this.opts.element.val(this.id(data));
this.updateSelection(data);
+
+ this.opts.element.trigger({ type: "selected", val: this.id(data), choice: data });
+
this.close();
if (!options || !options.noFocus)
@@ -1833,7 +1955,9 @@ the specific language governing permissions and limitations under the Apache Lic
self.opts.element.val(!data ? "" : self.id(data));
self.updateSelection(data);
self.setPlaceholder();
- self.triggerChange();
+ if (triggerChange) {
+ self.triggerChange();
+ }
});
}
},
@@ -1841,6 +1965,7 @@ the specific language governing permissions and limitations under the Apache Lic
// single
clearSearch: function () {
this.search.val("");
+ this.focusser.val("");
},
// single
@@ -1890,15 +2015,14 @@ the specific language governing permissions and limitations under the Apache Lic
if (opts.element.get(0).tagName.toLowerCase() === "select") {
// install sthe selection initializer
- opts.initSelection = function (element,callback) {
+ opts.initSelection = function (element, callback) {
var data = [];
+
element.find(":selected").each2(function (i, elm) {
- data.push({id: elm.attr("value"), text: elm.text(), element: elm});
+ data.push({id: elm.attr("value"), text: elm.text(), element: elm[0]});
});
-
- if ($.isFunction(callback))
- callback(data);
+ callback(data);
};
} else if ("data" in opts) {
// install default initSelection when applied to hidden input and data is local
@@ -1929,6 +2053,13 @@ the specific language governing permissions and limitations under the Apache Lic
this.searchContainer = this.container.find(".select2-search-field");
this.selection = selection = this.container.find(selector);
+ this.search.bind("input paste", this.bind(function() {
+ if (!this.enabled) return;
+ if (!this.opened()) {
+ this.open();
+ }
+ }));
+
this.search.bind("keydown", this.bind(function (e) {
if (!this.enabled) return;
@@ -1976,8 +2107,12 @@ the specific language governing permissions and limitations under the Apache Lic
return;
}
- if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {
- return;
+ if (e.which === KEY.ENTER) {
+ if (this.opts.openOnEnter === false) {
+ return;
+ } else if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
+ return;
+ }
}
this.open();
@@ -1993,7 +2128,7 @@ the specific language governing permissions and limitations under the Apache Lic
this.search.bind("blur", this.bind(function(e) {
this.container.removeClass("select2-container-active");
this.search.removeClass("select2-focused");
- this.clearSearch();
+ if (!this.opened()) this.clearSearch();
e.stopImmediatePropagation();
}));
@@ -2016,6 +2151,8 @@ the specific language governing permissions and limitations under the Apache Lic
this.clearPlaceholder();
}));
+ this.initContainerWidth();
+
// set the placeholder if necessary
this.clearSearch();
},
@@ -2069,9 +2206,7 @@ the specific language governing permissions and limitations under the Apache Lic
// stretch the search box to full width of the container so as much of the placeholder is visible as possible
this.resizeSearch();
} else {
- // we set this to " " instead of "" and later clear it on focus() because there is a firefox bug
- // that does not properly render the caret when the field starts out blank
- this.search.val(" ").width(10);
+ this.search.val("").width(10);
}
},
@@ -2079,9 +2214,6 @@ the specific language governing permissions and limitations under the Apache Lic
clearPlaceholder: function () {
if (this.search.hasClass("select2-default")) {
this.search.val("").removeClass("select2-default");
- } else {
- // work around for the space character we set to avoid firefox caret bug
- if (this.search.val() === " ") this.search.val("");
}
},
@@ -2092,6 +2224,8 @@ the specific language governing permissions and limitations under the Apache Lic
this.clearPlaceholder();
this.resizeSearch();
this.focusSearch();
+
+ this.opts.element.trigger($.Event("open"));
},
// multi
@@ -2104,6 +2238,7 @@ the specific language governing permissions and limitations under the Apache Lic
focus: function () {
this.close();
this.search.focus();
+ this.opts.element.triggerHandler("focus");
},
// multi
@@ -2146,6 +2281,9 @@ the specific language governing permissions and limitations under the Apache Lic
// multi
onSelect: function (data, options) {
this.addSelectedChoice(data);
+
+ this.opts.element.trigger({ type: "selected", val: this.id(data), choice: data });
+
if (this.select || !this.opts.closeOnSelect) this.postprocessResults();
if (this.opts.closeOnSelect) {
@@ -2155,10 +2293,16 @@ the specific language governing permissions and limitations under the Apache Lic
if (this.countSelectableResults()>0) {
this.search.width(10);
this.resizeSearch();
+ if (this.val().length >= this.getMaximumSelectionSize()) {
+ // if we reached max selection size repaint the results so choices
+ // are replaced with the max selection reached message
+ this.updateResults(true);
+ }
this.positionDropdown();
} else {
// if nothing left to select close
this.close();
+ this.search.width(10);
}
}
@@ -2252,6 +2396,8 @@ the specific language governing permissions and limitations under the Apache Lic
if (this.select) this.postprocessResults();
}
selected.remove();
+
+ this.opts.element.trigger({ type: "removed", val: this.id(data), choice: data });
this.triggerChange({ removed: data });
},
@@ -2287,7 +2433,6 @@ the specific language governing permissions and limitations under the Apache Lic
// multi
resizeSearch: function () {
-
var minimumWidth, left, maxWidth, containerLeft, searchWidth,
sideBorderPadding = getSideBorderPadding(this.search);
@@ -2299,6 +2444,7 @@ the specific language governing permissions and limitations under the Apache Lic
containerLeft = this.selection.offset().left;
searchWidth = maxWidth - (left - containerLeft) - sideBorderPadding;
+
if (searchWidth < minimumWidth) {
searchWidth = maxWidth - sideBorderPadding;
}
@@ -2308,7 +2454,7 @@ the specific language governing permissions and limitations under the Apache Lic
}
if (searchWidth <= 0) {
- searchWidth = minimumWidth
+ searchWidth = minimumWidth;
}
this.search.width(searchWidth);
@@ -2370,16 +2516,13 @@ the specific language governing permissions and limitations under the Apache Lic
this.setVal(val);
if (this.select) {
- this.select.find(":selected").each(function () {
- data.push({id: $(this).attr("value"), text: $(this).text()});
- });
- this.updateSelection(data);
+ this.opts.initSelection(this.select, this.bind(this.updateSelection));
if (triggerChange) {
this.triggerChange();
}
} else {
if (this.opts.initSelection === undefined) {
- throw new Error("val() cannot be called if initSelection() is not defined")
+ throw new Error("val() cannot be called if initSelection() is not defined");
}
this.opts.initSelection(this.opts.element, function(data){
@@ -2438,7 +2581,7 @@ the specific language governing permissions and limitations under the Apache Lic
.get();
} else {
if (!values) { values = []; }
- ids = $.map(values, function(e) { return self.opts.id(e)});
+ ids = $.map(values, function(e) { return self.opts.id(e); });
this.setVal(ids);
this.updateSelection(values);
this.clearSearch();
@@ -2499,9 +2642,9 @@ the specific language governing permissions and limitations under the Apache Lic
dropdownCss: {},
containerCssClass: "",
dropdownCssClass: "",
- formatResult: function(result, container, query) {
+ formatResult: function(result, container, query, escapeMarkup) {
var markup=[];
- markMatch(result.text, query.term, markup, this.escapeMarkup);
+ markMatch(result.text, query.term, markup, escapeMarkup);
return markup.join("");
},
formatSelection: function (data, container) {
@@ -2544,7 +2687,9 @@ the specific language governing permissions and limitations under the Apache Lic
});
},
blurOnChange: false,
- selectOnBlur: false
+ selectOnBlur: false,
+ adaptContainerCssClass: function(c) { return c; },
+ adaptDropdownCssClass: function(c) { return null; }
};
// exports
diff --git a/module/web/static/js/views/filterView.js b/module/web/static/js/views/filterView.js
index 792edfee2..ea0aff0d5 100644
--- a/module/web/static/js/views/filterView.js
+++ b/module/web/static/js/views/filterView.js
@@ -1,6 +1,16 @@
define(['jquery', 'backbone', 'underscore', 'app', 'utils/apitypes'],
function($, Backbone, _, App, Api) {
+ // Modified version of type ahead show, nearly the same without absolute positioning
+ function show() {
+ this.$menu
+ .insertAfter(this.$element)
+ .show();
+
+ this.shown = true;
+ return this;
+ }
+
// Renders the actionbar for the dashboard, handles everything related to filtering displayed files
return Backbone.View.extend({
el: 'ul.actionbar',
@@ -14,6 +24,9 @@ define(['jquery', 'backbone', 'underscore', 'app', 'utils/apitypes'],
stateMenu: null,
initialize: function() {
+
+ // use our modified method
+ $.fn.typeahead.Constructor.prototype.show = show;
this.$('.search-query').typeahead({
minLength: 2,
source: this.getAutocompletion
@@ -24,7 +37,6 @@ define(['jquery', 'backbone', 'underscore', 'app', 'utils/apitypes'],
// Apply the filter before the content is shown
App.vent.on('dashboard:contentReady', _.bind(this.apply_filter, this));
-
},
render: function() {
@@ -33,7 +45,8 @@ define(['jquery', 'backbone', 'underscore', 'app', 'utils/apitypes'],
getAutocompletion: function() {
return ["static", "autocompletion", "demo", "with", "some", "keywords",
- "a very long proposal for autocompletion"];
+ "a very long proposal for autocompletion", "autobot",
+ "a very long proposal for autocompletion second one"];
},
switch_filter: function(e) {
diff --git a/module/web/templates/default/base.html b/module/web/templates/default/base.html
index 77789e790..621059c8c 100644
--- a/module/web/templates/default/base.html
+++ b/module/web/templates/default/base.html
@@ -13,13 +13,13 @@
<link href="/static/css/bootstrap.css" rel="stylesheet" type="text/css"/>
<link href="/static/css/select2.css" rel="stylesheet" type="text/css"/>
<link href="/static/css/font.css" rel="stylesheet" type="text/css"/>
- <link href="static/css/fontawesome.css" rel="stylesheet" type="text/css"/>
+ <link href="/static/css/fontawesome.css" rel="stylesheet" type="text/css"/>
<link href="/static/css/default/style.less" rel="stylesheet/less" type="text/css" media="screen"/>
{% block css %}
{% endblock %}
<script src="/static/js/libs/less-1.3.0.min.js" type="text/javascript"></script>
- <script type="text/javascript" data-main="static/js/config" src="/static/js/libs/require-2.1.2.js"></script>
+ <script type="text/javascript" data-main="static/js/config" src="/static/js/libs/require-2.1.5.js"></script>
<script>
require(['default'], function(App) {
App.init();