From 8a9341b186c2bb33309d96d639d0bb36329f5443 Mon Sep 17 00:00:00 2001 From: Ryan Lane Date: Tue, 9 Apr 2013 00:48:21 -0700 Subject: [PATCH] Add chosen support to HTMLForm's multiselect field For very large multiselects, the list of checkboxes is overwhelming. This change adds support for using jquery.chosen conditionally on multiselect fields, if 'chosen' is used for the cssclass parameter. Change-Id: If1eba7fb705089deb4cff7a326db0ac803a522ec --- .jshintignore | 1 + RELEASE-NOTES-1.22 | 2 + languages/messages/MessagesEn.php | 1 + languages/messages/MessagesQqq.php | 1 + resources/Resources.php | 5 + resources/jquery.chosen/LICENSE | 24 + resources/jquery.chosen/chosen-sprite.png | Bin 0 -> 646 bytes resources/jquery.chosen/chosen-sprite@2x.png | Bin 0 -> 872 bytes resources/jquery.chosen/chosen.css | 413 +++++++ resources/jquery.chosen/chosen.jquery.js | 1090 ++++++++++++++++++ resources/mediawiki/mediawiki.htmlform.js | 68 +- 11 files changed, 1603 insertions(+), 2 deletions(-) create mode 100644 resources/jquery.chosen/LICENSE create mode 100644 resources/jquery.chosen/chosen-sprite.png create mode 100644 resources/jquery.chosen/chosen-sprite@2x.png create mode 100644 resources/jquery.chosen/chosen.css create mode 100644 resources/jquery.chosen/chosen.jquery.js diff --git a/.jshintignore b/.jshintignore index 30b6ee1056..64add554d7 100644 --- a/.jshintignore +++ b/.jshintignore @@ -23,6 +23,7 @@ resources/jquery.effects/ resources/jquery.tipsy/ resources/jquery.ui/ resources/mediawiki.libs/ +resources/jquery.chosen/chosen.jquery.js # legacy scripts skins/common/ diff --git a/RELEASE-NOTES-1.22 b/RELEASE-NOTES-1.22 index ce4c9490a8..aad11a010b 100644 --- a/RELEASE-NOTES-1.22 +++ b/RELEASE-NOTES-1.22 @@ -54,6 +54,8 @@ production. well. * (bug 45535) introduced the new 'LanguageLinks' hook for manipulating the language links associated with a page before display. +* Chosen (http://harvesthq.github.io/chosen/) was added as module 'jquery.chosen' +* HTMLForm will turn multiselect checkboxes into a Chosen interface when setting cssclass 'mw-chosen' === Bug fixes in 1.22 === * Disable Special:PasswordReset when $wgEnableEmail. Previously one could still diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 8191f590a9..aadccac5be 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -4888,6 +4888,7 @@ This site is experiencing technical difficulties.', 'htmlform-selectorother-other' => 'Other', 'htmlform-no' => 'No', 'htmlform-yes' => 'Yes', +'htmlform-chosen-placeholder' => 'Select an option', # SQLite database support 'sqlite-has-fts' => '$1 with full-text search support', diff --git a/languages/messages/MessagesQqq.php b/languages/messages/MessagesQqq.php index bdebfd4437..b1b452ed7a 100644 --- a/languages/messages/MessagesQqq.php +++ b/languages/messages/MessagesQqq.php @@ -8747,6 +8747,7 @@ See also: {{Identical|No}}', 'htmlform-yes' => 'Used in form, such as with radio buttons, for generic yes / no questions. {{Identical|Yes}}', +'htmlform-chosen-placeholder' => 'Used as initial placeholder text in select multiple "chosen" input boxes', # SQLite database support 'sqlite-has-fts' => 'Shown on [[Special:Version]]. diff --git a/resources/Resources.php b/resources/Resources.php index 538ee01706..0d8b330c6b 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -141,6 +141,10 @@ return array( 'scripts' => 'resources/jquery/jquery.checkboxShiftClick.js', 'targets' => array( 'desktop', 'mobile' ), ), + 'jquery.chosen' => array( + 'scripts' => 'resources/jquery.chosen/chosen.jquery.js', + 'styles' => 'resources/jquery.chosen/chosen.css', + ), 'jquery.client' => array( 'scripts' => 'resources/jquery/jquery.client.js', 'targets' => array( 'desktop', 'mobile' ), @@ -636,6 +640,7 @@ return array( ), 'mediawiki.htmlform' => array( 'scripts' => 'resources/mediawiki/mediawiki.htmlform.js', + 'messages' => array( 'htmlform-chosen-placeholder' ), ), 'mediawiki.notification' => array( 'styles' => 'resources/mediawiki/mediawiki.notification.css', diff --git a/resources/jquery.chosen/LICENSE b/resources/jquery.chosen/LICENSE new file mode 100644 index 0000000000..0675dc5264 --- /dev/null +++ b/resources/jquery.chosen/LICENSE @@ -0,0 +1,24 @@ +# Chosen, a Select Box Enhancer for jQuery and Protoype +## by Patrick Filler for [Harvest](http://getharvest.com) + +Available for use under the [MIT License](http://en.wikipedia.org/wiki/MIT_License) + +Copyright (c) 2011-2013 by Harvest + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/resources/jquery.chosen/chosen-sprite.png b/resources/jquery.chosen/chosen-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..3611ae4ace1c4b1cbeacd6145b5a79cbc72e0bdc GIT binary patch literal 646 zcmV;10(t$3P)0006_Nkl&pbAC0n?)s%2x5M$#UgGxI1~gymp~v; zh<`zGaTJP5BybQY4tlRo;SIcmE0t>ueW3>*u6N;@_u;;|BoL8PuhZ#FWY9$(flan1oVvxDBL8~}0Q5z;^2p>Ov z7}Q$E7=l>$BZLUt1*uKMCaQwKYf$lsJCyerWMd+%BeGH6f_f&Vpy%=$BN%uK%Ahxi zF+%Jj=Pc-WXF;djSiJw|m4>cN%^Fi|FBZ!E{_yJLS?RI<3U696XLkQSs z{{&kQJ$K(#5CgC1;GbA>mjm56zJZ^-Hg2_ASKI_K@CybPh7Rq}8ud``)NM~eZx}qT z)oK?Lf>t!B;%Uh}*P+)Ef?jbx#w|BNEVb(l{2LK}m#fw4xx>ddF;&j}!S{N-e!<&Q z?kvzyI_AT@H-u4tUz1h&GCh8>?TnA~?BZ7WGP<9`r gQ6DuZO!_~60ju@{TzXF%TmS$707*qoM6N<$g2#CqL;wH) literal 0 HcmV?d00001 diff --git a/resources/jquery.chosen/chosen-sprite@2x.png b/resources/jquery.chosen/chosen-sprite@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ffe4d7d1121ca45cd35783696940050c690a8676 GIT binary patch literal 872 zcmeAS@N?(olHy`uVBq!ia0vp^89?mC!3-o5mOWetq|OBRgt-3y{~yTgfB`oc01C8& zL0el}Lqh|Q1oD8A5J8A6G6@lfkU;ftMr&&;+$f+RkloVK0wm!8C|FWb0x`e2xj8g6 z6i7l;BAWwL4-tfu5G@ccP!{MmqnYOy06pVW666=m!0_*bfx(A_gav;C1PU5HKT!C5 z;g7@l4POuZ{>hQBP{j4uqq`I2WP9&Sn{}I8xJi*&v*QL&+Dw-Bf-CQLyLk0Ht2-;T zynum$iPO`?F{C2y?bYjfj|~J`6Xz~`vM4Ef+U{Vpli%)D%kKSey_RG0Bi9Xw4jtOb z@!)?~_%DVelO793W#Pl3vjdNCDTnGGb(^YY+BbF2;mJK!nq}@nBGoHxCn#7X*gdxr z+~ZQF6rpL6;MDP)JzehcJBL53AM-QU?@65Plc4-}1EW@`H@EEGrnFmTubZ~5iUzVn zrZYyBIm|RmW$3F@+wkq2)c>|mGh5Rv3%(p~zjStyruBl(TP2_51LpTH2noN*e&}J; z1;$+4EpJ(Mb+^1}Fv>ms%b`r}+KYy~zf5x(4?8l28%eNnEHzx({;NGP)_hX&tEw9t zSKv=Qjt(d#~b;F7hbDdUu$OUK8iumkkl&-=~$APCd2zdqHg6@=Z#Pt*5RY_s@Hw*YS9+ z^u)7AmzM6Ux!dus_!gJY)Vtf?+t>a3wO2S)_Vct=T}#@RuG(h!d8WYZS9Tst+VfKv zt~zntPsvfyqLY`klZSPslCz_dlcSRJLa$Px)_+W2Y&u!?oJrIMCNTz2S3j3^P6' + option.html + ''; + } else { + return ""; + } + }; + + AbstractChosen.prototype.results_update_field = function() { + this.set_default_text(); + if (!this.is_multiple) { + this.results_reset_cleanup(); + } + this.result_clear_highlight(); + this.result_single_selected = null; + return this.results_build(); + }; + + AbstractChosen.prototype.results_toggle = function() { + if (this.results_showing) { + return this.results_hide(); + } else { + return this.results_show(); + } + }; + + AbstractChosen.prototype.results_search = function(evt) { + if (this.results_showing) { + return this.winnow_results(); + } else { + return this.results_show(); + } + }; + + AbstractChosen.prototype.keyup_checker = function(evt) { + var stroke, _ref; + stroke = (_ref = evt.which) != null ? _ref : evt.keyCode; + this.search_field_scale(); + switch (stroke) { + case 8: + if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) { + return this.keydown_backstroke(); + } else if (!this.pending_backstroke) { + this.result_clear_highlight(); + return this.results_search(); + } + break; + case 13: + evt.preventDefault(); + if (this.results_showing) { + return this.result_select(evt); + } + break; + case 27: + if (this.results_showing) { + this.results_hide(); + } + return true; + case 9: + case 38: + case 40: + case 16: + case 91: + case 17: + break; + default: + return this.results_search(); + } + }; + + AbstractChosen.prototype.generate_field_id = function() { + var new_id; + new_id = this.generate_random_id(); + this.form_field.id = new_id; + return new_id; + }; + + AbstractChosen.prototype.generate_random_char = function() { + var chars, newchar, rand; + chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + rand = Math.floor(Math.random() * chars.length); + return newchar = chars.substring(rand, rand + 1); + }; + + return AbstractChosen; + + })(); + + root.AbstractChosen = AbstractChosen; + +}).call(this); + +/* +Chosen source: generate output using 'cake build' +Copyright (c) 2011 by Harvest +*/ + + +(function() { + var $, Chosen, get_side_border_padding, root, + __hasProp = {}.hasOwnProperty, + __extends = 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; }; + + root = this; + + $ = jQuery; + + $.fn.extend({ + chosen: function(options) { + var browser, match, ua; + ua = navigator.userAgent.toLowerCase(); + match = /(msie) ([\w.]+)/.exec(ua) || []; + browser = { + name: match[1] || "", + version: match[2] || "0" + }; + if (browser.name === "msie" && (browser.version === "6.0" || (browser.version === "7.0" && document.documentMode === 7))) { + return this; + } + return this.each(function(input_field) { + var $this; + $this = $(this); + if (!$this.hasClass("chzn-done")) { + return $this.data('chosen', new Chosen(this, options)); + } + }); + } + }); + + Chosen = (function(_super) { + + __extends(Chosen, _super); + + function Chosen() { + return Chosen.__super__.constructor.apply(this, arguments); + } + + Chosen.prototype.setup = function() { + this.form_field_jq = $(this.form_field); + this.current_value = this.form_field_jq.val(); + return this.is_rtl = this.form_field_jq.hasClass("chzn-rtl"); + }; + + Chosen.prototype.finish_setup = function() { + return this.form_field_jq.addClass("chzn-done"); + }; + + Chosen.prototype.set_up_html = function() { + var container_classes, container_div, container_props, dd_top, dd_width, sf_width; + this.container_id = this.form_field.id.length ? this.form_field.id.replace(/[^\w]/g, '_') : this.generate_field_id(); + this.container_id += "_chzn"; + container_classes = ["chzn-container"]; + container_classes.push("chzn-container-" + (this.is_multiple ? "multi" : "single")); + if (this.inherit_select_classes && this.form_field.className) { + container_classes.push(this.form_field.className); + } + if (this.is_rtl) { + container_classes.push("chzn-rtl"); + } + this.f_width = this.form_field_jq.outerWidth(); + container_props = { + id: this.container_id, + "class": container_classes.join(' '), + style: 'width: ' + this.f_width + 'px;', + title: this.form_field.title + }; + container_div = $("
", container_props); + if (this.is_multiple) { + container_div.html('
    '); + } else { + container_div.html('' + this.default_text + '
      '); + } + this.form_field_jq.hide().after(container_div); + this.container = $('#' + this.container_id); + this.dropdown = this.container.find('div.chzn-drop').first(); + dd_top = this.container.height(); + dd_width = this.f_width - get_side_border_padding(this.dropdown); + this.dropdown.css({ + "width": dd_width + "px", + "top": dd_top + "px" + }); + this.search_field = this.container.find('input').first(); + this.search_results = this.container.find('ul.chzn-results').first(); + this.search_field_scale(); + this.search_no_results = this.container.find('li.no-results').first(); + if (this.is_multiple) { + this.search_choices = this.container.find('ul.chzn-choices').first(); + this.search_container = this.container.find('li.search-field').first(); + } else { + this.search_container = this.container.find('div.chzn-search').first(); + this.selected_item = this.container.find('.chzn-single').first(); + sf_width = dd_width - get_side_border_padding(this.search_container) - get_side_border_padding(this.search_field); + this.search_field.css({ + "width": sf_width + "px" + }); + } + this.results_build(); + this.set_tab_index(); + return this.form_field_jq.trigger("liszt:ready", { + chosen: this + }); + }; + + Chosen.prototype.register_observers = function() { + var _this = this; + this.container.mousedown(function(evt) { + _this.container_mousedown(evt); + }); + this.container.mouseup(function(evt) { + _this.container_mouseup(evt); + }); + this.container.mouseenter(function(evt) { + _this.mouse_enter(evt); + }); + this.container.mouseleave(function(evt) { + _this.mouse_leave(evt); + }); + this.search_results.mouseup(function(evt) { + _this.search_results_mouseup(evt); + }); + this.search_results.mouseover(function(evt) { + _this.search_results_mouseover(evt); + }); + this.search_results.mouseout(function(evt) { + _this.search_results_mouseout(evt); + }); + this.form_field_jq.bind("liszt:updated", function(evt) { + _this.results_update_field(evt); + }); + this.form_field_jq.bind("liszt:activate", function(evt) { + _this.activate_field(evt); + }); + this.form_field_jq.bind("liszt:open", function(evt) { + _this.container_mousedown(evt); + }); + this.search_field.blur(function(evt) { + _this.input_blur(evt); + }); + this.search_field.keyup(function(evt) { + _this.keyup_checker(evt); + }); + this.search_field.keydown(function(evt) { + _this.keydown_checker(evt); + }); + this.search_field.focus(function(evt) { + _this.input_focus(evt); + }); + if (this.is_multiple) { + return this.search_choices.click(function(evt) { + _this.choices_click(evt); + }); + } else { + return this.container.click(function(evt) { + evt.preventDefault(); + }); + } + }; + + Chosen.prototype.search_field_disabled = function() { + this.is_disabled = this.form_field_jq[0].disabled; + if (this.is_disabled) { + this.container.addClass('chzn-disabled'); + this.search_field[0].disabled = true; + if (!this.is_multiple) { + this.selected_item.unbind("focus", this.activate_action); + } + return this.close_field(); + } else { + this.container.removeClass('chzn-disabled'); + this.search_field[0].disabled = false; + if (!this.is_multiple) { + return this.selected_item.bind("focus", this.activate_action); + } + } + }; + + Chosen.prototype.container_mousedown = function(evt) { + var target_closelink; + if (!this.is_disabled) { + target_closelink = evt != null ? ($(evt.target)).hasClass("search-choice-close") : false; + if (evt && evt.type === "mousedown" && !this.results_showing) { + evt.preventDefault(); + } + if (!this.pending_destroy_click && !target_closelink) { + if (!this.active_field) { + if (this.is_multiple) { + this.search_field.val(""); + } + $(document).click(this.click_test_action); + this.results_show(); + } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chzn-single").length)) { + evt.preventDefault(); + this.results_toggle(); + } + return this.activate_field(); + } else { + return this.pending_destroy_click = false; + } + } + }; + + Chosen.prototype.container_mouseup = function(evt) { + if (evt.target.nodeName === "ABBR" && !this.is_disabled) { + return this.results_reset(evt); + } + }; + + Chosen.prototype.blur_test = function(evt) { + if (!this.active_field && this.container.hasClass("chzn-container-active")) { + return this.close_field(); + } + }; + + Chosen.prototype.close_field = function() { + $(document).unbind("click", this.click_test_action); + this.active_field = false; + this.results_hide(); + this.container.removeClass("chzn-container-active"); + this.winnow_results_clear(); + this.clear_backstroke(); + this.show_search_field_default(); + return this.search_field_scale(); + }; + + Chosen.prototype.activate_field = function() { + this.container.addClass("chzn-container-active"); + this.active_field = true; + this.search_field.val(this.search_field.val()); + return this.search_field.focus(); + }; + + Chosen.prototype.test_active_click = function(evt) { + if ($(evt.target).parents('#' + this.container_id).length) { + return this.active_field = true; + } else { + return this.close_field(); + } + }; + + Chosen.prototype.results_build = function() { + var content, data, _i, _len, _ref; + this.parsing = true; + this.results_data = root.SelectParser.select_to_array(this.form_field); + if (this.is_multiple && this.choices > 0) { + this.search_choices.find("li.search-choice").remove(); + this.choices = 0; + } else if (!this.is_multiple) { + this.selected_item.addClass("chzn-default").find("span").text(this.default_text); + if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) { + this.container.addClass("chzn-container-single-nosearch"); + } else { + this.container.removeClass("chzn-container-single-nosearch"); + } + } + content = ''; + _ref = this.results_data; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + data = _ref[_i]; + if (data.group) { + content += this.result_add_group(data); + } else if (!data.empty) { + content += this.result_add_option(data); + if (data.selected && this.is_multiple) { + this.choice_build(data); + } else if (data.selected && !this.is_multiple) { + this.selected_item.removeClass("chzn-default").find("span").text(data.text); + if (this.allow_single_deselect) { + this.single_deselect_control_build(); + } + } + } + } + this.search_field_disabled(); + this.show_search_field_default(); + this.search_field_scale(); + this.search_results.html(content); + return this.parsing = false; + }; + + Chosen.prototype.result_add_group = function(group) { + if (!group.disabled) { + group.dom_id = this.container_id + "_g_" + group.array_index; + return '
    • ' + $("
      ").text(group.label).html() + '
    • '; + } else { + return ""; + } + }; + + Chosen.prototype.result_do_highlight = function(el) { + var high_bottom, high_top, maxHeight, visible_bottom, visible_top; + if (el.length) { + this.result_clear_highlight(); + this.result_highlight = el; + this.result_highlight.addClass("highlighted"); + maxHeight = parseInt(this.search_results.css("maxHeight"), 10); + visible_top = this.search_results.scrollTop(); + visible_bottom = maxHeight + visible_top; + high_top = this.result_highlight.position().top + this.search_results.scrollTop(); + high_bottom = high_top + this.result_highlight.outerHeight(); + if (high_bottom >= visible_bottom) { + return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0); + } else if (high_top < visible_top) { + return this.search_results.scrollTop(high_top); + } + } + }; + + Chosen.prototype.result_clear_highlight = function() { + if (this.result_highlight) { + this.result_highlight.removeClass("highlighted"); + } + return this.result_highlight = null; + }; + + Chosen.prototype.results_show = function() { + var dd_top; + if (!this.is_multiple) { + this.selected_item.addClass("chzn-single-with-drop"); + if (this.result_single_selected) { + this.result_do_highlight(this.result_single_selected); + } + } else if (this.max_selected_options <= this.choices) { + this.form_field_jq.trigger("liszt:maxselected", { + chosen: this + }); + return false; + } + dd_top = this.is_multiple ? this.container.height() : this.container.height() - 1; + this.form_field_jq.trigger("liszt:showing_dropdown", { + chosen: this + }); + this.dropdown.css({ + "top": dd_top + "px", + "left": 0 + }); + this.results_showing = true; + this.search_field.focus(); + this.search_field.val(this.search_field.val()); + return this.winnow_results(); + }; + + Chosen.prototype.results_hide = function() { + if (!this.is_multiple) { + this.selected_item.removeClass("chzn-single-with-drop"); + } + this.result_clear_highlight(); + this.form_field_jq.trigger("liszt:hiding_dropdown", { + chosen: this + }); + this.dropdown.css({ + "left": "-9000px" + }); + return this.results_showing = false; + }; + + Chosen.prototype.set_tab_index = function(el) { + var ti; + if (this.form_field_jq.attr("tabindex")) { + ti = this.form_field_jq.attr("tabindex"); + this.form_field_jq.attr("tabindex", -1); + return this.search_field.attr("tabindex", ti); + } + }; + + Chosen.prototype.show_search_field_default = function() { + if (this.is_multiple && this.choices < 1 && !this.active_field) { + this.search_field.val(this.default_text); + return this.search_field.addClass("default"); + } else { + this.search_field.val(""); + return this.search_field.removeClass("default"); + } + }; + + Chosen.prototype.search_results_mouseup = function(evt) { + var target; + target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); + if (target.length) { + this.result_highlight = target; + this.result_select(evt); + return this.search_field.focus(); + } + }; + + Chosen.prototype.search_results_mouseover = function(evt) { + var target; + target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); + if (target) { + return this.result_do_highlight(target); + } + }; + + Chosen.prototype.search_results_mouseout = function(evt) { + if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) { + return this.result_clear_highlight(); + } + }; + + Chosen.prototype.choices_click = function(evt) { + evt.preventDefault(); + if (this.active_field && !($(evt.target).hasClass("search-choice" || $(evt.target).parents('.search-choice').first)) && !this.results_showing) { + return this.results_show(); + } + }; + + Chosen.prototype.choice_build = function(item) { + var choice_id, html, link, + _this = this; + if (this.is_multiple && this.max_selected_options <= this.choices) { + this.form_field_jq.trigger("liszt:maxselected", { + chosen: this + }); + return false; + } + choice_id = this.container_id + "_c_" + item.array_index; + this.choices += 1; + if (item.disabled) { + html = '
    • ' + item.html + '
    • '; + } else { + html = '
    • ' + item.html + '
    • '; + } + this.search_container.before(html); + link = $('#' + choice_id).find("a").first(); + return link.click(function(evt) { + return _this.choice_destroy_link_click(evt); + }); + }; + + Chosen.prototype.choice_destroy_link_click = function(evt) { + evt.preventDefault(); + if (!this.is_disabled) { + this.pending_destroy_click = true; + return this.choice_destroy($(evt.target)); + } else { + return evt.stopPropagation; + } + }; + + Chosen.prototype.choice_destroy = function(link) { + if (this.result_deselect(link.attr("rel"))) { + this.choices -= 1; + this.show_search_field_default(); + if (this.is_multiple && this.choices > 0 && this.search_field.val().length < 1) { + this.results_hide(); + } + link.parents('li').first().remove(); + return this.search_field_scale(); + } + }; + + Chosen.prototype.results_reset = function() { + this.form_field.options[0].selected = true; + this.selected_item.find("span").text(this.default_text); + if (!this.is_multiple) { + this.selected_item.addClass("chzn-default"); + } + this.show_search_field_default(); + this.results_reset_cleanup(); + this.form_field_jq.trigger("change"); + if (this.active_field) { + return this.results_hide(); + } + }; + + Chosen.prototype.results_reset_cleanup = function() { + this.current_value = this.form_field_jq.val(); + return this.selected_item.find("abbr").remove(); + }; + + Chosen.prototype.result_select = function(evt) { + var high, high_id, item, position; + if (this.result_highlight) { + high = this.result_highlight; + high_id = high.attr("id"); + this.result_clear_highlight(); + if (this.is_multiple) { + this.result_deactivate(high); + } else { + this.search_results.find(".result-selected").removeClass("result-selected"); + this.result_single_selected = high; + this.selected_item.removeClass("chzn-default"); + } + high.addClass("result-selected"); + position = high_id.substr(high_id.lastIndexOf("_") + 1); + item = this.results_data[position]; + item.selected = true; + this.form_field.options[item.options_index].selected = true; + if (this.is_multiple) { + this.choice_build(item); + } else { + this.selected_item.find("span").first().text(item.text); + if (this.allow_single_deselect) { + this.single_deselect_control_build(); + } + } + if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) { + this.results_hide(); + } + this.search_field.val(""); + if (this.is_multiple || this.form_field_jq.val() !== this.current_value) { + this.form_field_jq.trigger("change", { + 'selected': this.form_field.options[item.options_index].value + }); + } + this.current_value = this.form_field_jq.val(); + return this.search_field_scale(); + } + }; + + Chosen.prototype.result_activate = function(el) { + return el.addClass("active-result"); + }; + + Chosen.prototype.result_deactivate = function(el) { + return el.removeClass("active-result"); + }; + + Chosen.prototype.result_deselect = function(pos) { + var result, result_data; + result_data = this.results_data[pos]; + if (!this.form_field.options[result_data.options_index].disabled) { + result_data.selected = false; + this.form_field.options[result_data.options_index].selected = false; + result = $("#" + this.container_id + "_o_" + pos); + result.removeClass("result-selected").addClass("active-result").show(); + this.result_clear_highlight(); + this.winnow_results(); + this.form_field_jq.trigger("change", { + deselected: this.form_field.options[result_data.options_index].value + }); + this.search_field_scale(); + return true; + } else { + return false; + } + }; + + Chosen.prototype.single_deselect_control_build = function() { + if (this.allow_single_deselect && this.selected_item.find("abbr").length < 1) { + return this.selected_item.find("span").first().after(""); + } + }; + + Chosen.prototype.winnow_results = function() { + var found, option, part, parts, regex, regexAnchor, result, result_id, results, searchText, startpos, text, zregex, _i, _j, _len, _len1, _ref; + this.no_results_clear(); + results = 0; + searchText = this.search_field.val() === this.default_text ? "" : $('
      ').text($.trim(this.search_field.val())).html(); + regexAnchor = this.search_contains ? "" : "^"; + regex = new RegExp(regexAnchor + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i'); + zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i'); + _ref = this.results_data; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + option = _ref[_i]; + if (!option.disabled && !option.empty) { + if (option.group) { + $('#' + option.dom_id).css('display', 'none'); + } else if (!(this.is_multiple && option.selected)) { + found = false; + result_id = option.dom_id; + result = $("#" + result_id); + if (regex.test(option.html)) { + found = true; + results += 1; + } else if (this.enable_split_word_search && (option.html.indexOf(" ") >= 0 || option.html.indexOf("[") === 0)) { + parts = option.html.replace(/\[|\]/g, "").split(" "); + if (parts.length) { + for (_j = 0, _len1 = parts.length; _j < _len1; _j++) { + part = parts[_j]; + if (regex.test(part)) { + found = true; + results += 1; + } + } + } + } + if (found) { + if (searchText.length) { + startpos = option.html.search(zregex); + text = option.html.substr(0, startpos + searchText.length) + '' + option.html.substr(startpos + searchText.length); + text = text.substr(0, startpos) + '' + text.substr(startpos); + } else { + text = option.html; + } + result.html(text); + this.result_activate(result); + if (option.group_array_index != null) { + $("#" + this.results_data[option.group_array_index].dom_id).css('display', 'list-item'); + } + } else { + if (this.result_highlight && result_id === this.result_highlight.attr('id')) { + this.result_clear_highlight(); + } + this.result_deactivate(result); + } + } + } + } + if (results < 1 && searchText.length) { + return this.no_results(searchText); + } else { + return this.winnow_results_set_highlight(); + } + }; + + Chosen.prototype.winnow_results_clear = function() { + var li, lis, _i, _len, _results; + this.search_field.val(""); + lis = this.search_results.find("li"); + _results = []; + for (_i = 0, _len = lis.length; _i < _len; _i++) { + li = lis[_i]; + li = $(li); + if (li.hasClass("group-result")) { + _results.push(li.css('display', 'auto')); + } else if (!this.is_multiple || !li.hasClass("result-selected")) { + _results.push(this.result_activate(li)); + } else { + _results.push(void 0); + } + } + return _results; + }; + + Chosen.prototype.winnow_results_set_highlight = function() { + var do_high, selected_results; + if (!this.result_highlight) { + selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : []; + do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first(); + if (do_high != null) { + return this.result_do_highlight(do_high); + } + } + }; + + Chosen.prototype.no_results = function(terms) { + var no_results_html; + no_results_html = $('
    • ' + this.results_none_found + ' ""
    • '); + no_results_html.find("span").first().html(terms); + return this.search_results.append(no_results_html); + }; + + Chosen.prototype.no_results_clear = function() { + return this.search_results.find(".no-results").remove(); + }; + + Chosen.prototype.keydown_arrow = function() { + var first_active, next_sib; + if (!this.result_highlight) { + first_active = this.search_results.find("li.active-result").first(); + if (first_active) { + this.result_do_highlight($(first_active)); + } + } else if (this.results_showing) { + next_sib = this.result_highlight.nextAll("li.active-result").first(); + if (next_sib) { + this.result_do_highlight(next_sib); + } + } + if (!this.results_showing) { + return this.results_show(); + } + }; + + Chosen.prototype.keyup_arrow = function() { + var prev_sibs; + if (!this.results_showing && !this.is_multiple) { + return this.results_show(); + } else if (this.result_highlight) { + prev_sibs = this.result_highlight.prevAll("li.active-result"); + if (prev_sibs.length) { + return this.result_do_highlight(prev_sibs.first()); + } else { + if (this.choices > 0) { + this.results_hide(); + } + return this.result_clear_highlight(); + } + } + }; + + Chosen.prototype.keydown_backstroke = function() { + var next_available_destroy; + if (this.pending_backstroke) { + this.choice_destroy(this.pending_backstroke.find("a").first()); + return this.clear_backstroke(); + } else { + next_available_destroy = this.search_container.siblings("li.search-choice").last(); + if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) { + this.pending_backstroke = next_available_destroy; + if (this.single_backstroke_delete) { + return this.keydown_backstroke(); + } else { + return this.pending_backstroke.addClass("search-choice-focus"); + } + } + } + }; + + Chosen.prototype.clear_backstroke = function() { + if (this.pending_backstroke) { + this.pending_backstroke.removeClass("search-choice-focus"); + } + return this.pending_backstroke = null; + }; + + Chosen.prototype.keydown_checker = function(evt) { + var stroke, _ref; + stroke = (_ref = evt.which) != null ? _ref : evt.keyCode; + this.search_field_scale(); + if (stroke !== 8 && this.pending_backstroke) { + this.clear_backstroke(); + } + switch (stroke) { + case 8: + this.backstroke_length = this.search_field.val().length; + break; + case 9: + if (this.results_showing && !this.is_multiple) { + this.result_select(evt); + } + this.mouse_on_container = false; + break; + case 13: + evt.preventDefault(); + break; + case 38: + evt.preventDefault(); + this.keyup_arrow(); + break; + case 40: + this.keydown_arrow(); + break; + } + }; + + Chosen.prototype.search_field_scale = function() { + var dd_top, div, h, style, style_block, styles, w, _i, _len; + if (this.is_multiple) { + h = 0; + w = 0; + style_block = "position:absolute; left: -1000px; top: -1000px; display:none;"; + styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing']; + for (_i = 0, _len = styles.length; _i < _len; _i++) { + style = styles[_i]; + style_block += style + ":" + this.search_field.css(style) + ";"; + } + div = $('
      ', { + 'style': style_block + }); + div.text(this.search_field.val()); + $('body').append(div); + w = div.width() + 25; + div.remove(); + if (w > this.f_width - 10) { + w = this.f_width - 10; + } + this.search_field.css({ + 'width': w + 'px' + }); + dd_top = this.container.height(); + return this.dropdown.css({ + "top": dd_top + "px" + }); + } + }; + + Chosen.prototype.generate_random_id = function() { + var string; + string = "sel" + this.generate_random_char() + this.generate_random_char() + this.generate_random_char(); + while ($("#" + string).length > 0) { + string += this.generate_random_char(); + } + return string; + }; + + return Chosen; + + })(AbstractChosen); + + root.Chosen = Chosen; + + get_side_border_padding = function(elmt) { + var side_border_padding; + return side_border_padding = elmt.outerWidth() - elmt.width(); + }; + + root.get_side_border_padding = get_side_border_padding; + +}).call(this); diff --git a/resources/mediawiki/mediawiki.htmlform.js b/resources/mediawiki/mediawiki.htmlform.js index 83bf2e3a2a..433679018f 100644 --- a/resources/mediawiki/mediawiki.htmlform.js +++ b/resources/mediawiki/mediawiki.htmlform.js @@ -1,7 +1,7 @@ /** * Utility functions for jazzing up HTMLForm elements. */ -( function ( $ ) { +( function ( mw, $ ) { /** * jQuery plugin to fade or snap to visible state. @@ -59,4 +59,68 @@ } ); -}( jQuery ) ); + function addMulti( $oldContainer, $container ) { + var name = $oldContainer.find( 'input:first-child' ).attr( 'name' ), + $select = $( '