summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/SemanticMediaWiki/res/jquery/jquery.selectmenu.js
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/res/jquery/jquery.selectmenu.js')
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/res/jquery/jquery.selectmenu.js1597
1 files changed, 1597 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/res/jquery/jquery.selectmenu.js b/www/wiki/extensions/SemanticMediaWiki/res/jquery/jquery.selectmenu.js
new file mode 100644
index 00000000..8c052221
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/res/jquery/jquery.selectmenu.js
@@ -0,0 +1,1597 @@
+/**
+ * @summary SelectMenu
+ * @desc Simple, easily and diversity menu solution
+ * @file selectmenu.js
+ * @version 2.1
+ * @author TerryZeng
+ * @contact https://terryz.github.io/
+ * @license MIT License
+ *
+ * depend on:
+ * jQuery1.x
+ *
+ */
+;(function($){
+ "use strict";
+ /**
+ * Version: v3.6.1
+ * The MIT License: Copyright (c) 2010-2017 LiosK.
+ * Link: https://github.com/LiosK/UUID.js
+ */
+ var UUID;
+ UUID=function(f){function a(){}a.generate=function(){var b=a._getRandomInt,c=a._hexAligner;return c(b(32),8)+"-"+c(b(16),4)+"-"+c(16384|b(12),4)+"-"+c(32768|b(14),4)+"-"+c(b(48),12)};a._getRandomInt=function(b){if(0>b||53<b)return NaN;var c=0|1073741824*Math.random();return 30<b?c+1073741824*(0|Math.random()*(1<<b-30)):c>>>30-b};a._hexAligner=function(b,c){for(var a=b.toString(16),d=c-a.length,e="0";0<d;d>>>=1,e+=e)d&1&&(a=e+a);return a};a.overwrittenUUID=f;"undefined"!==typeof module&&module&&module.exports&&
+ (module.exports=a);return a}(UUID);
+ /**
+ * Default options
+ */
+ var defaults = {
+ /**
+ * Menu data source
+ * @type array | function
+ * @example
+ * array:[{a:1,b:2,c:3},{...}]
+ * function: function(){ return [{...}];}
+ * return data format is same to array
+ */
+ data: undefined,
+ /**
+ * Show quick search input element, work on advance menu mode
+ * @type boolean
+ * @default true
+ */
+ search : true,
+ /**
+ * Title bar text, set false to close title bar
+ * @type string | boolean
+ * @default 'SelectMenu'
+ */
+ title : 'SelectMenu',
+ /**
+ * Regular menu mode
+ * @type boolean
+ * @default false
+ */
+ regular : false,
+ /**
+ * Mouse right click to show menu
+ * @type boolean
+ * @default false
+ */
+ rightClick : false,
+ /**
+ * Menu show arrow, look like a bubble
+ * @type boolean
+ * @default false
+ */
+ arrow : false,
+ /**
+ * Alignment direction
+ * @type string
+ * @enum
+ * 'left'
+ * 'center'
+ * 'right'
+ * @default 'left'
+ */
+ position : 'left',
+ /**
+ * Embedded to page
+ * @type boolean
+ * @default false
+ */
+ embed : false,
+ /**
+ * Language ('cn', 'ja', 'en', 'es', 'pt-br')
+ * @type string
+ * @default 'cn'
+ */
+ lang: 'cn',
+ /**
+ * Multiple select mode(tags)
+ * @type boolean
+ * @default false
+ */
+ multiple: false,
+ /**
+ * Menu result list size, the number mean is visible menu item amount
+ * @type number
+ * @default 10
+ */
+ listSize : 10,
+ /**
+ * Maximum selected item limit in multiple select mode, set 0 to unlimited
+ * @type number
+ * @default 0 (unlimited)
+ */
+ maxSelectLimit: 0,
+ /**
+ * Close result list after menu item selected, work on multiple select mode
+ * @type boolean
+ * @default true
+ */
+ selectToCloseList: false,
+ /**
+ * Set a key to selected menu item when plugin init complete, work on multiple select mode
+ * the key will match to keyField
+ * @type string
+ */
+ initSelected: undefined,
+ /**
+ * Key field to return data
+ * @type string
+ * @default 'id'
+ */
+ keyField: 'id',
+ /**
+ * Show content field
+ * @type string
+ * @default 'name'
+ */
+ showField: 'name',
+ /**
+ * Data field in search, not set default used showField
+ * @type string
+ */
+ searchField : undefined,
+ /**
+ * Filter type ('AND' or 'OR')
+ * @type string default: 'AND'
+ */
+ andOr: 'AND',
+ /**
+ * Sort order, not set default used showField
+ * @type array
+ * @example
+ * orderBy : ['id desc']//order by id desc
+ */
+ orderBy: undefined,
+ /**
+ * Max item size
+ * @type number
+ */
+ pageSize: 100,
+ /**
+ * Menu item result format
+ * @type function
+ * @param data {object} menu item data
+ * @return string
+ */
+ formatItem : undefined,
+ /**
+ * -----------------------------------------Event--------------------------------------------
+ */
+ /**
+ * Menu item select callback
+ * @type function
+ * @param data {array[Object]} selected items data
+ */
+ eSelect : undefined,
+ /**
+ * Multiple group data type tab switch callback
+ * @type function
+ * @param index {number}
+ */
+ eTabSwitch : undefined,
+ /**
+ * Menu hide callback
+ * @type function
+ * @param data {array[Object]} selected items data
+ */
+ eHidden : undefined
+ };
+
+
+ /**
+ * @constructor
+ * @param {Object} input - menu caller
+ * @param {Object} option - menu init option
+ */
+ var SelectMenu = function(input, option) {
+ this.target = input;
+ this.setOption(option);
+ if(this.option.embed && !$(input).is('div')){
+ console.warn('SelectMenu embed mode need a "div" container element!');
+ return;
+ }
+
+ this.setLanguage();
+ this.setCssClass();
+ this.setProp();
+
+ if(option.regular) this.setRegularMenu();
+ else this.setElem();
+
+ if(!option.rightClick) this.populate();
+
+ this.eInput();
+ if(!option.embed) this.eWhole();
+ this.atLast();
+ };
+ /**
+ * Plugin version number
+ */
+ SelectMenu.version = '2.1';
+ /**
+ * Plugin object cache key
+ */
+ SelectMenu.dataKey = 'selectMenuObject';
+ /**
+ * Data source type
+ * List type
+ */
+ SelectMenu.dataTypeList = 'SelectMenuList';
+ /**
+ * Group type
+ */
+ SelectMenu.dataTypeGroup = 'SelectMenuGroup';
+ /**
+ * Regular menu type
+ */
+ SelectMenu.dataTypeMenu = 'SelectMenuMenu';
+ /**
+ * Initial plugin option
+ * @param {Object} option
+ */
+ SelectMenu.prototype.setOption = function(option) {
+ //if not set, default used showField set field
+ option.searchField = option.searchField || option.showField;
+
+ if(option.regular && option.title === defaults.title) option.title = false;
+ //Close arrow in embed and mouse right click mode
+ if(option.embed || option.rightClick) option.arrow = false;
+
+ option.andOr = option.andOr.toUpperCase();
+ if(option.andOr!=='AND' && option.andOr!=='OR') option.andOr = 'AND';
+
+ option.orderBy = (option.orderBy === undefined) ? option.showField : option.orderBy;
+
+ //Multiple field sort
+ //Example: [ ['id', 'ASC'], ['name', 'DESC'] ]
+ option.orderBy = this.setOrderbyOption(option.orderBy, option.showField);
+
+ if($.type(option.data) === 'string'){
+ option.autoSelectFirst = false;
+ }
+ if($.type(option.listSize) !== 'number' || option.listSize < 0) option.listSize = 12;
+
+ this.option = option;
+ };
+
+ /**
+ * Initial order
+ * @param {Array} arg_order
+ * @param {string} arg_field
+ * @return {Array}
+ */
+ SelectMenu.prototype.setOrderbyOption = function(arg_order, arg_field) {
+ var arr = [],orders = [];
+ if (typeof arg_order == 'object') {
+ for (var i = 0; i < arg_order.length; i++) {
+ orders = $.trim(arg_order[i]).split(' ');
+ arr[i] = (orders.length == 2) ? orders: [orders[0], 'ASC'];
+ }
+ } else {
+ orders = $.trim(arg_order).split(' ');
+ arr[0] = (orders.length == 2) ? orders: (orders[0].match(/^(ASC|DESC)$/i)) ? [arg_field, orders[0]] : [orders[0], 'ASC'];
+ }
+ return arr;
+ };
+
+ /**
+ * i18n
+ */
+ SelectMenu.prototype.setLanguage = function() {
+ var message;
+ switch (this.option.lang) {
+ // 中文
+ case 'cn':
+ message = {
+ select_all_btn: '选择所有 (或当前页签) 项目',
+ remove_all_btn: '清除所有选中的项目',
+ close_btn: '关闭菜单 (Esc键)',
+ loading: '读取中...',
+ select_ng: '请注意:请从列表中选择.',
+ select_ok: 'OK : 已经选择.',
+ not_found: '无查询结果',
+ ajax_error: '连接到服务器时发生错误!',
+ max_selected: '最多只能选择 max_selected_limit 个项目'
+ };
+ break;
+ // English
+ case 'en':
+ message = {
+ select_all_btn: 'Select All (Tabs) items',
+ remove_all_btn: 'Clear all selected items',
+ close_btn: 'Close Menu (Esc key)',
+ loading: 'loading...',
+ select_ng: 'Attention : Please choose from among the list.',
+ select_ok: 'OK : Correctly selected.',
+ not_found: 'not found',
+ ajax_error: 'An error occurred while connecting to server.',
+ max_selected: 'You can only select up to max_selected_limit items'
+ };
+ break;
+ // Japanese
+ case 'ja':
+ message = {
+ select_all_btn: 'すべての (または現在のタブ) 項目を選択',
+ remove_all_btn: '選択したすべての項目をクリアする',
+ close_btn: '閉じる (Tabキー)',
+ loading: '読み込み中...',
+ select_ng: '注意 : リストの中から選択してください',
+ select_ok: 'OK : 正しく選択されました。',
+ not_found: '(0 件)',
+ ajax_error: 'サーバとの通信でエラーが発生しました。',
+ max_selected: '最多で max_selected_limit のプロジェクトを選ぶことしかできません'
+ };
+ break;
+ // German
+ case 'de':
+ message = {
+ select_all_btn: 'Wählen Sie alle (oder aktuellen Registerkarten) aus',
+ remove_all_btn: 'Alle ausgewählten Elemente löschen',
+ close_btn: 'Schließen (Tab)',
+ loading: 'lade...',
+ select_ng: 'Achtung: Bitte wählen Sie aus der Liste aus.',
+ select_ok: 'OK : Richtig ausgewählt.',
+ not_found: 'nicht gefunden',
+ ajax_error: 'Bei der Verbindung zum Server ist ein Fehler aufgetreten.',
+ max_selected: 'Sie können nur bis zu max_selected_limit Elemente auswählen'
+ };
+ break;
+ // Spanish
+ case 'es':
+ message = {
+ select_all_btn: 'Seleccionar todos los elementos (o la pestaña actual)',
+ remove_all_btn: 'Borrar todos los elementos seleccionados',
+ close_btn: 'Cerrar (tecla TAB)',
+ loading: 'Cargando...',
+ select_ng: 'Atencion: Elija una opcion de la lista.',
+ select_ok: 'OK: Correctamente seleccionado.',
+ not_found: 'no encuentre',
+ ajax_error: 'Un error ocurrió mientras conectando al servidor.',
+ max_selected: 'Solo puedes seleccionar hasta max_selected_limit elementos'
+ };
+ break;
+ // Brazilian Portuguese
+ case 'pt-br':
+ message = {
+ select_all_btn: 'Selecione todos os itens (ou guia atual)',
+ remove_all_btn: 'Limpe todos os itens selecionados',
+ close_btn: 'Fechar (tecla TAB)',
+ loading: 'Carregando...',
+ select_ng: 'Atenção: Escolha uma opção da lista.',
+ select_ok: 'OK: Selecionado Corretamente.',
+ not_found: 'não encontrado',
+ ajax_error: 'Um erro aconteceu enquanto conectando a servidor.',
+ max_selected: 'Você só pode selecionar até max_selected_limit itens'
+ };
+ break;
+ }
+ this.message = message;
+ };
+
+ /**
+ * CSS classname set
+ */
+ SelectMenu.prototype.setCssClass = function() {
+ var css_class = {
+ target_clicked : 'sm_target_clicked',
+ container: 'sm_container',
+ container_open: 'sm_container_open',
+ container_embed: 'sm_embed',
+ header: 'sm_header',
+ re_area: 'sm_result_area',
+ re_tabs: 'sm_result_tabs',
+ re_list: 'sm_list_mode',
+ control_box: 'sm_control_box',
+ two_btn: 'sm_two_btn',
+ element_box: 'sm_element_box',
+ results: 'sm_results',
+ re_off: 'sm_results_off',
+ select: 'sm_over',
+ selected_icon: 'sm_selected_icon',
+ item_text: 'sm_item_text',
+ select_ok: 'sm_select_ok',
+ select_ng: 'sm_select_ng',
+ selected: 'sm_selected',
+ input_off: 'sm_input_off',
+ message_box: 'sm_message_box',
+
+ btn_close: 'sm_close_button',
+ btn_selectall: 'sm_selectall_button',
+ btn_removeall: 'sm_removeall_button',
+ btn_on: 'sm_btn_on',
+ btn_out: 'sm_btn_out',
+ btn_back: 'sm_sub_back',
+ input: 'sm_input',
+ input_area: 'sm_input_area',
+ clear_btn: 'sm_clear_btn',
+
+ menu_root: 'sm_menu_root',
+ menu_divider: 'sm_divider',
+ menu_regular: 'sm_regular',
+ menu_arrow: 'sm_arrow',
+ menu_arrow_have_title : 'sm_have_title',
+ menu_disabled: 'sm_disabled',
+ menu_header: 'sm_header',
+ menu_caret: 'sm_caret',
+ menu_sub_menu: 'sm_sub_menu',
+ menu_sub_item: 'sm_sub_item',
+ menu_sub_header: 'sm_sub_header',
+
+
+ direction_top : 'sm_arrow_top',
+ direction_bottom : 'sm_arrow_bottom'
+ };
+ this.css_class = css_class;
+ this.template = {
+ msg :{
+ maxSelectLimit: 'max_selected_limit'
+ }
+ };
+ };
+
+ /**
+ * Internal variable initial
+ */
+ SelectMenu.prototype.setProp = function() {
+ this.prop = {
+ //selected menu item keys
+ values : [],
+ data : undefined,
+ //multiple group data current data index
+ data_index : 0,
+ key_select: false,
+ prev_value: '',
+ selected_text : '',
+ last_input_time: undefined,
+ //menu data type
+ data_type : SelectMenu.dataTypeList,
+ //id prefix
+ menu_tab_id_prefix : 'selectmenu_tab_',
+ menu_code_prefix: 'selectmenu_',
+ //mouse x point
+ x : undefined,
+ //mouse y point
+ y : undefined
+ };
+ };
+
+ /**
+ * Data source type check
+ */
+ SelectMenu.prototype.checkDataType = function(d){
+ var self = this,p = this.option;
+ if(d && $.isArray(d) && d.length){
+ if(p.regular) return SelectMenu.dataTypeMenu;
+ else{
+ var row = d[0];
+ if(row.hasOwnProperty('title') && row.hasOwnProperty('list') && $.isArray(row.list)){
+ return SelectMenu.dataTypeGroup;
+ }else return SelectMenu.dataTypeList;
+ }
+ }else return null;
+ };
+
+ /**
+ * Menu structure build
+ */
+ SelectMenu.prototype.setElem = function() {
+ var self = this, p = this.option, css = this.css_class;
+ // 1. build dom element
+ var elem = {};
+
+ elem.container = p.embed ? $(self.target).addClass(css.container_embed) : $('<div>');
+ elem.container.addClass(css.container).addClass(css.direction_bottom);
+ if(p.title){
+ elem.header = $('<div>').addClass(css.header);
+ elem.header.append('<h3>' + p.title + '</h3>');
+ if(p.multiple){
+ elem.selectAllButton = $('<button type="button"><i class="iconfont icon-selectall"></i></button>')
+ .attr('title',this.message.select_all_btn)
+ .addClass(css.btn_selectall);
+ elem.removeAllButton = $('<button type="button"><i class="iconfont icon-removeall"></i></button>')
+ .attr('title',this.message.remove_all_btn)
+ .addClass(css.btn_removeall);
+ elem.header.append(elem.selectAllButton);
+ elem.header.append(elem.removeAllButton);
+ }
+
+ if(!p.embed){
+ elem.closeButton = $('<button type="button">×</button>')
+ .attr('title',self.message.close_btn)
+ .addClass(css.btn_close);
+ elem.header.append(elem.closeButton);
+ }
+ }
+
+ elem.inputArea = $('<div>').addClass(css.input_area);
+ elem.input = $('<input type="text" autocomplete="off">').addClass(css.input);
+
+ //Result list
+ elem.resultArea = $('<div>').addClass(css.re_area);
+ elem.resultTabs = $('<div>').addClass(css.re_tabs);
+ elem.results = $('<ul>').addClass(css.results);
+ elem.selectedIcon = $('<i class="iconfont icon-selected">');
+
+ // 2. DOM element put
+ if(p.arrow){
+ elem.arrow = $('<div>').addClass(css.menu_arrow);
+ if(p.title) elem.arrow.addClass(css.menu_arrow_have_title);
+ elem.container.append(elem.arrow);
+ }
+ if(p.title) elem.container.append(elem.header);
+ if(p.search){
+ elem.container.append(elem.inputArea);
+ elem.inputArea.append(elem.input);
+ }
+ elem.container.append(elem.resultTabs).append(elem.resultArea);
+ elem.resultArea.append(elem.results);
+
+ if(!p.embed) $(document.body).append(elem.container);
+
+ this.elem = elem;
+ };
+
+ /**
+ * Initial regular menu frame
+ */
+ SelectMenu.prototype.setRegularMenu = function(){
+ var p = this.option, self = this, css = this.css_class;
+ var elem = {};
+ elem.container = p.embed ? $(self.target).addClass(css.container_embed) : $('<div>');
+ elem.container.addClass(css.container)
+ .addClass(css.direction_bottom)
+ .addClass(css.menu_regular);
+ if(p.title){
+ elem.header = $('<div>').addClass(css.header);
+ elem.header.append('<h3>' + p.title + '</h3>');
+ if(!p.embed)
+ elem.closeButton = $('<button type="button">×</button>')
+ .attr('title',self.message.close_btn)
+ .addClass(css.btn_close);
+ }
+
+ elem.resultArea = $('<div>').addClass(css.re_area);
+ elem.results = $('<ul>').addClass(css.results).addClass(css.menu_root);
+
+ if(p.arrow){
+ elem.arrow = $('<div>').addClass(css.menu_arrow);
+ if(p.title) elem.arrow.addClass(css.menu_arrow_have_title);
+ elem.container.append(elem.arrow);
+ }
+
+ if(p.title){
+ elem.container.append(elem.header);
+ if(!p.embed) elem.header.append(elem.closeButton);
+ }
+ elem.container.append(elem.resultArea);
+ elem.resultArea.append(elem.results);
+
+ if(!p.embed) $(document.body).append(elem.container);
+ this.elem = elem;
+ };
+
+ /**
+ * Regular menu item render
+ */
+ SelectMenu.prototype.regularMenuInit = function(){
+ var d = this.prop.data, p = this.option, self = this, css = this.css_class, el = self.elem;
+ var showMenu = function(){
+ if(!p.embed){
+ this.calcResultsSize(this);
+ el.container.addClass(css.container_open);
+ }
+ };
+ if(el.results.find('li').length && !$.isFunction(p.data)){
+ showMenu.call(self);
+ return;
+ }
+ if(d && $.isArray(d) && d.length){
+ var buildMenu = function(menudata, ul){
+ if(ul.hasClass(css.menu_root)) ul.empty().hide();
+
+ $.each(menudata,function(i,row){
+ if(!row.content ||
+ (!row.header &&
+ !row.url &&
+ !row.callback &&
+ !row.menus &&
+ row.content !== css.menu_divider))
+ return true;
+ var li = $('<li>');
+ if(row.content === css.menu_divider){
+ li.addClass(css.menu_divider);
+ }else{
+ var a = $('<a>').html(row.content).attr('href',
+ (row.url && !row.disabled)?row.url:'javascript:void(0);');
+ if(row.callback && $.isFunction(row.callback) && !row.url){
+ a.on('click.selectMenu',function(e){
+ e.stopPropagation();
+ if(row.disabled) return;
+ row.callback();
+ self.hideResults(self);
+ });
+ }
+ //build sub menus
+ if(row.menus && $.isArray(row.menus) && row.menus.length){
+ var itemCode = self.prop.menu_code_prefix + UUID.generate();
+ a.attr({
+ 'href': 'javascript:void(0);',
+ 'item_code': itemCode
+ }).append($('<span>').addClass(css.menu_caret)).addClass(css.menu_sub_item);
+ var subMenu = $('<ul>').attr('id', itemCode).addClass(css.results).addClass(css.menu_sub_menu);
+
+ //build sub menu header bar
+ var backBtn = $('<button type="button">').addClass(css.btn_back).append('<i class="iconfont icon-back"></i>');
+ var header = $('<li>').append(backBtn).append($('<p>').text(row.content)).addClass(css.menu_sub_header);
+
+ subMenu.append(header).append($('<li>').addClass(css.menu_divider));
+ el.resultArea.append(subMenu);
+ buildMenu(row.menus, subMenu);
+ }
+ li.prepend(a);
+ if(row.disabled) li.addClass(css.menu_disabled);
+ if(row.header) li.addClass(css.menu_header);
+ }
+ ul.append(li);
+ });
+ if(!ul.hasClass(css.menu_sub_menu)) ul.show();
+ };
+
+ el.resultArea.find('ul.'+css.results+':not(.'+css.menu_root+')').remove();
+ buildMenu(d, el.results);
+
+ //sub menus event bind
+ el.resultArea.find('a.'+css.menu_sub_item).off('click.SelectMenu').on('click.SelectMenu', function(e){
+ e.preventDefault();
+ e.stopPropagation();
+ var $this = $(this),
+ $menu = $this.closest('ul.'+css.results),
+ $subMenu = $('#'+$this.attr('item_code'));
+ if($subMenu.length){
+ $menu.hide();
+ /*
+ $subMenu.css({ marginLeft: 60 }).show().animate({
+ marginLeft: 0
+ },100);
+ */
+ $subMenu.addClass('vivify fadeInRight').show();
+ }
+ });
+ //back button
+ el.resultArea.find('button.'+css.btn_back).off('click.SelectMenu').on('click.SelectMenu', function(e){
+ var $btn = $(this),
+ $menu = $btn.closest('ul'),
+ $parentMenu = $('a[item_code="'+$menu.attr('id')+'"]').closest('ul');
+ $menu.hide();
+ $parentMenu.addClass('vivify fadeInLeft').show();
+ });
+
+ showMenu.call(self);
+ }
+ };
+
+ /**
+ * Show menu
+ * @param self
+ */
+ SelectMenu.prototype.showMenu = function(self){
+ self.populate();
+ if($(self.target).is('button'))
+ $(self.target).addClass(self.css_class.target_clicked);
+ };
+
+ /**
+ * Set menu item to selected
+ * @param self
+ * @param list - datasource
+ */
+ SelectMenu.prototype.setInitSelected = function(self, list){
+ var p = self.option;
+ if($.type(p.initSelected) !== 'undefined' &&
+ !p.regular && list && $.isArray(list) && list.length){
+ var str = String(p.initSelected),arr = str.split(',');
+ var matchItem = function(dataList){
+ $.each(dataList, function(i,row){
+ var id = String(row[p.keyField]);
+ if(id && $.inArray(id,arr) !== -1) self.prop.values.push(row);
+ });
+ };
+ if(self.prop.data_type === SelectMenu.dataTypeList){
+ matchItem(list);
+ }else if(self.prop.data_type === SelectMenu.dataTypeGroup){
+ $.each(list, function(i,group){
+ group && group.list && group.list.length && matchItem(group.list);
+ });
+ }
+ p.initSelected = undefined;
+ }
+ };
+
+ /**
+ * Menu frame event handle
+ */
+ SelectMenu.prototype.eInput = function() {
+ var self = this,p = this.option,el = self.elem;
+ if(!p.regular && p.search){
+ el.input.keyup(function(e) {
+ self.processKey(self, e);
+ }).keydown(function(e){
+ self.processControl(self, e);
+ });
+ }
+ if(p.title){
+ if(!p.embed){
+ el.closeButton.click(function(e){
+ self.hideResults(self);
+ });
+ }
+ if(!p.regular){
+ if(p.multiple){
+ el.selectAllButton.click(function(e){
+ e.stopPropagation();
+ self.selectAllLine(self);
+ });
+ el.removeAllButton.click(function(e){
+ e.stopPropagation();
+ self.clearAll(self);
+ });
+ }
+ }
+ }
+ if(!p.regular && self.prop.data_type === SelectMenu.dataTypeGroup){
+ el.resultTabs.off('click.selectMenu').on('click.selectMenu', 'a', function(e){
+ e.stopPropagation();
+ if(!$(this).hasClass('active')){
+ var li = $(this).closest('li');
+ li.siblings().children('a').removeClass('active');
+ $(this).addClass('active');
+ self.prop.data_index = parseInt($(this).attr('data_index'));
+ self.populate();
+ if(p.eTabSwitch && $.isFunction(p.eTabSwitch)){
+ var currentGroup = $.extend({}, self.prop.data[self.prop.data_index]);
+ //cut the list item
+ delete currentGroup.list;
+ p.eTabSwitch.call(this, self.prop.data_index, currentGroup);
+ }
+ }
+ });
+ }
+ if(p.rightClick){
+ $(self.target).on('contextmenu',function(e){
+ e.preventDefault();
+ e.stopPropagation();
+ e.cancelBubble = true;
+ e.returnValue = false;
+ var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft,
+ scrollY = document.documentElement.scrollTop || document.body.scrollTop;
+ self.prop.x = e.pageX || e.clientX + scrollX;
+ self.prop.y = e.pageY || e.clientY + scrollY;
+ if(!self.isVisible(self)) self.populate();
+ else self.calcResultsSize(self);
+ return false;
+ }).mouseup(function(e){
+ if(e.button != 2) self.hideResults(self);
+ });
+ self.hideResults(self);
+ }
+ };
+
+ /**
+ * Out of menu event bind
+ */
+ SelectMenu.prototype.eWhole = function() {
+ var self = this, css = this.css_class;
+ $(document).off('mouseup.selectMenu').on('mouseup.selectMenu',function(e) {
+ var srcEl = e.target || e.srcElement,
+ sm = $(srcEl).closest('div.' + css.container);
+ //out of menu area click, when menu is opened , hide it
+ $('div.' + css.container + '.' + css.container_open).each(function(){
+ var d = $(this).data(SelectMenu.dataKey);
+ if(this == sm[0] || d.target == srcEl || $(srcEl).closest(d.target).length) return;
+ d.hideResults(d);
+ });
+ });
+ };
+
+ /**
+ * Menu item event bind
+ */
+ SelectMenu.prototype.eResultList = function() {
+ var self = this,p = this.option,el = self.elem;
+ self.elem.results.children('li').mouseenter(function() {
+ if (self.prop.key_select) {
+ self.prop.key_select = false;
+ return;
+ }
+ if(!$(this).hasClass('sm_message_box')) $(this).addClass(self.css_class.select);
+ }).mouseleave(function(){
+ $(this).removeClass(self.css_class.select);
+ }).click(function(e) {
+ if (self.prop.key_select) {
+ self.prop.key_select = false;
+ return;
+ }
+ e.preventDefault();
+ e.stopPropagation();
+
+ self.selectCurrentLine(self, false);
+ });
+ };
+
+ /**
+ * Reposition result list when list beyond the visible area
+ */
+ SelectMenu.prototype.eScroll = function(){
+ var self = this, css = this.css_class;
+ $(window).on('scroll.SelectMenu',function(e){
+ $('div.' + css.container + '.' + css.container_open).each(function(){
+ var d = $(this).data(SelectMenu.dataKey),
+ offset = d.elem.container.offset(),
+ screenScrollTop = $(window).scrollTop(),
+ docHeight = $(document).height(),//the document full height
+ viewHeight = $(window).height(),//browser visible area height
+ menuHeight = d.elem.container.outerHeight(),
+ menuBottom = offset.top + menuHeight,
+ hasOverflow = docHeight > viewHeight,
+ down = d.elem.container.hasClass(css.direction_bottom);
+ if(hasOverflow){
+ if(down){//show down
+ if(menuBottom > (viewHeight + screenScrollTop)) d.calcResultsSize(d);
+ }else{//show up
+ if(offset.top < screenScrollTop) d.calcResultsSize(d);
+ }
+ }
+ });
+ });
+ };
+
+ /**
+ * Closing work
+ * @param {Object} self
+ */
+ SelectMenu.prototype.atLast = function(self){
+ if(!self) self = this;
+ var p = self.option;
+ if(p.search && !p.regular && !p.embed && !p.rightClick) self.elem.input.focus();
+ self.elem.container.data(SelectMenu.dataKey,self);
+ if($(self.target).is('button,.btn') && !p.embed && !p.rightClick)
+ $(self.target).addClass(self.css_class.target_clicked);
+ }
+
+ /**
+ * Ajax request fail
+ * @param {Object} self
+ * @param {string} errorThrown
+ */
+ SelectMenu.prototype.ajaxErrorNotify = function(self, errorThrown) {
+ self.showMessage(self.message.ajax_error);
+ };
+
+ /**
+ * Show some message
+ * @param {Object} self
+ * @param msg {string}
+ */
+ SelectMenu.prototype.showMessage = function(self,msg){
+ if(!msg) return;
+ var msgLi = '<li class="sm_message_box"><i class="iconfont icon-warn"></i> '+msg+'</li>';
+ self.elem.results.empty().append(msgLi);
+ self.calcResultsSize(self);
+ self.elem.container.addClass(self.css_class.container_open);
+ self.elem.control.hide();
+ };
+
+ /**
+ * Check input to search
+ * @param {Object} self
+ */
+ SelectMenu.prototype.checkValue = function(self) {
+ var now_value = self.elem.input.val();
+ if (now_value != self.prop.prev_value) {
+ self.prop.prev_value = now_value;
+ self.suggest(self);
+ }
+ };
+
+ /**
+ * Input element event handle( regular letter )
+ * @param {Object} self
+ * @param {Object} e - event
+ */
+ SelectMenu.prototype.processKey = function(self, e){
+ if($.inArray(e.keyCode, [38, 40, 27, 9, 13]) === -1){
+ //if(e.keyCode != 16) self.setCssFocusedInput(self); // except Shift(16)
+ if($.type(self.option.data) === 'string'){
+ self.prop.last_input_time = e.timeStamp;
+ setTimeout(function(){
+ if((e.timeStamp - self.prop.last_input_time) === 0)
+ self.checkValue(self);
+ },self.option.inputDelay * 1000);
+ }else{
+ self.checkValue(self);
+ }
+ }
+ }
+
+ /**
+ * Input element event handle( control key )
+ * @param {Object} self
+ * @param {Object} e - event
+ */
+ SelectMenu.prototype.processControl = function(self, e) {
+ if (($.inArray(e.keyCode, [38, 40, 27, 9]) > -1 && self.elem.container.is(':visible')) ||
+ ($.inArray(e.keyCode, [13, 9]) > -1 && self.getCurrentLine(self))) {
+ e.preventDefault();
+ e.stopPropagation();
+ e.cancelBubble = true;
+ e.returnValue = false;
+ switch (e.keyCode) {
+ case 38:// up
+ self.prop.key_select = true;
+ self.prevLine(self);
+ break;
+ case 40:// down
+ if (self.elem.results.children('li').length) {
+ self.prop.key_select = true;
+ self.nextLine(self);
+ } else self.suggest(self);
+ break;
+ case 9: // tab
+ self.selectCurrentLine(self, true);
+ //self.hideResults(self);
+ break;
+ case 13:// return
+ self.selectCurrentLine(self, true);
+ break;
+ case 27:// escape
+ self.hideResults(self);
+ break;
+ }
+ }
+ };
+
+
+ /**
+ * Populate menu data
+ */
+ SelectMenu.prototype.populate = function() {
+ var self = this, p = this.option;
+ if(!p.regular) self.elem.input.val('');
+ /**
+ * 1.Process data source
+ */
+ if(p.data){
+ if($.type(p.data) === 'array'){
+ self.prop.data = p.data;
+ }else if($.type(p.data) === 'function'){
+ self.prop.data = p.data();
+ }
+ }
+ //Check data type
+ if($.type(self.prop.data) === 'array')
+ this.prop.data_type = this.checkDataType(self.prop.data);
+ /**
+ * 2.Set menu init selected
+ */
+ if($.type(p.data) !== 'string') self.setInitSelected(self, self.prop.data);
+ /**
+ * 3.Show data
+ */
+ if(p.regular) self.regularMenuInit();
+ else self.suggest(self);
+
+ //scrolling listen
+ if(!p.embed) self.eScroll();
+ };
+
+ /**
+ * Search suggest
+ * @param {Object} self
+ */
+ SelectMenu.prototype.suggest = function(self) {
+ var q_word, p = self.option,
+ val = $.trim(self.elem.input.val());
+ if(p.multiple) q_word = val;
+ else{
+ if(val && val === self.prop.selected_text) q_word = '';
+ else q_word = val;
+ }
+ q_word = q_word.split(/[\s ]+/);
+ self.setLoading(self);
+ if ($.type(p.data) === 'array' || $.type(p.data) === 'function') self.search(self, q_word);
+ };
+
+ /**
+ * Loading
+ * @param {Object} self
+ */
+ SelectMenu.prototype.setLoading = function(self) {
+ if (self.elem.results.html() === '') {
+ //self.calcResultsSize(self);
+ if(!self.option.embed) self.elem.container.addClass(self.css_class.container_open);
+ }
+ };
+
+ /**
+ * Search / load menu data
+ * @param {Object} self
+ * @param {Array} q_word - query keywords
+ */
+ SelectMenu.prototype.search = function(self, q_word) {
+ var p = self.option, innerData = self.prop.data,
+ matched = [], esc_q = [], sorted = [], json = {}, i = 0, arr_reg = [];
+ do {
+ //'/\W/g'正则代表全部不是字母,数字,下划线,汉字的字符
+ //将非法字符进行转义
+ esc_q[i] = q_word[i].replace(/\W/g, '\\$&').toString();
+ arr_reg[i] = new RegExp(esc_q[i], 'gi');
+ i++;
+ } while ( i < q_word.length );
+ var d = [];
+ if(self.prop.data_index > (innerData.length-1) || self.prop.data_index < 0) self.prop.data_index = 0;
+ if(self.prop.data_type === SelectMenu.dataTypeGroup){
+ d = innerData[self.prop.data_index].list;
+ }else d = innerData;
+ // SELECT * FROM data WHERE field LIKE q_word;
+ for (i = 0; i < d.length; i++) {
+ var flag = false;
+ var row = d[i];
+ for (var j = 0; j < arr_reg.length; j++) {
+ var itemText = row[p.searchField];
+ if(p.formatItem && $.isFunction(p.formatItem))
+ itemText = p.formatItem(row);
+ if (itemText.match(arr_reg[j])) {
+ flag = true;
+ if (p.andOr == 'OR') break;
+ } else {
+ flag = false;
+ if (p.andOr == 'AND') break;
+ }
+ }
+ if (flag) matched.push(row);
+ }
+
+ // (CASE WHEN ...) then く order some field
+ var reg1 = new RegExp('^' + esc_q[0] + '$', 'gi'),
+ reg2 = new RegExp('^' + esc_q[0], 'gi'),
+ matched1 = [], matched2 = [], matched3 = [];
+ for (i = 0; i < matched.length; i++) {
+ var orderField = p.orderBy[0][0],
+ orderValue = String(matched[i][orderField]);
+ if (orderValue.match(reg1)) {
+ matched1.push(matched[i]);
+ } else if (orderValue.match(reg2)) {
+ matched2.push(matched[i]);
+ } else {
+ matched3.push(matched[i]);
+ }
+ }
+
+ if (p.orderBy[0][1].match(/^asc$/i)) {
+ matched1 = self.sortAsc(self, matched1);
+ matched2 = self.sortAsc(self, matched2);
+ matched3 = self.sortAsc(self, matched3);
+ } else {
+ matched1 = self.sortDesc(self, matched1);
+ matched2 = self.sortDesc(self, matched2);
+ matched3 = self.sortDesc(self, matched3);
+ }
+ sorted = sorted.concat(matched1).concat(matched2).concat(matched3);
+
+ /*
+ if (sorted.length === undefined || sorted.length === 0 ) {
+ self.notFoundSearch(self);
+ return;
+ }
+ */
+ //json.cnt_whole = sorted.length;
+
+ //Cache original row data
+ json.originalResult = [];
+ if(json.keyField === undefined) json.keyField = [];
+ if(json.candidate === undefined) json.candidate = [];
+
+ $.each(sorted, function(i,row){
+ if(row === undefined || $.type(row) !== 'object') return true;
+ json.originalResult.push(row);
+ if(row.hasOwnProperty(p.keyField) && row.hasOwnProperty(p.showField)){
+ json.keyField.push(row[p.keyField]);
+ json.candidate.push(row[p.showField]);
+ }
+ });
+
+ //json.cnt_page = json.candidate.length;
+ self.prepareResults(self, json, q_word);
+ };
+
+ /**
+ * Sort ascending
+ * @param {Object} self
+ * @param {Array} arr
+ */
+ SelectMenu.prototype.sortAsc = function(self, arr) {
+ arr.sort(function(a, b) {
+ var valA = a[self.option.orderBy[0][0]],
+ valB = b[self.option.orderBy[0][0]];
+ return $.type(valA) === 'number' ? valA - valB : String(valA).localeCompare(String(valB));
+ });
+ return arr;
+ };
+
+ /**
+ * Sort descending
+ * @param {Object} self
+ * @param {Array} arr
+ */
+ SelectMenu.prototype.sortDesc = function(self, arr) {
+ arr.sort(function(a, b) {
+ var valA = a[self.option.orderBy[0][0]],
+ valB = b[self.option.orderBy[0][0]];
+ return $.type(valA) === 'number' ? valB - valA : String(valB).localeCompare(String(valA));
+ });
+ return arr;
+ };
+
+ /**
+ * No result handle
+ * @param {Object} self
+ */
+ SelectMenu.prototype.notFoundSearch = function(self) {
+ self.elem.results.empty();
+ self.calcResultsSize(self);
+ self.elem.container.addClass(self.css_class.container_open);
+ self.setCssFocusedInput(self);
+ };
+
+ /**
+ * Prepare data to render menu item
+ * @param {Object} self
+ * @param {Object} json
+ * @param {Array} q_word - query keywords
+ */
+ SelectMenu.prototype.prepareResults = function(self, json, q_word) {
+ if (!json.keyField) json.keyField = false;
+
+ if (self.option.selectOnly &&
+ json.candidate.length === 1 &&
+ json.candidate[0] == q_word[0]) {
+ self.elem.hidden.val(json.keyField[0]);
+ this.setButtonAttrDefault();
+ }
+ var is_query = false;
+ if (q_word && q_word.length && q_word[0]) is_query = true;
+ //self.setInitSelected(self,json.originalResult);
+ self.displayResults(self, json, is_query);
+ };
+
+ /**
+ * Render menu item
+ * @param {Object} self
+ * @param {Object} json
+ * @param {boolean} is_query
+ */
+ SelectMenu.prototype.displayResults = function(self, json, is_query) {
+ var p = self.option, el = self.elem, css = self.css_class;
+ el.results.hide().empty();
+
+ // build tabs
+ if(self.prop.data_type === SelectMenu.dataTypeGroup) {
+ var ul = $('<ul>');
+ $.each(self.prop.data,function(i,row){
+ var a = $('<a href="javascript:void(0);">').html(row.title).attr({
+ 'tab_id' : self.prop.menu_tab_id_prefix + (i+1),
+ 'data_index' : i
+ });
+ if(i === self.prop.data_index) a.addClass('active');
+ var li = $('<li>').append(a);
+ ul.append(li);
+ });
+ el.resultTabs.empty().append(ul);
+ }else{
+ el.resultTabs.hide();
+ if(p.title || p.search) el.resultArea.addClass(this.css_class.re_list);
+ }
+
+ if(p.multiple && $.type(p.maxSelectLimit) === 'number' && p.maxSelectLimit){
+ var selectedSize = self.prop.results.length;
+ if(selectedSize && selectedSize >= p.maxSelectLimit){
+ var msg = self.message.max_selected;
+ self.showMessage(self, msg.replace(self.template.msg.maxSelectLimit, p.maxSelectLimit));
+ return;
+ }
+ }
+
+ if(json.candidate.length){
+ var arr_candidate = json.candidate, arr_primary_key = json.keyField;
+ for (var i = 0; i < arr_candidate.length; i++) {
+ var itemText = '', custom = false, row = json.originalResult[i];
+ if(p.formatItem && $.isFunction(p.formatItem)){
+ try {
+ itemText = p.formatItem(row);
+ custom = true;
+ } catch (e) {
+ console.error('formatItem 内容格式化函数内容设置不正确!');
+ itemText = arr_candidate[i];
+ }
+ }else itemText = arr_candidate[i];
+ var icon = $('<div>').html('<i class="iconfont icon-selected">').addClass(css.selected_icon),
+ text = $('<div>').html(itemText).addClass(css.item_text),
+ li = $('<li>').append(icon).append(text).attr('pkey' , arr_primary_key[i]);
+ if(!custom) li.attr('title',itemText);
+
+ //set selected item to highlight
+ if ($.inArray(row,self.prop.values) !== -1) {
+ li.addClass(css.selected);
+ }
+ //cache item data
+ li.data('dataObj',row);
+ el.results.append(li);
+ }
+ }else{
+ var li = '<li class="sm_message_box"><i class="iconfont icon-warn"></i> ' + self.message.not_found + '</li>';
+ el.results.append(li);
+ }
+ el.results.show();
+
+ self.calcResultsSize(self);
+ if(!p.embed) el.container.addClass(css.container_open);
+
+ //menu item event bind
+ self.eResultList();
+ //auto highlight first item in search, in have result and set autoSelectFirst to true situation
+ //if (is_query && json.candidate.length > 0 && p.autoSelectFirst) self.nextLine(self);
+ self.atLast(self);
+ };
+
+ /**
+ * Calculate menu position and size
+ * @param {Object} self
+ */
+ SelectMenu.prototype.calcResultsSize = function(self) {
+ var p = self.option, el = self.elem, css = self.css_class,
+ hasScroll = function(){
+ return $(document).height() > $(window).height();
+ };
+ var setListHeight = function(){
+ if(!p.regular){
+ //result list height
+ var itemHeight = el.results.find('li:first').outerHeight(),
+ listHeight = itemHeight * p.listSize;
+ el.results.css({
+ 'max-height':listHeight
+ });
+ }
+ };
+ var scrollFlag = hasScroll();
+ var rePosition = function(){
+ var menuHeight = el.container.outerHeight(),
+ screenScrollTop = $(window).scrollTop(),
+ viewHeight = $(window).height();
+ if(p.rightClick){
+ var top = self.prop.y;
+ if((self.prop.y + menuHeight) > (screenScrollTop + viewHeight))
+ top = self.prop.y - menuHeight;
+ return {top : top, left : self.prop.x};
+ }
+ var boxoffset = $(self.target).offset(),
+ t = boxoffset.top,
+ menuWidth = el.container.outerWidth(),
+ targetWidth = Math.round($(self.target)[0].getBoundingClientRect().width),
+ dist = 5;
+ t += $(self.target).outerHeight() + dist;
+ if(p.arrow && !p.embed) t += el.arrow.outerHeight(true);
+
+ if((t + menuHeight) > (screenScrollTop + viewHeight)){
+ t = boxoffset.top - dist - menuHeight;
+ if(p.arrow && !p.embed) t -= el.arrow.outerHeight(true);
+ el.container.removeClass(css.direction_bottom).addClass(css.direction_top);
+ }else{
+ if(el.container.hasClass(css.direction_top))
+ el.container.removeClass(css.direction_top).addClass(css.direction_bottom);
+ }
+
+ var l = boxoffset.left;
+ switch (p.position){
+ case 'right':
+ l = l + targetWidth - menuWidth;
+ if(p.arrow) el.arrow.css('left',menuWidth - (targetWidth / 2));
+ break;
+ case 'center':
+ l = l + (targetWidth / 2) - (menuWidth / 2);
+ break;
+ case 'left':
+ default:
+ if(p.arrow) el.arrow.css('left',targetWidth / 2);
+ break;
+ }
+ return {top : t,left : l};
+ }
+ if(el.container.is(':visible')){
+ setListHeight();
+ if(!p.embed) el.container.offset(rePosition());
+ }else{
+ el.container.show(1,function(){
+ setListHeight();
+ $(this).offset(rePosition());
+ });
+ }
+ if(scrollFlag !== hasScroll()) el.container.offset(rePosition());
+ };
+
+ /**
+ *
+ */
+ SelectMenu.prototype.subMenuPosition = function(parent, menu){
+ var pOffset = $(parent).offset();
+ var t = pOffset.top,l = pOffset.left + $(parent).outerWidth() + 5;
+ };
+
+ /**
+ * Hide menu
+ * @param {Object} self
+ */
+ SelectMenu.prototype.hideResults = function(self) {
+ var p = self.option;
+ if (p.autoFillResult) {
+ //self.selectCurrentLine(self, true);
+ }
+
+ if(!p.regular) self.elem.results.empty();
+ if(!p.embed){
+ self.elem.container.removeClass(self.css_class.container_open).hide();
+ if($(self.target).is('button,.btn')) $(self.target).removeClass(self.css_class.target_clicked);
+ }
+ self.elem.resultArea.find('ul.'+self.css_class.results).not('.'+self.css_class.menu_root).hide();
+ //remove animate class
+ self.elem.results.removeClass('vivify').removeClass('fadeInLeft').show();
+ $(window).off('scroll.SelectMenu');
+ if(!p.regular && p.eHidden && $.isFunction(p.eHidden)) p.eHidden.call(self, self.prop.values.concat());
+ };
+ /**
+ * do something after select/unSelect action
+ * @param {Object} self
+ */
+ SelectMenu.prototype.afterAction = function(self){
+ //$(self.elem.input).change();
+ if(self.option.multiple){
+ if(self.option.selectToCloseList){
+ self.hideResults(self);
+ self.elem.input.blur();
+ }else{
+ //self.suggest(self);
+ self.elem.input.focus();
+ }
+ }else{
+ self.hideResults(self);
+ self.elem.input.blur();
+ }
+ };
+
+ /**
+ * Get current menu item
+ * @param {Object} self
+ */
+ SelectMenu.prototype.getCurrentLine = function(self) {
+ if (self.elem.container.is(':hidden')) return false;
+ var obj = self.elem.results.find('li.' + self.css_class.select);
+ if (obj.length) return obj;
+ else return false;
+ };
+
+ /**
+ * Get selected menu item
+ * @param self
+ * @returns {*}
+ */
+ SelectMenu.prototype.getSelectedLine = function(self) {
+ if (self.elem.container.is(':hidden')) return false;
+ var obj = self.elem.results.find('li.' + self.css_class.selected);
+ if (obj.length) return obj;
+ else return false;
+ };
+
+ /**
+ * Selected menu item and trigger select callback
+ * @param {Object} self
+ * @param {boolean} is_enter_key
+ */
+ SelectMenu.prototype.selectCurrentLine = function(self, is_enter_key) {
+ var current = self.getCurrentLine(self), p = self.option;
+ if (current) {
+ var rowData = current.data('dataObj'),
+ id = String(rowData[p.keyField]);
+ if($.inArray(rowData,self.prop.values) === -1){
+ if(!p.multiple) self.prop.values.splice(0,self.prop.values.length);
+ self.prop.values.push(rowData);
+ if(!p.multiple)
+ self.elem.results.find('li.' + self.css_class.selected).removeClass(self.css_class.selected);
+ current.addClass(self.css_class.selected);
+ } else{
+ self.prop.values.splice($.inArray(rowData,self.prop.values),1);
+ current.removeClass(self.css_class.selected);
+ }
+
+ //trigger callback
+ if(p.eSelect && $.isFunction(p.eSelect)){
+ if(p.multiple){
+ p.eSelect.call(self, self.prop.values.concat());
+ }else p.eSelect.call(self, [rowData]);
+ }
+
+ self.prop.prev_value = self.elem.input.val();
+ self.prop.selected_text = self.elem.input.val();
+ }
+ if(!p.embed) self.afterAction(self);
+ };
+
+ /**
+ * Select all menu item
+ * @param {Object} self
+ */
+ SelectMenu.prototype.selectAllLine = function(self){
+ self.elem.results.find('li').each(function(i,row){
+ var d = $(row).data('dataObj');
+ if($.inArray(d,self.prop.values) === -1) self.prop.values.push(d);
+ $(this).addClass(self.css_class.selected);
+ //limited max select items
+ /*
+ if($.type(self.option.maxSelectLimit) === 'number' &&
+ self.option.maxSelectLimit > 0 &&
+ self.option.maxSelectLimit === $('li.selected_tag',self.elem.element_box).length){
+ return false;
+ }
+ */
+ });
+ if(self.option.eSelect && $.isFunction(self.option.eSelect))
+ self.option.eSelect.call(self, self.prop.values.concat());
+ self.afterAction(self);
+ };
+ /**
+ * Clear all selected menu items
+ * @param {Object} self
+ */
+ SelectMenu.prototype.clearAll = function(self){
+ var p = self.option, el = self.elem;
+ el.input.val('');
+ el.results.find('li').each(function(i,row){
+ $(this).removeClass(self.css_class.selected);
+ });
+ self.prop.values.splice(0,self.prop.values.length);
+ self.afterAction(self);
+ if (p.eSelect && $.isFunction(p.eSelect)) p.eSelect.call(self, []);
+ };
+
+ /**
+ * Select next menu item
+ * @param {Object} self
+ */
+ SelectMenu.prototype.nextLine = function(self) {
+ var obj = self.getCurrentLine(self), el = self.elem, idx;
+ if (!obj) idx = -1;
+ else {
+ idx = el.results.children('li').index(obj);
+ obj.removeClass(self.css_class.select);
+ }
+ idx++;
+ var size = el.results.find('li').length;
+ if(idx === size) idx = size - 1;
+ if (idx < size) {
+ var next = el.results.children('li').eq(idx);
+ next.addClass(self.css_class.select);
+
+ var itemHeight = el.results.find('li:first').outerHeight(),
+ curTop = next.position().top,
+ curScrollTop = el.resultArea.scrollTop(),
+ listHeight = el.resultArea.outerHeight(),
+ dist = curTop + itemHeight - listHeight;
+ if((curTop + itemHeight) > listHeight)
+ el.resultArea.scrollTop(curScrollTop + dist);
+ }
+ };
+
+ /**
+ * Select previous menu item
+ * @param {Object} self
+ */
+ SelectMenu.prototype.prevLine = function(self) {
+ var el = self.elem, idx, obj = self.getCurrentLine(self);
+ if (!obj) idx = el.results.children('li').length;
+ else {
+ idx = el.results.children('li').index(obj);
+ obj.removeClass(self.css_class.select);
+ }
+ idx--;
+ if(idx < 0) idx = 0;
+ if (idx > -1) {
+ var prev = el.results.children('li').eq(idx),
+ itemHeight = el.results.find('li:first').outerHeight(),
+ curTop = prev.position().top,
+ curScrollTop = el.resultArea.scrollTop(),
+ listHeight = el.resultArea.outerHeight();
+ prev.addClass(self.css_class.select);
+ if((curTop > (curScrollTop + listHeight)) || (curTop < curScrollTop))
+ el.resultArea.scrollTop(curScrollTop - (0 - curTop));
+ }
+ };
+
+ /**
+ * Check menu visible
+ * @param self
+ */
+ SelectMenu.prototype.isVisible = function(self){
+ return self.elem.container.hasClass(self.css_class.container_open);
+ }
+
+
+ /**
+ * Init plugin entrance
+ * @global
+ * @memberof jQuery
+ * @param option {Object} init parameters
+ */
+ function Plugin(option) {
+ return this.each(function(){
+ var $this = $(this),
+ data = $this.data(SelectMenu.dataKey),
+ params = $.extend({}, defaults, $this.data(), data && data.option ,typeof option === 'object' && option);
+ if(!data) $this.data(SelectMenu.dataKey,(data = new SelectMenu(this,params)));
+ else{
+ if(data.isVisible(data)) data.hideResults(data);
+ else data.showMenu(data);
+ }
+ });
+ }
+
+ /**
+ * Hide menu
+ */
+ function HideMenu(){
+ return this.each(function(){
+ var $this = $(this),
+ data = $this.data(SelectMenu.dataKey);
+ if(data) data.hideResults(data);
+ });
+ }
+
+ /**
+ * Clear all menu selected item
+ */
+ function ClearSelected(){
+ return this.each(function(){
+ var $this = $(this),
+ data = $this.data(SelectMenu.dataKey);
+ if(data) data.clearAll(data);
+ });
+ }
+
+ /**
+ * Get selected item data
+ */
+ function GetSelected(){
+ var results = new Array();
+ this.each(function(){
+ var $this =$(this),
+ data = $this.data(SelectMenu.dataKey);
+ if(data) results = data.prop.values.concat();
+ });
+ return results;
+ }
+
+ var old = $.fn.selectMenu;
+
+ $.fn.selectMenu = Plugin;
+ $.fn.selectMenu.Constructor = SelectMenu;
+ $.fn.selectMenuHide = HideMenu;
+ $.fn.selectMenuClear = ClearSelected;
+ $.fn.selectMenuValues = GetSelected;
+
+ // SelectMenu no conflict
+ // =================
+ $.fn.selectMenu.noConflict = function () {
+ $.fn.selectMenu = old;
+ return this;
+ };
+})(window.jQuery); \ No newline at end of file