Your IP : 18.219.40.177


Current Path : /usr/local/mgr5/skins/orion/src/
Upload File :
Current File : //usr/local/mgr5/skins/orion/src/App.Select.js

/**
 * Select Module
 *  @param {object} window  global object
 *  @param {function} $ jQuery library
 *  @param {object} EventMgr EventMgr library
 *  @param {object} App Application
 *  @return {object} api
 */
App.Select = function(window, $, EventMgr, App) {
  'use strict';

  var UPKEY = 38,
      DOWNKEY = 40,
      LEFTKEY = 37,
      RIGHTKEY = 39,
      ENTERKEY = 13,
      TABKEY = 9,
      ESCKEY = 27,
      SPACE = 32,
      //wrapper for select
      selectSelector = '.b-myselect:not(".readonly")' +
          ' .b-myselect__select-selected',
      //wrapper for select item
      selectItemSelector = '.b-myselect:not(".readonly")' +
          ' .b-myselect__select-li',
      selectKeySelector = '.b-myselect:not(".readonly")' +
          ' .b-myselect__select-selected,' +
          ' .b-myselect:not(".readonly") .sb-input',
      CACHE = {},
      CACHEOPENEDSELECT = {},

      dependSlistSelector = '.depend.b-myselect input[type="hidden"],' +
          ' .depend.b-select-ac input[type="hidden"],' +
          ' .depend.b-radio input[type="hidden"]';

  function $body() {
    return $('body');
  }

  function getActiveTabId() {
    return ($('.tab-content_st_active').attr('data-tabid') || false);
  }
  //flag for active select list
  function $content() {
    return App.Common.selectorCache('.i-form-wr');
  }

  function $selectCont(id) {
    if (id) {
      return $('#' + id + '.b-myselect');
    } else {
      return $('.b-myselect');
    }
  }

  //add /remove handler for body, for close selectlist
  function addRemoveHandlerForBody(add) {
    if (add) {
      $body().on('click', bodyHandlerClick);
    } else {
      $body().off('click', bodyHandlerClick);
    }
  }

  function closeOtherSelectList(tabId, click) {
    if (!tabId) {
      tabId = getActiveTabId();
    }
    if (CACHEOPENEDSELECT[tabId] && CACHEOPENEDSELECT[tabId].removeClass) {
      CACHEOPENEDSELECT[tabId].addClass('b-myselect_st_close')
          .removeClass('b-myselect_st_open');
      addRemoveHandlerForBody();
    }
  }

  function bodyHandlerClick(e) {
    if (e) {
      var scrElemClass = e.srcElement ?
              e.srcElement.className : e.target ? e.target.className : '',
          scrollFlag = scrElemClass.indexOf('scrlbr'),
          highlightFlag = scrElemClass.indexOf('highlight');
      if (scrollFlag === -1 && highlightFlag === -1) {
        closeOtherSelectList();
      }
    } else {
      //what is it?!
      e.stopPropagation();
    }
  }
  //click for select
  function selectListHandler(e) {
    e.preventDefault();
    e.stopPropagation();
    var id = this.getAttribute('data-id'),
        $selectContVar = $selectCont(id),
        ids, searchBox,
        tabId = getActiveTabId(), keySymbol, r;
    //check current state option list
    if (!$selectContVar.hasClass('b-myselect_st_open')) {
      $('body').trigger('click');
      closeOtherSelectList(tabId);
      $selectContVar
          .removeClass('b-myselect_st_close')
          .addClass('b-myselect_st_open');
      //set optionlist position
      App.Common.setOptionListPosition('#opt', id);

      ids = $selectContVar.find('.b-myselect__select-list').attr('id');
      EventMgr.trigger('updateScroll', { id: ids });
      addRemoveHandlerForBody(true);
      //set focus on searchbox
      if (this.parentNode.className.match('sb-select')) {
        searchBox = App.Dom.byId('sb-' + ids);
        if (searchBox) {
          //try guess symbol of pressed key
          if (e && e.originalEvent) {
            if (e.originalEvent.key) {
              keySymbol = e.originalEvent.key;
              if (keySymbol.length > 1) {
                keySymbol = null;
              }
            }
          }
          searchBox.value = keySymbol || '';
          setTimeout(function() {
            findElemsInSelect.apply(searchBox, [{ codeKey: 'ololo' }]);
          }, 1);
          searchBox.focus();
          //set cursor after 1st symbol
          if (keySymbol) {
            if (searchBox.setSelectionRange) {
              searchBox.setSelectionRange(1, 1);
            } else {
              r = searchBox.createTextRange();
              r.collapse(true);
              r.select(1, 1);
            }
          }
          window.scrollToTopLeft();
        }
      }
      CACHEOPENEDSELECT[tabId] = $selectContVar;
    } else {
      $selectContVar
          .removeClass('b-myselect_st_open')
          .addClass('b-myselect_st_close');
      delete CACHEOPENEDSELECT[tabId];
      addRemoveHandlerForBody(false);
      this.childNodes[1].focus();
      window.scrollToTopLeft();
    }
  }

  //select item handler
  function setSelectedValue(e, sv, close) {
    var self = $(this),
        val = this.getAttribute('data-val'),
        handlerVal = this.getAttribute('data-handler-val'),
        content = self.html(),
        id = self.parent().attr('data-id'),
        currentSelect = $('#' + id + ' .b-myselect__select-value');
    if (self.hasClass('group')) {
      return;
    }
    const $inputValue = $('input#' + id + '-val');
    const prevValue = $inputValue.val();

    //вызываем change только при изменение значения, чтобы не зациклить setvalues
    if (prevValue !== val) {
      $inputValue.val(val)
        .attr('data-handler-val', handlerVal)
        .trigger('change', [sv, close]);
    }
    //if it clone from search - search self made it
    if (!self.hasClass('b-myselect__select-li_clone_true')) {
      self.addClass('selected').siblings().removeClass('selected');
    } else if (!e) {
      //up/down keydown
      self.addClass('selected')
          .siblings().removeClass('selected');
      self.trigger('customclick');
      content = self.siblings('.selected')
          .find('.b-myselect__option-value').html();
    }
    currentSelect.html(content);
    if (close !== false) {
      $body().trigger('click');
      if (e && !e.isTrigger) {
        currentSelect.focus();
        window.scrollToTopLeft();
      }
    }
    EventMgr.trigger('selectChange', { id: id });
  }

  //идем по селекту вниз downkey
  function selectListNext(e) {
    var tabId = getActiveTabId(),
        id = this.getAttribute('data-id'),
        l,
        currentLi = $('#' + id + ' li.selected'),
        nextLi = currentLi.next(),
        next = true,
        closed = currentLi.parent()[0].offsetWidth ? false : true;
    if (!currentLi[0].offsetWidth && !closed) {
      currentLi = $('#' + id + ' li[style$="display: block;"]');
      l = currentLi.length;
      if (l > 0) {
        setSelectedValue.apply(currentLi[0], [false, false, false]);
        return;
      }
    }
    while (next) {
      if (nextLi.length === 0) {
        return;
        //detect showed elements by class 'show'
      } else if (nextLi[0].offsetWidth && !closed) {
        next = false;
      } else if (closed && nextLi[0].className.match('b-myselect__select-li_show_yes')) {
        next = false;
      } else {
        nextLi = nextLi.next();
      }
    }
    setSelectedValue.apply(nextLi[0], [false, false, false]);
    var offsetTop = nextLi[0].offsetTop,
        scrollId = 'cont-' + id;

    //if (offsetTop != 0) {
    ScrollHandler.forceMoveSelectItem(scrollId, offsetTop);
    //}
  }

  //идем по селекту вверх upkey
  function selectListPrev() {
    var tabId = getActiveTabId(),
        id = this.getAttribute('data-id'),
        l,
        currentLi = $('#' + id + ' li.selected'),
        prevLi = currentLi.prev(),
        prev = true,
        closed = currentLi.parent()[0].offsetWidth ? false : true;
    if (!currentLi[0].offsetWidth && !closed) {
      currentLi = $('#' + id + ' li[style$="display: block;"]');
      l = currentLi.length;
      if (l > 0) {
        setSelectedValue.apply(currentLi[l - 1], [false, false, false]);
        return;
      }

    }
    while (prev) {
      if (prevLi.length === 0) {
        return;
        //detect showed elements by class 'show'
      } else if (prevLi[0].offsetWidth && !closed) {
        prev = false;
      } else if (closed && prevLi[0].className.match('b-myselect__select-li_show_yes')) {
        prev = false;
      } else {
        prevLi = prevLi.prev();
      }
    }

    setSelectedValue.apply(prevLi[0], [false, false, false]);
    var offsetTop = prevLi[0].offsetTop,
        scrollId = 'cont-' + id;

    //if (offsetTop !== 0) {
    ScrollHandler.forceMoveSelectItem(scrollId, offsetTop);
    //}
  }

  //обработчик клавишных нажатий по селекту
  function selectListKeyDownHandler(e) {
    var codeKey = e.which || e.keyCode,
        tabId = this.getAttribute('data-tabid'),
        listOpened = !!CACHEOPENEDSELECT[tabId];
    //by ENTER and SPACE
    if ((codeKey === ENTERKEY || codeKey === SPACE) &&
        !e.ctrlKey && this.type !== 'text') {
      e.preventDefault();
      selectListHandler.apply(this, [e]);
      //by ENTER and SPACE search field
    } else if (codeKey === ENTERKEY && !e.ctrlKey && this.type === 'text') {
      selectFindFirstElem(this);
      e.preventDefault();
      //by TABKEY when openlist
    } else if ((codeKey === TABKEY || codeKey === ESCKEY) && listOpened) {
//      e.preventDefault();
//      closeSelectList(e, true);
      e.stopPropagation();
      closeOtherSelectList(false, true);
      //UP or LEFT when list opened
    } else if ((codeKey === UPKEY || codeKey === LEFTKEY) &&
        ! listOpened && !e.ctrlKey && this.type !== 'text') {
      e.preventDefault();
      selectListPrev.apply(this, [e]);
      //DOWN or RIGHT list opened
    } else if ((codeKey === DOWNKEY || codeKey === RIGHTKEY) &&
        ! listOpened && !e.ctrlKey && this.type !== 'text') {
      e.preventDefault();
      selectListNext.apply(this, [e]);
      //DOWN when list closed
    } else if (codeKey === DOWNKEY && listOpened && !e.ctrlKey) {
      e.preventDefault();
      selectListNext.apply(this, [e]);
      //UP when list closed
    } else if (codeKey === UPKEY && listOpened && !e.ctrlKey) {
      e.preventDefault();
      selectListPrev.apply(this, [e]);
      //Open by any symbol
    } else if (this.type !== 'text' && codeKey > 32) {
      selectListHandler.apply(this, [e]);
    }
  }

  function selectFindFirstElem(self) {
    var id, sElem, selElem,
        currentSelect;
    id = self.getAttribute('data-id');
    sElem = $('#' + id);
    if (sElem.length === 0) { return; }
    selElem = sElem.find('li.selected:visible');
    if (selElem.length !== 0) {
      selElem.trigger('click');
    } else {
      selElem = sElem.find('li:visible:first');
      if (selElem.length !== 0) {
        selElem.trigger('click');
      } else {
        $('body').trigger('click');
      }
    }
    //set focus on select
    currentSelect = $('#' + sElem.attr('data-id') +
        ' .b-myselect__select-value');
    currentSelect.focus();
    window.scrollToTopLeft();
  }

  var matchesElems = {};
  //поиск по селекту
  function findElemsInSelect(e) {
    e = e || window.event;
    var codeKey = e.which || e.keyCode;
    if (codeKey === UPKEY || codeKey === DOWNKEY || TABKEY === codeKey) {
      return;
    }
    var value, id, sElem, sElems, len, regEx, words, wLen,
        find, inner, searchAll = true, optListId,
        curElem, selElems, tabId, matches, listParent;
    value = this.value.toLowerCase();

    value = App.u.escapeRegExp(value);
    id = this.getAttribute('data-id');
    sElem = App.Dom.byId(id);
    if (!sElem) { return; }
    var $sElem = $(sElem);
    optListId = String(sElem.getAttribute('data-id'));
    sElems = sElem.children;
    len = sElems.length;
    tabId = this.getAttribute('data-tabId');
    //cache html nodes
    if (!CACHE[tabId]) {
      CACHE[tabId] = {};
    }
    if (!CACHE[tabId][id]) {
      sElems = sElem.children;
      selElems = [];
      var l = sElems.length,
          t1, pushed,
          clone;
      while (l--) {
        clone = sElems[l].cloneNode(true);
        clone.className += ' b-myselect__select-li_clone_true';
        t1 = $(clone).find('.b-myselect__option-value');
        /* jslint loopfunc:true */
        pushed = selElems.push({
          node: sElems[l],
          clone: clone,
          innerNode: t1,
          inner: t1.html(),
          bindClick: function() {
            var $clone = $(this.clone);
            $clone.bind('click', $.proxy(function(e) {
              this.returnDefValue();
              var $node = $(this.node);
              $node.addClass('selected')
                  .siblings().removeClass('selected');
              //for unknow reasons it doesn't bubble to parent li
              //force click
              if (e) {
                var scrElemClass = e.srcElement ?
                    e.srcElement.className : e.target ? e.target.className : '';
                if (scrElemClass.indexOf('highlight') === 0) {
                  $node.trigger('click');
                }
              }
            }, this));

            $clone.bind('customclick', $.proxy(function() {
              var $node = $(this.node);
              $node.addClass('selected');
            }, this));
          },
          returnDefValue: function() {
            if (this.isMatched) {
              this.innerNode.html(this.inner);
            }
            this.isMatched = false;
          }
        });
        /* jslint loopfunc:false */
        selElems[pushed - 1].bindClick();
        CACHE[tabId][id] = selElems;
      }
    } else {
      selElems = CACHE[tabId][id];
      len = selElems.length;
    }
    if (value === '') {
      //show all elems in list
      $sElem.removeClass('b-myselect__select-ul_searching_true');
      hideElement(matchesElems[id]);
      scrollToSelectedElement(sElem, id);
      EventMgr.trigger('updateScroll', { id: 'cont-' + id });
      return;
    } else {
      $sElem.addClass('b-myselect__select-ul_searching_true');
    }
    if (!searchAll) {
      regEx = new RegExp('^' + value);
    } else {
      regEx = new RegExp(value);
    }

    var wordLowerCase = '';
    matchesElems[id] = [];

    while (len--) {
      curElem = selElems[len];
      curElem.returnDefValue();
      inner = curElem.inner;
      words = inner.split(' ');
      wLen = words.length;
      find = false;
      while (wLen--) {
        wordLowerCase = words[wLen].toLocaleLowerCase();
        matches = wordLowerCase.match(regEx);
        if (matches) {
          selElems[len].isMatched = true;
          selElems[len].searchIndex = wordLowerCase.indexOf(matches[0]) +
              Math.pow(10, wLen);
          find = true;
          words[wLen] = addHightLight(value, words[wLen], searchAll);
          matchesElems[id].push(selElems[len]);
        }
      }
      if (!find) {
        hideElement(curElem);
      } else {
        showElement(curElem);
        curElem.innerNode.html(words.join(' '));
      }
    }
    //sort result of find

    if (matchesElems[id].length > 0) {
      var lMatchesElems = matchesElems[id];
      lMatchesElems.sort(sortMatches);
      listParent = $(sElem);
      var mLen = lMatchesElems.length;
      while (mLen--) {
        listParent.prepend(lMatchesElems[mLen].clone);
      }
    }
    EventMgr.trigger('updateScroll', { id: 'cont-' + id });
    ScrollHandler.scrollTo('cont-' + id, 0);
    App.Common.setOptionListPosition('#opt', optListId);
  }

  function sortMatches(a, b) {
    if (b.searchIndex === a.searchIndex) { return 0; }
    if (b.searchIndex < a.searchIndex) { return 1; } else { return -1; }
  }

  function scrollToSelectedElement(sElem, id) {
    var top,
        selectedElem;
    selectedElem = $(sElem)
        .find('.selected:not(".b-myselect__select-li_clone_true")');
    if (selectedElem.length) {
      top = selectedElem[0].offsetTop;
      setTimeout(function() {
        ScrollHandler.scrollTo('cont-' + id, top);
      }, 1);
    }
  }

  //показываем элемент или элементы в селекте
  function showElement(elem) {
    if (!elem) { return; }
    var len = elem.length;
    if (len) {
      while (len--) {
        if (elem[len].clone.className.match('b-myselect__select-li_show_yes')) {
          elem[len].clone.style.display = 'block';
        } else {
          elem[len].clone.style.display = 'none';
        }
      }
    } else {
      if (elem.clone) {
        if (elem.clone.className.match('b-myselect__select-li_show_yes')) {
          elem.clone.style.display = 'block';
        } else {
          elem.clone.style.display = 'none';
        }
      }
    }
  }

  //скрываем элемент или элементы в селекте
  function hideElement(elem) {
    if (!elem) { return; }
    var len = elem.length;
    if (len) {
      while (len--) {
        elem[len].clone.style.display = 'none';
      }
    } else {
      if (elem.clone) {
        elem.clone.style.display = 'none';
      }
    }
  }
  //добавляем выделение
  function addHightLight(rep, value, searchAll) {
    var re, elemValue;
    if (!searchAll) {
      re = rep ? new RegExp('(^' + rep + ')', 'i') : false;
    } else {
      re = rep ? new RegExp('(' + rep + ')', 'i') : false;
    }
    elemValue = value.replace(re, '<span class="highlight">$1</span>');
    return elemValue;
  }


  /**
   * Обрабатываем зависимости при отрисовке формы
   */
  function firstDependSlistHandler(e, data) {
    var tabId = data.tabId;
    $('#cont-' + tabId + ' tr:not(".row-error") .depend.b-myselect ' +
        'input[type="hidden"],' +
        ' #cont-' + tabId + ' .depend.b-radio input[type="hidden"],' +
        ' #cont-' + tabId + ' .depend.b-select-ac input[type="hidden"]').
        each(function() {
          dependSlistHandler.apply(this);
        });
    EventMgr.trigger('updFormHeight', { tabId: tabId });
  }


  function dependSlistHandler() {
    var value = this.value,
        name = this.getAttribute('name'),
        type = this.getAttribute('data-type'),
        tabId = this.getAttribute('data-tabid'),
        elem,
        selectElem, showElem, $dependSelect;
    //hide select options
    $dependSelect = $('#frm-' + tabId + ' div[data-depend="' + name + '"]');
    if ($dependSelect.length > 1) {
      $dependSelect.each(function() {
        var $self = $(this);
        selectElem = $self.find('li.dependelem[data-dependkey="' + value + '"].selected.b-myselect__select-li_show_yes');
        dependSlistCheckSelected(selectElem, $self);
      });
    } else {
      selectElem = $dependSelect.find('li.dependelem[data-dependkey="' + value + '"].selected.b-myselect__select-li_show_yes');
      dependSlistCheckSelected(selectElem, $dependSelect);
    }
    //set first value or prev key
    EventMgr.trigger('updateScroll', { id: 'form-scroll-' + tabId });
  }

  function dependSlistCheckSelected(selectElem, $dependSelect) {
    if (selectElem.length === 0) {
      var id = $dependSelect.attr('id'),
          prevValue = $('#' + id + '-val').val();

      $dependSelect.find('li').removeClass('selected');
      var elem = $dependSelect.find('li.b-myselect__select-li_show_yes[data-val="' + prevValue + '"]')[0] ||
         $dependSelect.find('li.b-myselect__select-li_show_yes')[0];
      if (elem) {
        setSelectedValue.apply(elem);
      } else {
        //console.log('alarm!!! no elem');
      }
    }
  }

  /**
   * Clean cache if slist changed by setvalues
   * @param {object} e
   * @param {object} data
   */
  function cleanSlistCache(e, data) {
    var id = data.id,
        tabId = data.tabId;
    if (CACHE && CACHE[tabId] && CACHE[tabId][id]) {
      delete CACHE[tabId][id];
    }
  }

  function init() {
    //select
    EventMgr.on($content(), selectSelector, 'click', selectListHandler);
    EventMgr.on($content(), selectKeySelector,
        'keydown', selectListKeyDownHandler);
    EventMgr.on($content(), selectItemSelector, 'click', setSelectedValue);
    EventMgr.on($content(), '.sb-input', 'keyup', findElemsInSelect);
    EventMgr.on($content(), dependSlistSelector, 'change', dependSlistHandler);
    EventMgr.bind('appendForm,appendReport,appendedFilter,forceDepend',
        firstDependSlistHandler);
    EventMgr.bind('cleanSlistCache', cleanSlistCache);
  }

  var api = {
    init: init
  };

  return api;

} (window, $, EventMgr, App);