Select2

The jQuery replacement for select boxes

  1. // ==UserScript==
  2. // @name Select2
  3. // @namespace https://select2.github.io/
  4. // @version 0.9.3
  5. // @description The jQuery replacement for select boxes
  6. // @author t_liang
  7. // @include *:*
  8. // @exclude *://select2.org/*
  9. // @exclude *://app.yinxiang.com/*
  10. // @exclude *://www.instagram.com/*
  11. // @exclude *://*.tmall.com/*
  12. // @exclude *://*.taobao.com/*
  13. // @exclude *://www.google.co*
  14. // @grant none
  15. // ==/UserScript==
  16.  
  17. /*
  18. History
  19. 0.1 初始版本
  20. 0.2 修复版本比较错误,versionMoreThan
  21. 0.3 jQuery.noConflict(true)
  22. 0.4 支持jQuery.ajax
  23. 0.5 exclude app.yinxiang.com
  24. 0.6 use setInterval
  25. 0.7 config, setTimeout, zIndex
  26. 0.8 templateResult matcher
  27. 0.9 add group matcher
  28. */
  29.  
  30. /*
  31. (function(factory) {
  32. debugger;
  33. if (typeof define === 'function' && define.amd) {
  34. // AMD. Register as an anonymous module.
  35. define([ 'jquery' ], factory);
  36. } else if (typeof exports === 'object') {
  37. // Node/CommonJS
  38. factory(require('jquery'));
  39. } else {
  40. // Browser globals
  41. factory(jQuery);
  42. }
  43. })(console.log);
  44. */
  45.  
  46. // console.log(arguments);
  47. setTimeout(function() {
  48. // config
  49. var config = {
  50. ignore : [
  51. 'typeof Vue == "function"',
  52. 'typeof jQuery == "function" && typeof jQuery.fn.selectpicker == "function"'
  53. ],
  54. jquery : {
  55. _1_3_2 : '1.3.2', // 无 jQuery.expando jQuery._data
  56. _1_6_4 : '1.6.4', // select2 渲染正常 支持事件
  57. js : '//cdn.bootcss.com/jquery/3.2.1/jquery.min.js'
  58. },
  59. select2 : {
  60. js : '//cdn.bootcss.com/select2/4.0.3/js/select2.min.js',
  61. css : '//cdn.bootcss.com/select2/4.0.3/css/select2.min.css'
  62. },
  63. timeout : 3000,
  64. interval : 3000,
  65. minWidth : 147
  66. };
  67. // ignore
  68. for (var i = config.ignore.length - 1; i >= 0; i--) {
  69. if (eval(config.ignore[i])) {
  70. return;
  71. }
  72. }
  73.  
  74. var noConflict,
  75. protocol = location.protocol == 'https:' ? 'https:' : 'http:',
  76. jQueryOnload = function() {
  77. jQuery(function($) {
  78. $.ajaxSetup({
  79. cache : true
  80. });
  81. var $head = $(document.head),
  82. select2Onload = function() {
  83. noConflict && $.noConflict(true);
  84. // console.log($.fn.select2, location.href);
  85. $head.append('<style>span.select2-dropdown{z-index:99999 !important;}</style>');
  86. setInterval(function() {
  87. $('select:not(.select2-hidden-accessible,.select2-offscreen,[multiple])').filter(':visible').each(function() {
  88. if (typeof jQuery == 'function' && !versionMoreThan(jQuery.fn.jquery, config.jquery._1_6_4) &&
  89. (jQuery.cache ? jQuery.cache[this[jQuery.expando]] : jQuery._data(this))) {
  90. return true;
  91. }
  92. var $this = $(this),
  93. $options = $this.find('option'),
  94. $firstOption = $options.first();
  95. $options.length > 2 && $this.select2({
  96. width : Math.max($this.width(), config.minWidth),
  97. dropdownAutoWidth : true,
  98. placeholder : $firstOption.val() ? '' : $firstOption.text(), //for allowClear
  99. allowClear : true,
  100. templateResult : function(option, Eoption) {
  101. if (option.loading || !option.id) {
  102. return option.text;
  103. }
  104. return '[' + option.id + ']' + option.text;
  105. },
  106. matcher : function(params, option) {
  107. var term = $.trim(params.term).toUpperCase();
  108. if (!term) {
  109. return option;
  110. }
  111. if ('id' in option) {
  112. if (option.text.toUpperCase().indexOf(term) > -1 ||
  113. option.id.toUpperCase().indexOf(term) > -1) {
  114. return option;
  115. }
  116. } else {
  117. var filteredChildren = [];
  118. $.each(option.children, function(idx, child) {
  119. if (child.text.toUpperCase().indexOf(term) > -1 ||
  120. child.id.toUpperCase().indexOf(term) > -1) {
  121. filteredChildren.push(child);
  122. }
  123. });
  124. if (filteredChildren.length) {
  125. return $.extend({}, option, {
  126. children : filteredChildren
  127. });
  128. }
  129. }
  130. return null;
  131. }
  132. });
  133. });
  134. }, config.interval);
  135. };
  136. if ($.isFunction($.fn.select2)) {
  137. select2Onload();
  138. } else {
  139. $head.append('<link href="' + (protocol + config.select2.css) + '" rel="stylesheet">');
  140. $.getScript(protocol + config.select2.js, select2Onload);
  141. }
  142. });
  143. },
  144. /** 版本比较: 大于 */
  145. versionMoreThan = function(version, moreThan) {
  146. version = version.split('.');
  147. moreThan = moreThan.split('.');
  148. for (var i = 0; i < version.length; i++) {
  149. var moreThan_i = i < moreThan.length ? Number(moreThan[i]) : 0;
  150. if (version[i] > moreThan_i) {
  151. return true;
  152. } else if (version[i] < moreThan_i) {
  153. return false;
  154. }
  155. }
  156. return false;
  157. };
  158.  
  159. // TODO enter
  160. if (typeof jQuery == 'function') {
  161. if (versionMoreThan(jQuery.fn.jquery, config.jquery._1_6_4)) {
  162. jQueryOnload();
  163. return;
  164. } else if (!versionMoreThan(jQuery.fn.jquery, config.jquery._1_3_2)) {
  165. return;
  166. }
  167. }
  168. // append jQuery
  169. noConflict = true;
  170. setTimeout(function() {
  171. var jQueryScript = document.createElement('SCRIPT');
  172. jQueryScript.src = protocol + config.jquery.js;
  173. jQueryScript.onload = jQueryOnload;
  174. document.head.appendChild(jQueryScript);
  175. }, config.timeout);
  176. }, 3000);