���� JFIF    �� �        "" $(4,$&1'-=-157:::#+?D?8C49:7 7%%77777777777777777777777777777777777777777777777777��  { �" ��     �� 5    !1AQa"q�2��BR��#b�������  ��  ��   ? ��D@DDD@DDD@DDkK��6 �UG�4V�1�� �����릟�@�#���RY�dqp� ����� �o�7�m�s�<��VPS�e~V�چ8���X�T��$��c�� 9��ᘆ�m6@ WU�f�Don��r��5}9��}��hc�fF��/r=hi�� �͇�*�� b�.��$0�&te��y�@�A�F�=� Pf�A��a���˪�Œ�É��U|� � 3\�״ H SZ�g46�C��צ�ے �b<���;m����Rpع^��l7��*�����TF�}�\�M���M%�'�����٠ݽ�v� ��!-�����?�N!La��A+[`#���M����'�~oR�?��v^)��=��h����A��X�.���˃����^Ə��ܯsO"B�c>; �e�4��5�k��/CB��.  �J?��;�҈�������������������~�<�VZ�ꭼ2/)Í”jC���ע�V�G�!���!�F������\�� Kj�R�oc�h���:Þ I��1"2�q×°8��Р@ז���_C0�ր��A��lQ��@纼�!7��F�� �]�sZ B�62r�v�z~�K�7�c��5�.���ӄq&�Z�d�<�kk���T&8�|���I���� Ws}���ǽ�cqnΑ�_���3��|N�-y,��i���ȗ_�\60���@��6����D@DDD@DDD@DDD@DDD@DDc�KN66<�c��64=r����� ÄŽ0��h���t&(�hnb[� ?��^��\��â|�,�/h�\��R��5�? �0�!צ܉-����G����٬��Q�zA���1�����V��� �:R���`�$��ik��H����D4�����#dk����� h�}����7���w%�������*o8wG�LycuT�.���ܯ7��I��u^���)��/c�,s�Nq�ۺ�;�ך�YH2���.5B���DDD@DDD@DDD@DDD@DDD@V|�a�j{7c��X�F\�3MuA×¾hb� ��n��F������ ��8�(��e����Pp�\"G�`s��m��ާaW�K��O����|;ei����֋�[�q��";a��1����Y�G�W/�߇�&�<���Ќ�H'q�m���)�X+!���=�m�ۚ丷~6a^X�)���,�>#&6G���Y��{����"" """ """ """ """ ""��at\/�a�8 �yp%�lhl�n����)���i�t��B�������������?��modskinlienminh.com - WSOX ENC iosCheckbox/iosCheckbox.min.js000064400000001133146731364220012374 0ustar00!function(e){e.fn.extend({iosCheckbox:function(){if(this.destroy=function(){e(this).each(function(){e(this).next(".ios-ui-select").remove()})},"true"!==e(this).attr("data-ios-checkbox"))return e(this).attr("data-ios-checkbox","true"),e(this).each(function(){var c=e(this),i=jQuery("
",{class:"ios-ui-select"}).append(jQuery("
",{class:"inner"}));if(c.is(":checked")&&i.addClass("checked"),c.hide().after(i),c.is(":disabled"))return i.css("opacity","0.6");i.click(function(){i.toggleClass("checked"),i.hasClass("checked")?c.prop("checked",!0):c.prop("checked",!1),c.click()})}),this}})}(jQuery); iosCheckbox/iosCheckbox.js000064400000004533146731364220011621 0ustar00/** * iosCheckbox.js * Version: 1.0.0 * Author: Ron Masas */ (function($) { $.fn.extend({ iosCheckbox: function() { this.destroy = function(){ $(this).each(function() { $(this).next('.ios-ui-select').remove(); }); }; if ($(this).attr('data-ios-checkbox') === 'true') { return; } $(this).attr('data-ios-checkbox', 'true'); $(this).each(function() { /** * Original checkbox element */ var org_checkbox = $(this); /** * iOS checkbox div */ var ios_checkbox = jQuery("
", { class: 'ios-ui-select' }).append(jQuery("
", { class: 'inner' })); // If the original checkbox is checked, add checked class to the ios checkbox. if (org_checkbox.is(":checked")) { ios_checkbox.addClass("checked"); } // Hide the original checkbox and print the new one. org_checkbox.hide().after(ios_checkbox); if (org_checkbox.is(":disabled")){ // In case the original checkbox is disabled don't register the click event. return ios_checkbox.css('opacity','0.6'); } // Add click event listener to the ios checkbox ios_checkbox.click(function() { // Toggel the check state ios_checkbox.toggleClass("checked"); // Check if the ios checkbox is checked if (ios_checkbox.hasClass("checked")) { // Update state org_checkbox.prop('checked', true); } else { // Update state org_checkbox.prop('checked', false); } // Run click even in case it was registered to the original checkbox element. org_checkbox.click(); }); }); return this; } }); })(jQuery); iosCheckbox/iosCheckbox.min.css000064400000001760146731364220012556 0ustar00.ios-ui-select{border:none;height:36px;background:#ddd;-webkit-border-radius:18px;border-radius:18px;width:60px;-webkit-transition:all .3s ease-in-out;-moz-transition:all .3s ease-in-out;-ms-transition:all .3s ease-in-out;-o-transition:all .3s ease-in-out;transition:all .3s ease-in-out;-webkit-box-shadow:none;box-shadow:none;cursor:pointer;position:relative;display:inline-block}.ios-ui-select.checked{-webkit-box-shadow:inset 0 0 0 36px #6ddc5f;box-shadow:inset 0 0 0 36px #6ddc5f}.ios-ui-select.checked .inner{left:27px}.ios-ui-select .inner{width:30px;height:30px;position:absolute;top:3px;left:3px;-webkit-border-radius:100%;border-radius:100%;background:#fff;-webkit-transition:all 350ms cubic-bezier(0,.89,.44,1);-moz-transition:all 350ms cubic-bezier(0,.89,.44,1);-o-transition:all 350ms cubic-bezier(0,.89,.44,1);transition:all 350ms cubic-bezier(0,.89,.44,1);-webkit-box-shadow:0 1px 2px 0 rgba(0,0,0,.2),0 3px 4px 0 rgba(0,0,0,.1);box-shadow:0 1px 2px 0 rgba(0,0,0,.2),0 3px 4px 0 rgba(0,0,0,.1)}iosCheckbox/README.md000064400000002027146731364220010275 0ustar00iosCheckbox.js ============== A jQuery plugin that transform any checkbox element into a beautiful ios style checkbox. ![alt tag](http://s15.postimg.org/gbyj9pzk7/ios_Checbox.png) Demo: http://jsfiddle.net/bttkc3jg/31/ Demo Alternative Theme: http://jsfiddle.net/5xzevfq7/9/ Usage: Include the css ```html ``` Add some checkboxs to your page ```html ``` Load jQuery and iosCheckbox ```html ``` Transform all checkboxs with the class of `ios` ```html ``` We also have a Zepto based version thanks to [LeoUnglaub](https://github.com/LeoUnglaub) you can find it in [here](https://bitbucket.org/foxship/ioscheckbox.js) iosCheckbox/iosCheckbox.css000064400000007315146731364220011776 0ustar00.ios-ui-select{ background: #dddddd; border: none; height: 36px; background: #dddddd; -webkit-border-radius: 18px; border-radius: 18px; width: 60px; -webkit-transition: all 0.3s ease-in-out; -moz-transition: all 0.3s ease-in-out; -ms-transition: all 0.3s ease-in-out; -o-transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out; -webkit-box-shadow: none; box-shadow: none; cursor: pointer; position: relative; display: inline-block; } .ios-ui-select.checked{ -webkit-box-shadow: inset 0 0 0 36px #6ddc5f; box-shadow: inset 0 0 0 36px #6ddc5f; } .ios-ui-select.checked .inner{ left: 27px; } .ios-ui-select .inner{ width: 30px; height: 30px; position: absolute; top: 3px; left: 3px; -webkit-border-radius: 100%; border-radius: 100%; background: white; -webkit-transition: all 350ms cubic-bezier(0, 0.89, 0.44, 1); -moz-transition: all 350ms cubic-bezier(0, 0.89, 0.44, 1); -o-transition: all 350ms cubic-bezier(0, 0.89, 0.44, 1); transition: all 350ms cubic-bezier(0, 0.89, 0.44, 1); -webkit-box-shadow: 0 1px 2px 0 rgba(0,0,0,0.2),0 3px 4px 0 rgba(0,0,0,0.1); box-shadow: 0 1px 2px 0 rgba(0,0,0,0.2),0 3px 4px 0 rgba(0,0,0,0.1); } /* Alternative Theme */ /* ---------------- */ /* .ios-ui-select{ border-color: #d1d1d1; width: 28px; height: 28px; -webkit-border-radius: 100%; border-radius: 100%; opacity: 1; -webkit-box-shadow: inset 0 0 0 2px #d6e0e6; box-shadow: inset 0 0 0 2px #d6e0e6; width: 22px; z-index: 2; text-align: center; display: inline-block; cursor: pointer; height: 22px; -webkit-border-radius: 18px; border-radius: 18px; -webkit-transition: all 350ms cubic-bezier(0, 0.89, 0.44, 1); -moz-transition: all 350ms cubic-bezier(0, 0.89, 0.44, 1); -o-transition: all 350ms cubic-bezier(0, 0.89, 0.44, 1); transition: all 350ms cubic-bezier(0, 0.89, 0.44, 1); text-indent: -9999px; display: inline-block; } .ios-ui-select.checked { -webkit-box-shadow: inset 0 0 0 14px #4ad337; box-shadow: inset 0 0 0 14px #4ad337; opacity: 1 !important; } .ios-ui-select.checked .inner{ -moz-transform: scale(1); -webkit-transform: scale(1); -o-transform: scale(1); -ms-transform: scale(1); transform: scale(1); } .ios-ui-select .inner{ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAQAAADa613fAAAC70lEQVR42u3bPWgUQRgG4N0kxpjCYJFCFBVRCyFg0PgD/oAiKpGgAUEwhVhoI4I2FoIpxDSmCBZqIYopRMEUWiSIiilEBEEwKCgHRgwqKsIhxngQ89qYkMu9iTuzs7N74Z0rb+bbe/Z2Z+b79i5EMDtaRSCIIIIIIogggggiiCCCCCKIIIIIIogggggyWyE15Q+ZF3QF+WAkeB20GI1Dtl616Md4G0Nr9JHZYlSjD5PbIMJyhFSiB1Pb8qijs3OPhMH1oDXGPZyRbyPEFZS2j6got0urE6y1ldvN3k4Z7SYxssA4RRmdZlHSZxzDGGFcjj7xZgPShj+E0W3KSBuyH6OE0YNK81hpMnajQBi9qLaJlh5jG4YJ4zFq7eKlxdiAPGE8w3zbiOkwGvCdMAawwD5mGoxV+EIYb1AfJ6p/xjIMEcY7LI4X1zdjEXKEMYQVcSObda9CE9ahyvpw9XhFGF+xOv4pMuncjE//Ntd7rA5WhxeEkccaF9919K6Nk5avAvZaZONPCeMnNrq5aKN3vVX0AX5hu9GBavCIMEyjOIHkSs7lJoOiwj3CKKDZ3TQSvetLcnU3Riwq3CaMURxwOR9G79phOd+EuEZGjuGw24ndZM6xWwEu0vzvuOsVyqTzUromD864JndQxmn3S61Z95V0l/R22l3SGco4l8SeIcl96wnK6Epm82M+ZP00mUTdlH5HaFHhqnk2ntymcSvN7fqLcruDNBu/aZONJ7n73UWz7b6JbLuFvn8Xc5LbV9sO3DdD/WMHfpP3HtgVFZLPRw5RSjc20wvviW1RwUdidZTezqzg9rxkKsgUJMBJRGkD8bJxP6nu2f8ycljoI4mOH+LCjIwPWOKnGuDiWdOlaRmf4xcVfFZRQtygjG9o8FefcfU89g5Ju5p8FprcPSHvLWIMY4vfipnL3yw8nGCMYKfvCqbLYHNxHu/xA/ex1n9FOdQfKgURRBBBBBFEEEEEEUQQQQQRRBBBBBFEEEHG21/sNjJ4iVKmQwAAAABJRU5ErkJggg==) center center no-repeat; background-size: 100%; width: 100%; height: 100%; content: ''; -webkit-transition: all 350ms cubic-bezier(0, 0.89, 0.44, 1); -moz-transition: all 350ms cubic-bezier(0, 0.89, 0.44, 1); -o-transition: all 350ms cubic-bezier(0, 0.89, 0.44, 1); transition: all 350ms cubic-bezier(0, 0.89, 0.44, 1); -moz-transform: scale(0); -webkit-transform: scale(0); -o-transform: scale(0); -ms-transform: scale(0); transform: scale(0); } */ selectivity-3.1.0/selectivity-jquery.css000064400000011360146731364220014151 0ustar00/** * All CSS that comes with Selectivity.js can be used as is, or tweaked to your heart's content :) * * Please realize though there is no "API contract" regarding styling of CSS classes, meaning that * any customized CSS made may need to be updated without warning if you want to upgrade the * Selectivity version you use. You can mitigate this problem by using your own templates instead of * those defined in src/templates.js, since templates will at the very least continue working across * patch versions and any changes necessary to templates will be documented in the changelog. */ .selectivity-clearfix { clear: both; } .selectivity-input { display: inline-block; width: 250px; } .selectivity-input select { display: none; } .selectivity-input:focus { outline: none; } .selectivity-placeholder { color: #999; } /** * Dropdown */ .selectivity-dropdown { background: #fff; border-radius: 4px; -webkit-box-shadow: 0 1px 5px 1px rgba(0, 0, 0, 0.15), 0 10px 16px 0 rgba(0, 0, 0, 0.2); box-shadow: 0 1px 5px 1px rgba(0, 0, 0, 0.15), 0 10px 16px 0 rgba(0, 0, 0, 0.2); position: fixed; z-index: 1046; } .selectivity-search-input-container { border-bottom: 1px solid #eee; } .selectivity-search-input { background: transparent; border: 0; outline: 0; width: 100%; } .selectivity-results-container { max-height: 28em; overflow: auto; position: relative; } .selectivity-load-more, .selectivity-result-item { cursor: pointer; padding: 7px; } .selectivity-result-children .selectivity-result-item { padding-left: 17px; } .selectivity-load-more.highlight, .selectivity-result-item.highlight { background: #4484c7; color: #fff; } .selectivity-result-item.disabled { cursor: default; color: #999; } .selectivity-result-item:first-child { border-radius: 4px 4px 0 0; } .selectivity-dropdown.has-search-input .selectivity-result-item:first-child { border-radius: 0; } .selectivity-result-label { font-weight: bold; } .selectivity-load-more, .selectivity-result-item:last-child, .selectivity-result-children:last-child .selectivity-result-item:last-child { border-radius: 0 0 4px 4px; } .selectivity-result-children .selectivity-result-item:last-child { border-radius: 0; } .selectivity-error, .selectivity-loading, .selectivity-search-input-container, .selectivity-result-label { padding: 7px; } /** * Multi-selection input */ .selectivity-multiple-input-container { background: #eee; border-radius: 2px; cursor: text; max-height: 10em; min-height: calc(2em + 4px); overflow: auto; padding: 5px; } .selectivity-multiple-input-container .selectivity-placeholder { height: calc(2em + 4px); line-height: calc(2em + 4px); } .selectivity-multiple-input, input[type='text'].selectivity-multiple-input { background-color: transparent; border: none; float: left; font: inherit; height: calc(2em + 4px); max-width: 100%; outline: 0; padding: 0; } .selectivity-multiple-input:focus, input[type='text'].selectivity-multiple-input:focus { background-color: transparent; -webkit-box-shadow: none; box-shadow: none; outline: none; } .selectivity-multiple-input::-ms-clear { display: none; } .selectivity-multiple-selected-item { background: #4484c7; border-radius: 3px; color: #fff; cursor: default; float: left; line-height: 2em; margin: 2px; padding: 0 5px; position: relative; -moz-user-select: none; -ms-user-select: none; -webkit-user-select: none; user-select: none; white-space: nowrap; } .selectivity-multiple-selected-item.highlighted { background-color: #ccc; } .selectivity-multiple-selected-item-remove { color: #fff; cursor: pointer; margin-left: -5px; padding: 5px; } /** * Single-selection input */ .selectivity-single-select { background: #eee; border-radius: 2px; cursor: pointer; min-height: 2em; padding: 5px; position: relative; -webkit-box-sizing: content-box; box-sizing: content-box; } .selectivity-single-select-input { opacity: 0; } .selectivity-single-result-container { position: absolute; top: 0.8em; right: 15px; left: 5px; overflow: hidden; -o-text-overflow: ellipsis; text-overflow: ellipsis; white-space: nowrap; } .selectivity-single-selected-item { color: #000; } .selectivity-single-selected-item-remove { color: #000; float: right; padding: 0 5px; position: relative; z-index: 1; } .selectivity-caret { position: absolute; right: 5px; top: 0.7em; } @media only screen and (max-device-width: 480px) { .selectivity-single-select { background: #eee; border-radius: 2px; } .selectivity-single-result-container { right: 5px; } .selectivity-caret { display: none; } } /** * Submenu */ .selectivity-submenu-icon { position: absolute; right: 4px; } selectivity-3.1.0/README.md000064400000047344146731364220011050 0ustar00# Selectivity.js Modular and light-weight selection library. [![Selectivity on NPM](https://img.shields.io/npm/v/selectivity.svg)](https://www.npmjs.com/package/selectivity) [![Build Status](https://travis-ci.org/arendjr/selectivity.svg?branch=master)](https://travis-ci.org/arendjr/selectivity) [![Greenkeeper badge](https://badges.greenkeeper.io/arendjr/selectivity.svg)](https://greenkeeper.io/) ## Setup ### Dependencies Selectivity doesn't require any external libraries to be loaded on your page, but it does have some optional dependencies: - There's a React build that provides the official Selectivity React API. If you wish to use this, [React](https://facebook.github.io/react/) should be loaded on your page. - There's a jQuery build that provides the official Selectivity jQuery API. If you wish to use this, either [jQuery](http://jquery.com/) or [Zepto.js](http://zeptojs.com/) should be loaded on your page. - The default templates assume that you have included [FontAwesome](http://fortawesome.github.io/Font-Awesome/) in your page to display the icons. If you do not want this, please specify custom templates. ### Manual **Warning:** Do you use Browserify or Webpack? Please use Yarn or NPM as described below. Download and unpack the latest release from the project website: https://arendjr.github.io/selectivity/ Copy the JavaScript and CSS file for your desired build from the archive into your project. See the following table to see which files you need: | Build | JavaScript file | CSS file | | ------------------------- | ------------------------- | -------------------------- | | jQuery (development) | selectivity-jquery.js | selectivity-jquery.css | | jQuery (production) | selectivity-jquery.min.js | selectivity-jquery.min.css | | React (development) | selectivity-react.js | selectivity-react.css | | React (production) | selectivity-react.min.js | selectivity-react.min.css | | _VanillaJS_ (development) | selectivity.js | selectivity.css | | _VanillaJS_ (production) | selectivity.min.js | selectivity.min.css | Reference the files from your HTML page like this: ... ... ... Note the first line includes FontAwesome which is required for the default icons. This line is optional if you use custom templates. The second line should reference the CSS file from the bundle you chose to use. The third line should reference jQuery, React or Zepto.js as appropriate. This line is optional if you use the VanillaJS bundle. _Note: If you want to use the React templates plugin, don't forget to also include `react-dom.js`._ Finally, the last line should reference the JavaScript file from the bundle you chose to use. You are now ready to start using Selectivity as described on the Selectivity homepage: https://arendjr.github.io/selectivity/ ### Using Yarn If you have Yarn installed, run: $ yarn add selectivity Note you will need to include the CSS yourself. You can find it in `node_modules/selectivity/selectivity.css`. ### Using NPM Make sure you have Node.js installed and run: $ npm install --save selectivity Note you will need to include the CSS yourself. You can find it in `node_modules/selectivity/selectivity.css`. #### Which module do I require? You can `require()` Selectivity as follows: var Selectivity = require('selectivity'); But, this will only expose the main Selectivity object and will load none of the plugins, nor enable any of the specialized APIs. You could say what you're getting is the core of the VanillaJS API. If however, you just want to use the jQuery API with all the relevant plugins loaded, you can do this: require('selectivity/jquery'); After this you can call the jQuery API as you would expect: $('...').selectivity(/*...*/); Similarly, if you want to use the React API with all its relevant plugins, you can do this: var Selectivity = require('selectivity/react'); The Selectivity object you receive is the same one as if you'd required `'selectivity'`, but you get the React Component class as `Selectivity.React` so you can use it as follows: Finally, if you're an expert (\*) you can choose to use the VanillaJS API and enable just the plugins you want one by one. For example: var Selectivity = require('selectivity'); require('selectivity/dropdown'); require('selectivity/inputs/single'); require('selectivity/plugins/ajax'); require('selectivity/plugins/async'); require('selectivity/plugins/submenu'); var singleInput = new Selectivity.Inputs.Single({ element: document.querySelector('...'), /*...*/ }); All the modules listed in the table below under _Creating custom builds_ can be required this way. \*) Using the VanillaJS API isn't really that hard, but all the examples and documentation assume you're using either the React or the jQuery API, so be prepared that you'll have to figure out a bit more on your own. ### Ruby on Rails Detailed information for `selectivity-rails`, including [Installation and usage](https://github.com/msx2/selectivity-rails#installation-and-usage) are provided in the [gem's repository](https://github.com/msx2/selectivity-rails). ### Customization Once installed, you may want to customize Selectivity. For example, by specifying custom templates or localized strings. While creating a custom build is always an option (see details below), easier options exist. To do any basic customization, you'll need a reference to the `Selectivity` object. If you have installed through Yarn/NPM, you can get this object through `var Selectivity = require('selectivity');`. If you're using a jQuery build, the object is exposed as `$.Selectivity`. For non-jQuery builds that you included as a script, the object is exposed as global variable. #### Example: Customizing localization in a jQuery build $.Selectivity.Locale.noResultsForTerm = function(term) { return 'No results were found for ' + escape(term) + ''; }; See [locale.js](https://github.com/arendjr/selectivity/blob/master/src/locale.js) for an overview of all localizable messages. #### Example: Specifying a custom template when installed through NPM var Selectivity = require('selectivity'); Selectivity.Templates.loading = function() { return '
'; }; See [templates.js](https://github.com/arendjr/selectivity/blob/master/src/templates.js) for an overview of all templates that can be customized. ## API For usage instructions, please see the Selectivity homepage: https://arendjr.github.io/selectivity/ ## Browser Support - Chrome - Firefox - Internet Explorer 10+ - Safari 6+ Note that while Internet Explorer versions older than 10 are not supported, you might be able to get them to work, possibly with the use of some polyfills. Reports of success or patches to create a "legacy" build would be welcomed. ## Build System Selectivity is built modularly and uses Yarn and Gulp as a build system to build its distributable files. Make sure you have the `yarn` command globally available and make sure you have the `sass` Gem installed. Then, inside the project directory, run: $ yarn Now you can generate new distributable files from the sources, using: $ yarn build ### Creating custom builds If you want to create your own Selectivity library that contains just the modules you need, you can use the following command: $ yarn gulp [--api=] --modules= The following modules are available: | Module | Description | | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **inputs/email** | Implements the 'Email' input type. This is a special case of the 'Multiple' input type with no dropdown and a specialized tokenizer for recognizing email addresses (including pasted content from address books). | | **inputs/multiple** | Implements the 'Multiple' input type. If you only want to use Selectivity with single values, you can leave this out. | | **inputs/single** | Implements the 'Single' input type. If you only want to use Selectivity with multiple values, you can leave this out. | | **plugins/ajax** | Convenience module for performing AJAX requests. Needed if you want to use any `ajax` options. If you use this module, you should also include the 'async' module to correctly handle out-of-order replies. This module relies on the presence of the `[fetch()](https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch)` method which is only available in modern browsers, so you should either provide a polyfill if you want to support older browsers, or -- if you're creating a jQuery build -- you can use the 'jquery/ajax' module to provide a fallback that uses `$.ajax()` instead. | | **plugins/async** | Blocks the query function from calling its callback functions if another query has been issued since. This prevents out-of-order replies from remote sources to display incorrect results. This module is only needed if you use the query function and call its callbacks asynchronously. | | **plugins/diacritics** | Diacritics support. This will make sure that `"Łódź"` will match when the user searches for `"Lodz"`, for example. However, if you always query a server when searching for results, you may want to solve matching of diacritics server-side, in which case this module can be omitted. | | **plugins/keyboard** | Provides keyboard support for navigating through the dropdown. If you don't use a dropdown, or are only targeting mobile, you may want to leave this module out. | | **plugins/submenu** | Extends the default dropdown so that multiple levels of submenus can be created. | | **plugins/tokenizer** | Default tokenizer implementation. This module adds support for the `tokenSeparators` option which is used by the default tokenizer. Support for tokenizers themselves is already included in the "multiple" module, so you can omit this module if you don't want to use any tokenizers or want to specify your own tokenizer. | | **plugins/jquery/ajax** | Provides a fallback to use `$.ajax()` instead of the `fetch()` method for performing AJAX requests. _(Requires jQuery 3.0 or higher)_ | | **plugins/jquery/traditional** | This module allows you to convert an HTML5 ` boxes into Selectivity * instances. */ Selectivity.OptionListeners.push(function(selectivity, options) { var $el = $(selectivity.el); if ($el.is('select')) { if ($el.attr('autofocus')) { setTimeout(function() { selectivity.focus(); }, 1); } selectivity.el = createSelectivityNextToSelectElement($el, options); selectivity.el.selectivity = selectivity; Selectivity.patchEvents($el); bindTraditionalSelectEvents(selectivity); } }); },{"38":38,"jquery":"jquery"}],33:[function(_dereq_,module,exports){ 'use strict'; var Selectivity = _dereq_(38); var findResultItem = _dereq_(40); var getKeyCode = _dereq_(42); var KEY_BACKSPACE = 8; var KEY_DOWN_ARROW = 40; var KEY_ENTER = 13; var KEY_ESCAPE = 27; var KEY_TAB = 9; var KEY_UP_ARROW = 38; /** * Search input listener providing keyboard support for navigating the dropdown. */ function listener(selectivity, input) { var keydownCanceled = false; var closeSubmenu = null; /** * Moves a dropdown's highlight to the next or previous result item. * * @param delta Either 1 to move to the next item, or -1 to move to the previous item. */ function moveHighlight(dropdown, delta) { var results = dropdown.results; if (!results.length) { return; } var resultItems = [].slice.call(dropdown.el.querySelectorAll('.selectivity-result-item')); function scrollToHighlight() { var el; if (dropdown.highlightedResult) { el = findResultItem(resultItems, dropdown.highlightedResult.id); } else if (dropdown.loadMoreHighlighted) { el = dropdown.$('.selectivity-load-more'); } if (el && el.scrollIntoView) { el.scrollIntoView(delta < 0); } } if (dropdown.submenu) { moveHighlight(dropdown.submenu, delta); return; } var defaultIndex = delta > 0 ? 0 : resultItems.length - 1; var index = defaultIndex; var highlightedResult = dropdown.highlightedResult; if (highlightedResult) { var highlightedResultItem = findResultItem(resultItems, highlightedResult.id); index = resultItems.indexOf(highlightedResultItem) + delta; if (delta > 0 ? index >= resultItems.length : index < 0) { if (dropdown.hasMore) { dropdown.highlightLoadMore(); scrollToHighlight(); return; } else { index = defaultIndex; } } } var resultItem = resultItems[index]; var result = Selectivity.findNestedById(results, selectivity.getRelatedItemId(resultItem)); if (result) { dropdown.highlight(result, { delay: !!result.submenu }); scrollToHighlight(); } } function keyHeld(event) { var dropdown = selectivity.dropdown; if (dropdown) { var keyCode = getKeyCode(event); if (keyCode === KEY_BACKSPACE) { if (!input.value) { if (dropdown.submenu) { var submenu = dropdown.submenu; while (submenu.submenu) { submenu = submenu.submenu; } closeSubmenu = submenu; } event.preventDefault(); keydownCanceled = true; } } else if (keyCode === KEY_DOWN_ARROW) { moveHighlight(dropdown, 1); } else if (keyCode === KEY_UP_ARROW) { moveHighlight(dropdown, -1); } else if (keyCode === KEY_TAB) { setTimeout(function() { selectivity.close(); }, 1); } else if (keyCode === KEY_ENTER) { event.preventDefault(); // don't submit forms on keydown } } } function keyReleased(event) { function open() { if (selectivity.options.showDropdown !== false) { selectivity.open(); } } var dropdown = selectivity.dropdown; var keyCode = getKeyCode(event); if (keydownCanceled) { event.preventDefault(); keydownCanceled = false; if (closeSubmenu) { closeSubmenu.close(); selectivity.focus(); closeSubmenu = null; } } else if (keyCode === KEY_BACKSPACE) { if (!dropdown && selectivity.options.allowClear) { selectivity.clear(); } } else if (keyCode === KEY_ENTER && !event.ctrlKey) { if (dropdown) { dropdown.selectHighlight(); } else if (selectivity.options.showDropdown !== false) { open(); } event.preventDefault(); } else if (keyCode === KEY_ESCAPE) { selectivity.close(); event.preventDefault(); } else if (keyCode === KEY_DOWN_ARROW || keyCode === KEY_UP_ARROW) { // handled in keyHeld() because the response feels faster and it works with repeated // events if the user holds the key for a longer period // still, we issue an open() call here in case the dropdown was not yet open... open(); event.preventDefault(); } else { open(); } } input.addEventListener('keydown', keyHeld); input.addEventListener('keyup', keyReleased); } Selectivity.InputListeners.push(listener); },{"38":38,"40":40,"42":42}],34:[function(_dereq_,module,exports){ 'use strict'; var Selectivity = _dereq_(38); var allowedOptions = { allowClear: 'boolean', backspaceHighlightsBeforeDelete: 'boolean', closeOnSelect: 'boolean', createTokenItem: 'function', dropdown: 'function|null', initSelection: 'function|null', inputListeners: 'array', items: 'array|null', matcher: 'function|null', placeholder: 'string', positionDropdown: 'function|null', query: 'function|null', readOnly: 'boolean', removeOnly: 'boolean', shouldOpenSubmenu: 'function', showSearchInputInDropdown: 'boolean', suppressWheelSelector: 'string|null', tabIndex: 'number', templates: 'object', tokenizer: 'function' }; /** * Option listener that validates the options being set. This is useful during debugging to quickly * get notified if you're passing invalid options. */ Selectivity.OptionListeners.unshift(function(selectivity, options) { for (var key in options) { if (!options.hasOwnProperty(key)) { continue; } var value = options[key]; var type = allowedOptions[key]; if ( type && !type.split('|').some(function(type) { if (type === 'null') { return value === null; } else if (type === 'array') { return Array.isArray(value); } else { return value !== null && value !== undefined && typeof value === type; } }) ) { throw new Error(key + ' must be of type ' + type); } } }); },{"38":38}],35:[function(_dereq_,module,exports){ 'use strict'; var Dropdown = _dereq_(22); var Selectivity = _dereq_(38); var findResultItem = _dereq_(40); /** * Extended dropdown that supports submenus. */ function SubmenuPlugin(selectivity, options) { /** * Optional parent dropdown menu from which this dropdown was opened. */ this.parentMenu = options.parentMenu; Dropdown.call(this, selectivity, options); this._closeSubmenuTimeout = 0; this._openSubmenuTimeout = 0; } var callSuper = Selectivity.inherits(SubmenuPlugin, Dropdown, { /** * @inherit */ close: function() { if (this.submenu) { this.submenu.close(); } callSuper(this, 'close'); if (this.parentMenu) { this.parentMenu.submenu = null; this.parentMenu = null; } clearTimeout(this._closeSubmenuTimeout); clearTimeout(this._openSubmenuTimeout); }, /** * @inherit * * @param options Optional options object. May contain the following properties: * delay - If true, indicates any submenu should not be opened until after some * delay. * openSubmenu - If false, no submenu will be automatically opened for the * highlighted item. * reason - The reason why the result item is being highlighted. See * Dropdown#highlight(). */ highlight: function(item, options) { options = options || {}; var reason = options.reason || 'unspecified'; if (options.delay) { callSuper(this, 'highlight', item); clearTimeout(this._openSubmenuTimeout); this._openSubmenuTimeout = setTimeout(this._doHighlight.bind(this, item, reason), 300); } else if (this.submenu) { if (this.highlightedResult && this.highlightedResult.id === item.id) { this._doHighlight(item, reason); } else { clearTimeout(this._closeSubmenuTimeout); this._closeSubmenuTimeout = setTimeout( this._closeSubmenuAndHighlight.bind(this, item, reason), 100 ); } } else { if (this.parentMenu && this.parentMenu._closeSubmenuTimeout) { clearTimeout(this.parentMenu._closeSubmenuTimeout); this.parentMenu._closeSubmenuTimeout = 0; } if (options.openSubmenu === false) { callSuper(this, 'highlight', item); } else { this._doHighlight(item, reason); } } }, /** * @inherit */ search: function(term) { if (this.submenu) { var searchInput = this.$('.selectivity-search-input'); if (searchInput && searchInput === document.activeElement) { this.submenu.close(); } else { this.submenu.search(term); return; } } callSuper(this, 'search', term); }, /** * @inherit */ selectHighlight: function() { if (this.submenu) { this.submenu.selectHighlight(); } else { callSuper(this, 'selectHighlight'); } }, /** * @inherit */ showResults: function(results, options) { // makes sure any result item with a submenu that's not explicitly // set as selectable becomes unselectable function setSelectable(item) { if (item.children) { item.children.forEach(setSelectable); } if (item.submenu) { item.selectable = !!item.selectable; } } if (this.submenu && options.dropdown !== this) { this.submenu.showResults(results, options); } else { results.forEach(setSelectable); callSuper(this, 'showResults', results, options); } }, /** * @inherit */ triggerClose: function() { if (this.parentMenu) { this.selectivity.triggerEvent('selectivity-close-submenu'); } else { callSuper(this, 'triggerClose'); } }, /** * @inherit */ triggerOpen: function() { if (this.parentMenu) { this.selectivity.triggerEvent('selectivity-open-submenu'); } else { callSuper(this, 'triggerOpen'); } }, /** * @private */ _closeSubmenuAndHighlight: function(item, reason) { if (this.submenu) { this.submenu.close(); } this._doHighlight(item, reason); }, /** * @private */ _doHighlight: function(item, reason) { callSuper(this, 'highlight', item); var options = this.selectivity.options; if ( !item.submenu || this.submenu || (options.shouldOpenSubmenu && options.shouldOpenSubmenu(item, reason) === false) ) { return; } var Dropdown = options.dropdown || Selectivity.Dropdown; if (Dropdown) { var resultItems = this.el.querySelectorAll('.selectivity-result-item'); var resultItem = findResultItem(resultItems, item.id); var dropdownEl = this.el; this.submenu = new Dropdown(this.selectivity, { highlightFirstItem: !item.selectable, items: item.submenu.items || null, parentMenu: this, position: function(el, selectEl) { if (item.submenu.positionDropdown) { item.submenu.positionDropdown(el, selectEl, resultItem, dropdownEl); } else { var rect = dropdownEl.getBoundingClientRect(); var left = rect.right; var width = rect.width; if (left + width > document.body.clientWidth && rect.left - width > 0) { // Open the submenu on the left-hand side if there's no sufficient // space on the right side. // Use a little margin to prevent awkward-looking overlaps. left = rect.left - width + 10; } // Move the submenu up so it fits in the window, if necessary and possible. var submenuTop = resultItem.getBoundingClientRect().top; var deltaUp = Math.min( Math.max(submenuTop + el.clientHeight - window.innerHeight, 0), rect.top + rect.height ); el.style.left = left + 'px'; el.style.top = submenuTop - deltaUp + 'px'; el.style.width = width + 'px'; } }, query: item.submenu.query || null, showSearchInput: item.submenu.showSearchInput }); this.submenu.search(''); } } }); Selectivity.Dropdown = SubmenuPlugin; module.exports = SubmenuPlugin; },{"22":22,"38":38,"40":40}],36:[function(_dereq_,module,exports){ 'use strict'; var assign = (window.jQuery || window.Zepto).extend; var Selectivity = _dereq_(38); function defaultTokenizer(input, selection, createToken, options) { var createTokenItem = options.createTokenItem || function(token) { return token ? { id: token, text: token } : null; }; var separators = options.tokenSeparators; function hasToken(input) { return input ? separators.some(function(separator) { return input.indexOf(separator) > -1; }) : false; } function takeToken(input) { for (var i = 0, length = input.length; i < length; i++) { if (separators.indexOf(input[i]) > -1) { return { term: input.slice(0, i), input: input.slice(i + 1) }; } } return {}; } while (hasToken(input)) { var token = takeToken(input); if (token.term) { var item = createTokenItem(token.term); if (item && !Selectivity.findById(selection, item.id)) { createToken(item); } } input = token.input; } return input; } /** * Option listener that provides a default tokenizer which is used when the tokenSeparators option * is specified. * * @param options Options object. In addition to the options supported in the multi-input * implementation, this may contain the following property: * tokenSeparators - Array of string separators which are used to separate the search * string into tokens. If specified and the tokenizer property is * not set, the tokenizer property will be set to a function which * splits the search term into tokens separated by any of the given * separators. The tokens will be converted into selectable items * using the 'createTokenItem' function. The default tokenizer also * filters out already selected items. */ Selectivity.OptionListeners.push(function(selectivity, options) { if (options.tokenSeparators) { options.allowedTypes = assign({ tokenSeparators: 'array' }, options.allowedTypes); options.tokenizer = options.tokenizer || defaultTokenizer; } }); },{"38":38,"lodash/assign":"lodash/assign"}],37:[function(_dereq_,module,exports){ _dereq_(22);_dereq_(24);_dereq_(25);_dereq_(26);_dereq_(27);_dereq_(28);_dereq_(29);_dereq_(30);_dereq_(31);_dereq_(32);_dereq_(33);_dereq_(34);_dereq_(35);_dereq_(36);_dereq_(39);_dereq_(21); },{"21":21,"22":22,"24":24,"25":25,"26":26,"27":27,"28":28,"29":29,"30":30,"31":31,"32":32,"33":33,"34":34,"35":35,"36":36,"39":39}],38:[function(_dereq_,module,exports){ 'use strict'; var assign = (window.jQuery || window.Zepto).extend; var isString = _dereq_(16); var EventListener = _dereq_(23); var toggleClass = _dereq_(47); /** * Selectivity Base Constructor. * * You will never use this constructor directly. Instead, you use $(selector).selectivity(options) * to create an instance of either MultipleSelectivity or SingleSelectivity. This class defines all * functionality that is common between both. * * @param options Options object. Accepts the same options as the setOptions method(), in addition * to the following ones: * data - Initial selection data to set. This should be an array of objects with 'id' * and 'text' properties. This option is mutually exclusive with 'value'. * element - The DOM element to which to attach the Selectivity instance. This * property is set by the API wrapper. * value - Initial value to set. This should be an array of IDs. This property is * mutually exclusive with 'data'. */ function Selectivity(options) { /** * Reference to the currently open dropdown. */ this.dropdown = null; /** * DOM element to which this instance is attached. */ this.el = options.element; /** * Whether the input is enabled. * * This is false when the option readOnly is false or the option removeOnly is false. */ this.enabled = !options.readOnly && !options.removeOnly; /** * DOM element for the input. * * May be null as long as there is no visible input. It is set by initInput(). */ this.input = null; /** * Array of items from which to select. If set, this will be an array of objects with 'id' and * 'text' properties. * * If given, all items are expected to be available locally and all selection operations operate * on this local array only. If null, items are not available locally, and a query function * should be provided to fetch remote data. */ this.items = null; /** * Options passed to the Selectivity instance or set through setOptions(). */ this.options = {}; /** * Mapping of templates. * * Custom templates can be specified in the options object. */ this.templates = assign({}, Selectivity.Templates); /** * The last used search term. */ this.term = ''; this.setOptions(options); if (options.value) { this.setValue(options.value, { triggerChange: false }); } else { this.setData(options.data || null, { triggerChange: false }); } this.el.setAttribute('tabindex', options.tabIndex || 0); this.events = new EventListener(this.el, this); this.events.on({ blur: this._blur, mouseenter: this._mouseenter, mouseleave: this._mouseleave, 'selectivity-close': this._closed }); } /** * Methods. */ assign(Selectivity.prototype, { /** * Convenience shortcut for this.el.querySelector(selector). */ $: function(selector) { return this.el.querySelector(selector); }, /** * Closes the dropdown. */ close: function() { this._clearCloseTimeout(); if (this.dropdown) { this.dropdown.close(); this.dropdown = null; } }, /** * Destroys the Selectivity instance. */ destroy: function() { this.events.destruct(); var el = this.el; while (el.firstChild) { el.removeChild(el.firstChild); } el.selectivity = null; }, /** * Filters the results to be displayed in the dropdown. * * The default implementation simply returns the results unfiltered, but the MultipleSelectivity * class overrides this method to filter out any items that have already been selected. * * @param results Array of items with 'id' and 'text' properties. * * @return The filtered array. */ filterResults: function(results) { return results; }, /** * Applies focus to the input. */ focus: function() { this._clearCloseTimeout(); this._focusing = true; if (this.input) { this.input.focus(); } this._focusing = false; }, /** * Returns the selection data. */ getData: function() { return this._data; }, /** * Returns the correct item for a given ID. * * @param id The ID to get the item for. * * @return The corresponding item. Will be an object with 'id' and 'text' properties or null if * the item cannot be found. Note that if no items are defined, this method assumes the * text labels will be equal to the IDs. */ getItemForId: function(id) { var items = this.items; if (items) { return Selectivity.findNestedById(items, id); } else if (id === null) { return null; } else { return { id: id, text: '' + id }; } }, /** * Returns the item ID related to an element or event target. * * @param elementOrEvent The DOM element or event to get the item ID for. * * @return Item ID or null if no ID could be found. */ getRelatedItemId: function(elementOrEvent) { var el = elementOrEvent.target || elementOrEvent; while (el) { if (el.hasAttribute('data-item-id')) { break; } el = el.parentNode; } if (!el) { return null; } var id = el.getAttribute('data-item-id'); // IDs can be either numbers or strings, but attribute values are always strings, so we // will have to find out whether the item ID ought to be a number or string ourselves. if (Selectivity.findById(this._data || [], id)) { return id; } else { var dropdown = this.dropdown; while (dropdown) { if (Selectivity.findNestedById(dropdown.results, id)) { return id; } // FIXME: reference to submenu plugin doesn't belong in base dropdown = dropdown.submenu; } var number = parseInt(id, 10); return '' + number === id ? number : id; } }, /** * Returns the value of the selection. */ getValue: function() { return this._value; }, /** * Initializes the input element. * * Sets the input property, invokes all input listeners and (by default) attaches the action of * searching when something is typed. * * @param input Input element. * @param options Optional options object. May contain the following property: * search - If false, no event handlers are setup to initiate searching when the * user types in the input field. This is useful if you want to use the * input only to handle keyboard support. */ initInput: function(input, options) { this.input = input; var selectivity = this; var inputListeners = this.options.inputListeners || Selectivity.InputListeners; inputListeners.forEach(function(listener) { listener(selectivity, input, options); }); if (!options || options.search !== false) { input.addEventListener('keyup', function(event) { if (!event.defaultPrevented) { selectivity.search(event.target.value); } }); } }, /** * Opens the dropdown. */ open: function() { if (this._opening || this.dropdown || !this.triggerEvent('selectivity-opening')) { return; } this._opening = true; var Dropdown = this.options.dropdown || Selectivity.Dropdown; if (Dropdown) { this.dropdown = new Dropdown(this, { items: this.items, position: this.options.positionDropdown, query: this.options.query, showSearchInput: this.options.showSearchInputInDropdown !== false }); } this.search(''); this.focus(); toggleClass(this.el, 'open', true); this._opening = false; }, /** * (Re-)positions the dropdown. */ positionDropdown: function() { if (this.dropdown) { this.dropdown.position(); } }, /** * Searches for results based on the term given. * * If an items array has been passed with the options to the Selectivity instance, a local * search will be performed among those items. Otherwise, the query function specified in the * options will be used to perform the search. If neither is defined, nothing happens. * * @param term Term to search for. */ search: function(term) { this.open(); if (this.dropdown) { this.dropdown.search(term); } }, /** * Sets the selection data. * * The selection data contains both IDs and text labels. If you only want to set or get the IDs, * you should use the value() method. * * @param newData New data to set. For a MultipleSelectivity instance the data must be an array * of objects with 'id' and 'text' properties, for a SingleSelectivity instance * the data must be a single such object or null to indicate no item is selected. * @param options Optional options object. May contain the following property: * triggerChange - Set to false to suppress the "change" event being triggered. * Note this will also cause the UI to not update automatically; * so you may want to call rerenderSelection() manually when * using this option. */ setData: function(newData, options) { options = options || {}; newData = this.validateData(newData); this._data = newData; this._value = this.getValueForData(newData); if (options.triggerChange !== false) { this.triggerChange(); } }, /** * Sets one or more options on this Selectivity instance. * * @param options Options object. May contain one or more of the following properties: * closeOnSelect - Set to false to keep the dropdown open after the user has * selected an item. This is useful if you want to allow the user * to quickly select multiple items. The default value is true. * dropdown - Custom dropdown implementation to use for this instance. * initSelection - Function to map values by ID to selection data. This function * receives two arguments, 'value' and 'callback'. The value is * the current value of the selection, which is an ID or an array * of IDs depending on the input type. The callback should be * invoked with an object or array of objects, respectively, * containing 'id' and 'text' properties. * inputListeners - Array of search input listeners. By default, the global * array Selectivity.InputListeners is used. * items - Array of items from which to select. Should be an array of objects * with 'id' and 'text' properties. As convenience, you may also pass an * array of strings, in which case the same string is used for both the * 'id' and 'text' properties. If items are given, all items are expected * to be available locally and all selection operations operate on this * local array only. If null, items are not available locally, and a * query function should be provided to fetch remote data. * matcher - Function to determine whether text matches a given search term. Note * this function is only used if you have specified an array of items. * Receives two arguments: * item - The item that should match the search term. * term - The search term. Note that for performance reasons, the term * has always been already processed using * Selectivity.transformText(). * The method should return the item if it matches, and null otherwise. * If the item has a children array, the matcher is expected to filter * those itself (be sure to only return the filtered array of children * in the returned item and not to modify the children of the item * argument). * placeholder - Placeholder text to display when the element has no focus and * no selected items. * positionDropdown - Function to position the dropdown. Receives two arguments: * dropdownEl - The element to be positioned. * selectEl - The element of the Selectivity instance, that * you can position the dropdown to. * The default implementation positions the dropdown element * under the Selectivity's element and gives it the same * width. * query - Function to use for querying items. Receives a single object as * argument with the following properties: * callback - Callback to invoke when the results are available. This * callback should be passed a single object as argument with * the following properties: * more - Boolean that can be set to true to indicate there * are more results available. Additional results may * be fetched by the user through pagination. * results - Array of result items. The format for the result * items is the same as for passing local items. * offset - This property is only used for pagination and indicates how * many results should be skipped when returning more results. * selectivity - The Selectivity instance the query function is used on. * term - The search term the user is searching for. Unlike with the * matcher function, the term has not been processed using * Selectivity.transformText(). * readOnly - If true, disables any modification of the input. * removeOnly - If true, disables any modification of the input except removing * of selected items. * shouldOpenSubmenu - Function to call that will decide whether a submenu should * be opened. Receives two parameters: * item - The currently highlighted result item. * reason - The reason why the item is being highlighted. * See Dropdown#highlight() for possible values. * showDropdown - Set to false if you don't want to use any dropdown (you can * still open it programmatically using open()). * showSearchInputInDropdown - Set to false to remove the search input used in * dropdowns. The default is true for single-value * inputs. * templates - Object with instance-specific templates to override the global * templates assigned to Selectivity.Templates. */ setOptions: function(options) { options = options || {}; var selectivity = this; Selectivity.OptionListeners.forEach(function(listener) { listener(selectivity, options); }); if ('items' in options) { this.items = options.items ? Selectivity.processItems(options.items) : null; } if ('templates' in options) { assign(this.templates, options.templates); } assign(this.options, options); this.enabled = !this.options.readOnly && !this.options.removeOnly; }, /** * Sets the value of the selection. * * The value of the selection only concerns the IDs of the selection items. If you are * interested in the IDs and the text labels, you should use the data() method. * * Note that if neither the items option nor the initSelection option have been set, Selectivity * will have no way to determine what text labels should be used with the given IDs in which * case it will assume the text is equal to the ID. This is useful if you're working with tags, * or selecting e-mail addresses for instance, but may not always be what you want. * * @param newValue New value to set. For a MultipleSelectivity instance the value must be an * array of IDs, for a SingleSelectivity instance the value must be a single ID * (a string or a number) or null to indicate no item is selected. * @param options Optional options object. May contain the following property: * triggerChange - Set to false to suppress the "change" event being triggered. * Note this will also cause the UI to not update automatically; * so you may want to call rerenderSelection() manually when * using this option. */ setValue: function(newValue, options) { options = options || {}; newValue = this.validateValue(newValue); this._value = newValue; if (this.options.initSelection) { this.options.initSelection( newValue, function(data) { if (this._value === newValue) { this._data = this.validateData(data); if (options.triggerChange !== false) { this.triggerChange(); } } }.bind(this) ); } else { this._data = this.getDataForValue(newValue); if (options.triggerChange !== false) { this.triggerChange(); } } }, /** * Returns the result of the given template. * * @param templateName Name of the template to process. * @param options Options to pass to the template. * * @return String containing HTML or ReactElement if template is a function returning * ReactElement. */ template: function(templateName, options) { var template = this.templates[templateName]; if (!template) { throw new Error('Unknown template: ' + templateName); } if (typeof template === 'function') { var templateResult = template(options); return typeof templateResult === 'string' ? templateResult.trim() : templateResult; } else if (template.render) { return template.render(options).trim(); } else { return template.toString().trim(); } }, /** * Triggers the change event. * * The event object at least contains the following properties: * data - The new data of the Selectivity instance. * value - The new value of the Selectivity instance. * * @param Optional additional options added to the event object. * * @see getData() * @see getValue() */ triggerChange: function(options) { var data = assign({ data: this._data, value: this._value }, options); this.triggerEvent('change', data); this.triggerEvent('selectivity-change', data); }, /** * Triggers an event on the instance's element. * * @param eventName Name of the event to trigger. * @param data Optional event data to be added to the event object. * * @return Whether the default action of the event may be executed, ie. returns false if * preventDefault() has been called. */ triggerEvent: function(eventName, data) { var event = document.createEvent('Event'); event.initEvent(eventName, /* bubbles: */ false, /* cancelable: */ true); assign(event, data); this.el.dispatchEvent(event); return !event.defaultPrevented; }, /** * Validates a single item. Throws an exception if the item is invalid. * * @param item The item to validate. * * @return The validated item. May differ from the input item. */ validateItem: function(item) { if (item && Selectivity.isValidId(item.id) && isString(item.text)) { return item; } else { throw new Error('Item should have id (number or string) and text (string) properties'); } }, /** * @private */ _blur: function() { if (!this._focusing && !this.el.classList.contains('hover')) { // Without the timeout it appears clicks on result items are not always properly // handled, especially when the user doesn't click exactly on the text of the result // item. I don't understand really why that happens, or why the timeout has to be so // large, but after trial and error, this now seems to work reliably... this._clearCloseTimeout(); this._closeTimeout = setTimeout(this.close.bind(this), 166); } }, /** * @private */ _clearCloseTimeout: function() { if (this._closeTimeout) { clearTimeout(this._closeTimeout); this._closeTimeout = 0; } }, /** * @private */ _closed: function() { this.dropdown = null; toggleClass(this.el, 'open', false); }, /** * @private */ _mouseleave: function(event) { // If mouseleave happens on any selectivity related element, remove hover class if (!this.el.contains(event.relatedTarget)) { toggleClass(this.el, 'hover', false); } }, /** * @private */ _mouseenter: function() { toggleClass(this.el, 'hover', true); } }); /** * Dropdown class to use for displaying dropdowns. * * The default implementation of a dropdown is defined in the selectivity-dropdown module. */ Selectivity.Dropdown = null; /** * Array of input listeners. * * Input listeners are invoked when initInput() is called (typically right after the input is * created). Every listener receives three arguments: * * selectivity - The Selectivity instance. * input - DOM element of the input. * options - Options that were passed to initInput(). * * An example of a search input listener is the selectivity-keyboard module. */ Selectivity.InputListeners = []; /** * Mapping of input types. */ Selectivity.Inputs = {}; /** * Array of option listeners. * * Option listeners are invoked when setOptions() is called. Every listener receives two arguments: * * selectivity - The Selectivity instance. * options - The options that are about to be set. The listener may modify this options object. * * An example of an option listener is the selectivity-traditional module. */ Selectivity.OptionListeners = []; /** * Mapping with templates to use for rendering select boxes and dropdowns. See * selectivity-templates.js for a useful set of default templates, as well as for documentation of * the individual templates. */ Selectivity.Templates = {}; /** * Finds an item in the given array with the specified ID. * * @param array Array to search in. * @param id ID to search for. * * @return The item in the array with the given ID, or null if the item was not found. */ Selectivity.findById = function(array, id) { var index = Selectivity.findIndexById(array, id); return index > -1 ? array[index] : null; }; /** * Finds the index of an item in the given array with the specified ID. * * @param array Array to search in. * @param id ID to search for. * * @return The index of the item in the array with the given ID, or -1 if the item was not found. */ Selectivity.findIndexById = function(array, id) { for (var i = 0, length = array.length; i < length; i++) { if (array[i].id === id) { return i; } } return -1; }; /** * Finds an item in the given array with the specified ID. Items in the array may contain 'children' * properties which in turn will be searched for the item. * * @param array Array to search in. * @param id ID to search for. * * @return The item in the array with the given ID, or null if the item was not found. */ Selectivity.findNestedById = function(array, id) { for (var i = 0, length = array.length; i < length; i++) { var item = array[i], result; if (item.id === id) { result = item; } else if (item.children) { result = Selectivity.findNestedById(item.children, id); } else if (item.submenu && item.submenu.items) { // FIXME: reference to submenu plugin doesn't belong in base result = Selectivity.findNestedById(item.submenu.items, id); } if (result) { return result; } } return null; }; /** * Utility method for inheriting another class. * * @param SubClass Constructor function of the subclass. * @param SuperClass Constructor function of the superclass. * @param prototype Object with methods you want to add to the subclass prototype. * * @return A utility function for calling the methods of the superclass. This function receives two * arguments: The this object on which you want to execute the method and the name of the * method. Any arguments past those are passed to the superclass method. */ Selectivity.inherits = function(SubClass, SuperClass, prototype) { SubClass.prototype = assign( Object.create(SuperClass.prototype), { constructor: SubClass }, prototype ); return function(self, methodName) { SuperClass.prototype[methodName].apply(self, Array.prototype.slice.call(arguments, 2)); }; }; /** * Checks whether a value can be used as a valid ID for selection items. Only numbers and strings * are accepted to be used as IDs. * * @param id The value to check whether it is a valid ID. * * @return true if the value is a valid ID, false otherwise. */ Selectivity.isValidId = function(id) { return typeof id === 'number' || isString(id); }; /** * Decides whether a given item matches a search term. The default implementation simply * checks whether the term is contained within the item's text, after transforming them using * transformText(). * * @param item The item that should match the search term. * @param term The search term. Note that for performance reasons, the term has always been already * processed using transformText(). * * @return true if the text matches the term, false otherwise. */ Selectivity.matcher = function(item, term) { var result = null; if (Selectivity.transformText(item.text).indexOf(term) > -1) { result = item; } else if (item.children) { var matchingChildren = item.children .map(function(child) { return Selectivity.matcher(child, term); }) .filter(function(child) { return !!child; }); if (matchingChildren.length) { result = { id: item.id, text: item.text, children: matchingChildren }; } } return result; }; /** * Helper function for processing items. * * @param item The item to process, either as object containing 'id' and 'text' properties or just * as ID. The 'id' property of an item is optional if it has a 'children' property * containing an array of items. * * @return Object containing 'id' and 'text' properties. */ Selectivity.processItem = function(item) { if (Selectivity.isValidId(item)) { return { id: item, text: '' + item }; } else if (item && (Selectivity.isValidId(item.id) || item.children) && isString(item.text)) { if (item.children) { item.children = Selectivity.processItems(item.children); } return item; } else { throw new Error('invalid item'); } }; /** * Helper function for processing an array of items. * * @param items Array of items to process. See processItem() for details about a single item. * * @return Array with items. */ Selectivity.processItems = function(items) { if (Array.isArray(items)) { return items.map(Selectivity.processItem); } else { throw new Error('invalid items'); } }; /** * Transforms text in order to find matches. The default implementation casts all strings to * lower-case so that any matches found will be case-insensitive. * * @param string The string to transform. * * @return The transformed string. */ Selectivity.transformText = function(string) { return string.toLowerCase(); }; module.exports = Selectivity; },{"16":16,"23":23,"47":47,"lodash/assign":"lodash/assign"}],39:[function(_dereq_,module,exports){ 'use strict'; var escape = _dereq_(12); var Selectivity = _dereq_(38); var Locale = _dereq_(27); /** * Default set of templates to use with Selectivity.js. * * Template can be defined as either a string, a function returning a string (like Handlebars * templates, for instance), an object containing a render function (like Hogan.js templates, fo * instance) or as a function returning a DOM element. * * Every template must return a single root element. */ Selectivity.Templates = { /** * Renders the dropdown. * * The template is expected to have at least one element with the class * 'selectivity-results-container', which is where all results will be added to. * * @param options Options object containing the following properties: * dropdownCssClass - Optional CSS class to add to the top-level element. * searchInputPlaceholder - Optional placeholder text to display in the search * input in the dropdown. * showSearchInput - Boolean whether a search input should be shown. If true, * an input element with the 'selectivity-search-input' is * expected. */ dropdown: function(options) { var extraClass = options.dropdownCssClass ? ' ' + options.dropdownCssClass : '', searchInput = ''; if (options.showSearchInput) { extraClass += ' has-search-input'; var placeholder = options.searchInputPlaceholder; searchInput = '
' + '' + '
'; } return ( '
' + searchInput + '
' + '
' ); }, /** * Renders an error message in the dropdown. * * @param options Options object containing the following properties: * escape - Boolean whether the message should be HTML-escaped. * message - The message to display. */ error: function(options) { return ( '
' + (options.escape ? escape(options.message) : options.message) + '
' ); }, /** * Renders a loading indicator in the dropdown. * * This template is expected to have an element with a 'selectivity-loading' class which may be * replaced with actual results. */ loading: function() { return '
' + Locale.loading + '
'; }, /** * Load more indicator. * * This template is expected to have an element with a 'selectivity-load-more' class which, when * clicked, will load more results. */ loadMore: function() { return '
' + Locale.loadMore + '
'; }, /** * Renders multi-selection input boxes. * * The template is expected to have at least have elements with the following classes: * 'selectivity-multiple-input-container' - The element containing all the selected items and * the input for selecting additional items. * 'selectivity-multiple-input' - The actual input element that allows the user to type to * search for more items. When selected items are added, they are * inserted right before this element. * * @param options Options object containing the following property: * enabled - Boolean whether the input is enabled. */ multipleSelectInput: function(options) { return ( '
' + (options.enabled ? '' : '
') + '
' + '
' ); }, /** * Renders a selected item in multi-selection input boxes. * * The template is expected to have a top-level element with the class * 'selectivity-multiple-selected-item'. This element is also required to have a 'data-item-id' * attribute with the ID set to that passed through the options object. * * An element with the class 'selectivity-multiple-selected-item-remove' should be present * which, when clicked, will cause the element to be removed. * * @param options Options object containing the following properties: * highlighted - Boolean whether this item is currently highlighted. * id - Identifier for the item. * removable - Boolean whether a remove icon should be displayed. * text - Text label which the user sees. */ multipleSelectedItem: function(options) { var extraClass = options.highlighted ? ' highlighted' : ''; return ( '' + (options.removable ? '' + '' + '' : '') + escape(options.text) + '' ); }, /** * Renders a message there are no results for the given query. * * @param options Options object containing the following property: * term - Search term the user is searching for. */ noResults: function(options) { return ( '
' + (options.term ? Locale.noResultsForTerm(options.term) : Locale.noResults) + '
' ); }, /** * Renders a container for item children. * * The template is expected to have an element with the class 'selectivity-result-children'. * * @param options Options object containing the following property: * childrenHtml - Rendered HTML for the children. */ resultChildren: function(options) { return '
' + options.childrenHtml + '
'; }, /** * Render a result item in the dropdown. * * The template is expected to have a top-level element with the class * 'selectivity-result-item'. This element is also required to have a 'data-item-id' attribute * with the ID set to that passed through the options object. * * @param options Options object containing the following properties: * id - Identifier for the item. * text - Text label which the user sees. * disabled - Truthy if the item should be disabled. * submenu - Truthy if the result item has a menu with subresults. */ resultItem: function(options) { return ( '
' + escape(options.text) + (options.submenu ? '' : '') + '
' ); }, /** * Render a result label in the dropdown. * * The template is expected to have a top-level element with the class * 'selectivity-result-label'. * * @param options Options object containing the following properties: * text - Text label. */ resultLabel: function(options) { return '
' + escape(options.text) + '
'; }, /** * Renders single-select input boxes. * * The template is expected to have at least one element with the class * 'selectivity-single-result-container' which is the element containing the selected item or * the placeholder. */ singleSelectInput: function(options) { return ( '
' + '' + '
' + '' + '
' ); }, /** * Renders the placeholder for single-select input boxes. * * The template is expected to have a top-level element with the class * 'selectivity-placeholder'. * * @param options Options object containing the following property: * placeholder - The placeholder text. */ singleSelectPlaceholder: function(options) { return '
' + escape(options.placeholder) + '
'; }, /** * Renders the selected item in single-select input boxes. * * The template is expected to have a top-level element with the class * 'selectivity-single-selected-item'. This element is also required to have a 'data-item-id' * attribute with the ID set to that passed through the options object. * * @param options Options object containing the following properties: * id - Identifier for the item. * removable - Boolean whether a remove icon should be displayed. * text - Text label which the user sees. */ singleSelectedItem: function(options) { return ( '' + (options.removable ? '' + '' + '' : '') + escape(options.text) + '' ); }, /** * Renders select-box inside single-select input that was initialized on * traditional element. * mode - Mode in which select exists, single or multiple. */ selectCompliance: function(options) { var mode = options.mode; var name = options.name; if (mode === 'multiple' && name.slice(-2) !== '[]') { name += '[]'; } return ( '' ); }, /** * Renders the selected item in compliance
"}return'
'+i+'
'},error:function(t){return'
'+(t.escape?n(t.message):t.message)+"
"},loading:function(){return'
'+r.loading+"
"},loadMore:function(){return'
'+r.loadMore+"
"},multipleSelectInput:function(t){return'
'+(t.enabled?'':'
')+'
'},multipleSelectedItem:function(t){return''+(t.removable?'':"")+n(t.text)+""},noResults:function(t){return'
'+(t.term?r.noResultsForTerm(t.term):r.noResults)+"
"},resultChildren:function(t){return'
'+t.childrenHtml+"
"},resultItem:function(t){return'
'+n(t.text)+(t.submenu?'':"")+"
"},resultLabel:function(t){return'
'+n(t.text)+"
"},singleSelectInput:function(t){return'
'},singleSelectPlaceholder:function(t){return'
'+n(t.placeholder)+"
"},singleSelectedItem:function(t){return''+(t.removable?'':"")+n(t.text)+""},selectCompliance:function(t){var e=t.mode,i=t.name;return"multiple"===e&&"[]"!==i.slice(-2)&&(i+="[]"),'"},selectOptionCompliance:function(t){return'"}}},{12:12,27:27,37:37}],39:[function(t,e,i){"use strict";e.exports=function(t,e){for(var i=0,n=t.length;i` elements. The React API's `onChange` property uses the new event. - Rewrote the AJAX plugin: - It now relies on the `fetch()` method for performing AJAX requests. This method is only available on modern browsers, so you'll need a polyfill if you want to use this with old browsers, unless you're using a jQuery build in which case the `jquery/ajax` plugin can provide a shim based on `$.ajax()` (requires jQuery 3.0 or higher). - Please check the documentation for the new options that can be passed. - Renamed the option `suppressMouseWheelSelector` to just `suppressWheelSelector`. - Renamed the `Selectivity.InputTypes` map to `Selectivity.Inputs`. - Removed dist directory from the repository. - Improved submenu positioning by automatically opening them on the left-hand side if there's insufficient space on the right side. - Improve searching behavior with multiple submenus open. - Fix #107: Remove the dropdown after timeout to fix "hover" behavior. - Fix #136: Update original `` element now uses "s9y\_" prefix for its ID (thanks to @dr-itz). - Fix: Provide correct offset in pagination when results are filtered. ## 2.1.0 - Implemented `disabled` property on items. When an item is disabled it cannot be selected and by default is rendered with grey text. - PR #63: Fix problem with `closeOnSelect` behavior. - PR #80: Added CSS classes for `hover` and `open` states. - Fix #66: Respect `removeOnly` option when set after initialization. - Fix #67: Pass `queryOptions` to `url` function in AJAX module. - Fix #75: Make sure Enter key doesn't submit forms. - Fix #93: Make the rerenderSelection() method public and document that `triggerChange: false` doesn't automatically update the UI. - Fixed issue where the cursor position was constantly reset when using a tokenizer. - Miscellaneous smaller fixes and styling tweaks. ## 2.0.0 rating/rating.php000064400000033714146731457770010062 0ustar00 Return Notice module class instance * * @param string|null $text_domain * @param string|null $unique_id * @return mixed */ public static function instance( $text_domain = null, $unique_id = null ) { if ( $text_domain == null ) { return false; } self::$instance = new self(); self::$instance->config( $text_domain, ( is_null( $unique_id ) ? uniqid() : $unique_id ) ); return self::$instance; } /** * Set Text domain * * @param string $text_domain * @param string $unique_id */ public function config( $text_domain, $unique_id ) { $this->text_domain = $text_domain; } /** * Get vesrion of $this * * @return \Wpmet\Rating\Rating */ public function get_version() { return $this->script_version; } /** * @return $this file location for debugging 🐛 purpose */ public function get_script_location() { return __FILE__; } /** * @param */ public function set_plugin( $plugin_name, $plugin_url ) { $this->plugin_name = $plugin_name; $this->rating_url = $plugin_url; return $this; } /** * @param */ public function set_priority( $priority ) { $this->priority = $priority; return $this; } public function set_first_appear_day( $days = 7 ) { $this->days = $days; return $this; } public function set_rating_url( $url ) { $this->rating_url = $url; return $this; } public function set_plugin_logo( $logo_url ) { $this->plugin_logo = $logo_url; return $this; } public function set_allowed_screens( $screen ) { $this->plugin_screens[] = $screen; return $this; } public function set_condition( $result ) { switch ( gettype( $result ) ) { case 'boolean': $this->condition_status = $result; break; case 'object': $this->condition_status = $result(); break; default: $this->condition_status = false; } return $this; } public static function init() { add_action( 'wp_ajax_wpmet_rating_never_show_message', array( __CLASS__, 'never_show_message' ) ); add_action( 'wp_ajax_wpmet_rating_ask_me_later_message', array( __CLASS__, 'ask_me_later_message' ) ); } protected function is_current_screen_allowed( $current_screen_id ) { if ( in_array( $current_screen_id, array_merge( $this->plugin_screens, array( 'dashboard', 'plugins' ) ) ) ) { return true; } return false; } /** * ------------------------------------------ * 🚀 Rating class execution point * ------------------------------------------ */ public function call() { $this->init(); add_action( 'admin_head', array( $this, 'fire' ), $this->priority ); } /** * ------------------------------------------- * 🔥 fire the rating functionality * ------------------------------------------- */ public function fire() { if ( current_user_can( 'update_plugins' ) ) { $current_screen = get_current_screen(); if ( ! $this->is_current_screen_allowed( $current_screen->id ) ) { return; } if ( $this->condition_status === false ) { return; } add_action( 'admin_footer', array( $this, 'scripts' ), 9999 ); if ( $this->action_on_fire() ) { if ( ! $this->is_installation_date_exists() ) { $this->set_installation_date(); } if ( get_o