diff --git a/templates/client/accounts/feed.html b/templates/client/accounts/feed.html index b4974111..4237fb73 100644 --- a/templates/client/accounts/feed.html +++ b/templates/client/accounts/feed.html @@ -28,7 +28,7 @@
~~text~~
- x + x
@@ -41,7 +41,7 @@
~~text~~
- x + x
@@ -106,7 +106,7 @@ filterInputId: 'filter-place-filter-input', modalTrigger: 'filter-place-modal-trigger', selectedItemsContainer: 'filter-csb-selected-items', - clearAllButtonClass: 'clear-all-button', + clearAllButtonClass: 'modal-clear', applyBtnClass: 'modal-approve', tagsBoxId: 'filter-places-tags', deleteTagClass: 'csbs-del', @@ -129,7 +129,7 @@ subjectTriggerWrapId: 'filter-subj-checks', //switched by default defaultOn: ['f-s-exhibition-check', 'f-s-conference-check'], - clearAllButtonClass: 'clear-all-button', + clearAllButtonClass: 'modal-clear', applyBtnClass: 'modal-approve', tagsBoxId: 'filter-subject-tags', deleteTagClass: 'csbs-del', diff --git a/templates/client/includes/catalog_search.html b/templates/client/includes/catalog_search.html index 0d9be6da..68302b11 100644 --- a/templates/client/includes/catalog_search.html +++ b/templates/client/includes/catalog_search.html @@ -1,7 +1,7 @@ {% load static %} {% load i18n %} -
+
- +
diff --git a/templates/client/popups/place.html b/templates/client/popups/place.html index baf50fba..2b3ab4d4 100644 --- a/templates/client/popups/place.html +++ b/templates/client/popups/place.html @@ -65,7 +65,6 @@
- {% trans 'Сбросить выбранное' %}
{% trans 'Быстрый выбор' %}:
- {% trans 'Уточнить тему' %} + + + {% trans 'Уточнить тему' %} {% if hasDate %}{% trans 'Уточнить дату' %}{% endif %}
diff --git a/templates/client/popups/theme.html b/templates/client/popups/theme.html index 2a4a7a4d..452707cc 100644 --- a/templates/client/popups/theme.html +++ b/templates/client/popups/theme.html @@ -68,15 +68,14 @@ -
- {% trans 'Сбросить выбранное' %} -
- {% trans 'Уточнить географию' %} + + + {% trans 'Уточнить географию' %} {% if hasDate %}{% trans 'Уточнить дату' %}{% endif %}
diff --git a/templates/client/static_client/css/main.css b/templates/client/static_client/css/main.css index 958d5873..4b06f2b7 100644 --- a/templates/client/static_client/css/main.css +++ b/templates/client/static_client/css/main.css @@ -171,12 +171,12 @@ body { height: 100%; background: #f8f8f6; color: #464646; - font-family: Arial, sans-serif; + font-family: Arial,'Helvetica Neue', sans-serif; font-weight: normal; font-style: normal; font-size: 13px; line-height: 18px; - /*-webkit-font-smoothing: antialiased;*/ + -webkit-font-smoothing: antialiased; } body { @@ -1902,298 +1902,305 @@ button.icon-save:before { # форма поиска \**************************/ -.in-search-form { - position: relative; - /*display: none;*/ - font-family: 'dindisplay_pro', Arial, sans-serif; - font-weight: normal; - font-size: 14px; - line-height: 18px; - color: #fff; - background: #ff6600 url(../img/search-bg.jpg) 100% 100% no-repeat; - height: 150px; - margin: 0 0 15px -40px; - padding: 30px 0 5px 40px; - z-index: 3; - border-radius: 4px; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.modals .popup-window{ - display: none; -} - -.search-form aside .s-title { - font-size: 25px; - line-height: 25px; - text-transform: uppercase; - white-space: nowrap; - margin-right: -20px; -} - -.in-search-form .s-title { - font-size: 25px; - line-height: 25px; - text-transform: uppercase; - margin-bottom: 15px; -} + .in-search-form { + position: relative; + /*display: none;*/ + font-family: 'dindisplay_pro', Arial, sans-serif; + font-weight: normal; + font-size: 14px; + line-height: 18px; + color: #fff; + background: #ff6600 url(../img/search-bg.jpg) 100% 100% no-repeat; + height: 150px; + margin: 0 0 15px -40px; + padding: 30px 0 5px 40px; + z-index: 3; + border-radius: 4px; + -moz-box-sizing: border-box; + box-sizing: border-box; + } -.search-form .mcl { - padding-right: 50px; -} + .modals .popup-window{ + display: none; + } -.search-form-wrap { - display: table; - width: 100%; - border-collapse: collapse; -} + .search-form aside .s-title { + font-size: 25px; + line-height: 25px; + text-transform: uppercase; + white-space: nowrap; + margin-right: -20px; + } -.search-form-wrap .search-line { - display: table-row; -} + .in-search-form .s-title { + font-size: 25px; + line-height: 25px; + text-transform: uppercase; + margin-bottom: 15px; + } -.search-form-wrap .search-line .sf-field-wrap { - display: table-cell; - vertical-align: middle; - padding: 0 10px 8px 0; - color: #ffd9bf; - line-height: 15px; -} + .search-form .mcl { + padding-right: 50px; + } -.search-form-wrap .search-line .sf-field-wrap:first-child { - width: 48%; -} + .search-form-wrap { + display: table; + width: 100%; + border-collapse: collapse; + } -.search-form-wrap .search-line .sf-field-wrap + .sf-field-wrap { - width: 32%; -} + .search-form-wrap .search-line { + display: table-row; + } -.search-form-wrap .search-line .sf-field-wrap + .sf-field-wrap + .sf-field-wrap { - width: 20%; -} + .search-form-wrap .search-line .sf-field-wrap { + display: table-cell; + vertical-align: middle; + padding: 0 10px 8px 0; + color: #ffd9bf; + line-height: 15px; + } -.search-line.sl-options a { - display: inline-block; - color: #fff; - text-decoration: none; - border-bottom: 1px dashed; - line-height: 13px; -} + .search-form-wrap .search-line .sf-field-wrap:first-child { + width: 48%; + } -.search-line.sl-options a:hover { - border-bottom: none; -} + .search-form-wrap .search-line .sf-field-wrap + .sf-field-wrap { + width: 32%; + } -.search-line.sl-options a.sf-clear { - position: relative; - display: inline-block; - vertical-align: middle; - border-bottom: none; - width: 16px; - height: 0; - padding-top: 24px; - margin: -5px 0 -5px 2px; - overflow: hidden; -} + .search-form-wrap .search-line .sf-field-wrap + .sf-field-wrap + .sf-field-wrap { + width: 20%; + } -.search-line.sl-options a.sf-clear:before { - content: ''; - display: block; - width: 6px; - height: 7px; - background: url(../img/sprites.png) -135px -25px no-repeat; - position: absolute; - left: 50%; - top: 50%; - margin: -3px 0 0 -3px; -} + .search-line.sl-options a { + display: inline-block; + color: #fff; + text-decoration: none; + border-bottom: 1px dashed; + line-height: 13px; + } -.sf-field { - position: relative; - display: table; - width: 100%; - height: 40px; - border-collapse: collapse; - background: #fff; - color: #aaa; - box-shadow: inset 0 1px 0 #d9d9d9, 0 -1px 0 rgba(0, 0, 0, .2); - z-index: 1; -} + .search-line.sl-options a:hover { + border-bottom: none; + } -.sf-field-wrap:first-child .sf-field { - border-radius: 4px 0 0 4px; -} + .search-line.sl-options a.sf-clear { + position: relative; + display: inline-block; + vertical-align: middle; + border-bottom: none; + width: 16px; + height: 0; + padding-top: 24px; + margin: -5px 0 -5px 2px; + overflow: hidden; + } -.sf-field > * { - display: table-cell; - vertical-align: middle; -} + .search-line.sl-options a.sf-clear:before { + content: ''; + display: block; + width: 6px; + height: 7px; + background: url(../img/sprites.png) -135px -25px no-repeat; + position: absolute; + left: 50%; + top: 50%; + margin: -3px 0 0 -3px; + } -.sf-field label { - font-size: 16px; - line-height: 20px; - font-weight: normal; - padding: 10px 5px 10px 20px; - white-space: nowrap; -} + .sf-field { + position: relative; + display: table; + width: 100%; + height: 40px; + border-collapse: collapse; + background: #fff; + color: #aaa; + box-shadow: inset 0 1px 0 #d9d9d9, 0 -1px 0 rgba(0, 0, 0, .2); + z-index: 1; + } -.sf-field .input-text { - width: 100%; - height: 100%; -} + .sf-field-wrap:first-child .sf-field { + border-radius: 4px 0 0 4px; + } -.sf-field .input-text input[type="text"] { - display: block; - width: 100%; - height: 100%; - background: none; - border: none; - outline: none; - padding: 10px 10px 10px 0; - font-family: 'dindisplay_pro', Arial, sans-serif; - font-weight: normal; - font-size: 16px; - line-height: 20px; - -moz-box-sizing: border-box; - box-sizing: border-box; -} + .sf-field > * { + display: table-cell; + vertical-align: middle; + } -.search-form button, -.in-search-form button{ - display: inline-block; - vertical-align: top; - height: 40px; - border: 1px solid #fff; - /*background: none;*/ - outline: none; - color: #fff; - font-family: 'dindisplay_pro', Arial, sans-serif; - font-weight: bold; - font-size: 15px; - line-height: 41px; - text-transform: uppercase; - padding: 0 25px; - border-radius: 0 4px 4px 0; - -moz-box-sizing: border-box; - box-sizing: border-box; - box-shadow: 0 1px 0 rgba(0, 0, 0, .2), inset 0 1px 0 rgba(0, 0, 0, .2); - -webkit-filter: none; - filter: none; -} -.pwf-buttons-line button{ - border-radius: 4px; -} + .sf-field label { + font-size: 16px; + line-height: 20px; + font-weight: normal; + padding: 10px 5px 10px 20px; + white-space: nowrap; + } -.search-form button:before, -.in-search-form button:before { - content: ' '; - display: inline-block; - vertical-align: middle; - width: 15px; - height: 14px; - background: url(../img/sprites.png) -98px 0 no-repeat; - margin: -2px 5px 0 -1px; -} + .sf-field .input-text { + width: 100%; + height: 100%; + } -.search-form button:hover, -.in-search-form button:hover { - position: relative; - top: -1px; - /*background: none;*/ -} + .sf-field .input-text input[type="text"] { + display: block; + width: 100%; + height: 100%; + background: none; + border: none; + outline: none; + padding: 10px 10px 10px 0; + font-family: 'dindisplay_pro', Arial, sans-serif; + font-weight: normal; + font-size: 16px; + line-height: 20px; + -moz-box-sizing: border-box; + box-sizing: border-box; + } -.sf-autocomplete { - position: relative; - z-index: 3048; - height: 40px; - display: none; -} -.sf-autocomplete.show { - display: block; -} + .search-form button.search_submit, + .search-form button.modal-approve, + .in-search-form button.search_submit, + .in-search-form button.modal-approve{ + display: inline-block; + vertical-align: top; + height: 40px; + border: 1px solid #fff; + /*background: none;*/ + outline: none; + color: #fff; + font-family: 'dindisplay_pro', Arial, sans-serif; + font-weight: bold; + font-size: 15px; + line-height: 41px; + text-transform: uppercase; + padding: 0 25px; + border-radius: 0 4px 4px 0; + -moz-box-sizing: border-box; + box-sizing: border-box; + box-shadow: 0 1px 0 rgba(0, 0, 0, .2), inset 0 1px 0 rgba(0, 0, 0, .2); + -webkit-filter: none; + filter: none; + } + button.modal-approve{ + border-radius: 4px !important; + } -.sf-autocomplete .sfa-wrap { - position: absolute; - left: 0; - width: 100%; - top: 0; - background: #fff; - padding: 20px 20px 20px 20px; - overflow: hidden; - -moz-box-sizing: border-box; - box-sizing: border-box; - border-radius: 4px; - box-shadow: 0 0 0 3px rgba(0, 0, 0, .2); - visibility: hidden; - background: #ffffff; /* Old browsers */ /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(10%,#ffffff), color-stop(100%,#efefef)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #ffffff 10%,#efefef 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #ffffff 10%,#efefef 100%); /* Opera 11.10+ */ /* IE10+ */ - background: -webkit-linear-gradient(top, #ffffff 10%, #efefef 100%); - background: -o-linear-gradient(top, #ffffff 10%, #efefef 100%); - background: linear-gradient(to bottom, #ffffff 10%,#efefef 100%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#efefef',GradientType=0 ); /* IE6-9 */ + .search-form button.search_submit:before, + .search-form button.modal-approve:before, + .in-search-form button.search_submit:before , + .in-search-form button.modal-approve:before { + content: ' '; + display: inline-block; + vertical-align: middle; + width: 15px; + height: 14px; + background: url(../img/sprites.png) -98px 0 no-repeat; + margin: -2px 5px 0 -1px; + } -} + .search-form button:hover, + .in-search-form button:hover { + position: relative; + top: -1px; + /*background: none;*/ + } -.sf-autocomplete .sfa-wrap { - border-radius: 4px 0 4px 4px; -} + .sf-autocomplete { + position: relative; + z-index: 3048; + height: 40px; + display: none; + } + .sf-autocomplete.show { + display: block; + } -.sf-autocomplete .sfa-wrap.show { - visibility: visible; -} + .sf-autocomplete .sfa-wrap { + position: absolute; + left: 0; + width: 100%; + top: 0; + background: #fff; + padding: 20px 20px 20px 20px; + overflow: hidden; + -moz-box-sizing: border-box; + box-sizing: border-box; + border-radius: 4px; + box-shadow: 0 0 0 3px rgba(0, 0, 0, .2); + visibility: hidden; + background: #ffffff; /* Old browsers */ /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(10%,#ffffff), color-stop(100%,#efefef)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #ffffff 10%,#efefef 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #ffffff 10%,#efefef 100%); /* Opera 11.10+ */ /* IE10+ */ + background: -webkit-linear-gradient(top, #ffffff 10%, #efefef 100%); + background: -o-linear-gradient(top, #ffffff 10%, #efefef 100%); + background: linear-gradient(to bottom, #ffffff 10%,#efefef 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#efefef',GradientType=0 ); /* IE6-9 */ -.ui-autocomplete { - position: relative; - width: 100%; - max-height: 265px; - overflow-y: auto; - overflow-x: hidden; - left: 0 !important; - top: 0 !important; - padding: 5px 10px 0 0; - border-top: 1px dotted #ccc; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.ui-autocomplete-category { - font-size: 15px; - line-height: 17px; - color: #ff6600; - padding: 8px 10px 0 0; -} + } -.ui-menu .ui-menu-item { - padding: 0 10px 0 5px; - margin-top: 2px; -} + .sf-autocomplete .sfa-wrap { + border-radius: 4px 0 4px 4px; + } -.ui-menu .ui-menu-item a { - color: #464646; - font-size: 15px; - line-height: 15px; - border: none; - padding: 2px 5px; - cursor: pointer; -} + .sf-autocomplete .sfa-wrap.show { + visibility: visible; + } -.ui-menu .ui-menu-item a.ui-state-focus, -.ui-menu .ui-menu-item a.ui-state-active { - color: #ff6600; - margin: 0; -} + .ui-autocomplete { + position: relative; + width: 100%; + max-height: 265px; + overflow-y: auto; + overflow-x: hidden; + left: 0 !important; + top: 0 !important; + padding: 5px 10px 0 0; + border-top: 1px dotted #ccc; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .ui-autocomplete-category { + font-size: 15px; + line-height: 17px; + color: #ff6600; + padding: 8px 10px 0 0; + } -.ui-menu .ui-menu-item a i { - font-style: normal; - color: #a2a2a2; -} + .ui-menu .ui-menu-item { + padding: 0 10px 0 5px; + margin-top: 2px; + } + .ui-menu .ui-menu-item a { + color: #464646; + font-size: 15px; + line-height: 15px; + border: none; + padding: 2px 5px; + cursor: pointer; + } -.mp-catalog { + .ui-menu .ui-menu-item a.ui-state-focus, + .ui-menu .ui-menu-item a.ui-state-active { + color: #ff6600; + margin: 0; + } -} + .ui-menu .ui-menu-item a i { + font-style: normal; + color: #a2a2a2; + } + /* # clear all button*/ + .in-search-form .modal-clear, + .search-form .modal-clear{ + height: 40px; + border: 1px solid #fff; + padding: 0 25px; + box-shadow: 0 1px 0 rgba(0, 0, 0, .2), inset 0 1px 0 rgba(0, 0, 0, .2); + } /* end of search block*/ @@ -4025,14 +4032,19 @@ form.s-message { margin-bottom: 15px; } -.c-select-box .csb-menu .places-list > ul li.active ul { +.c-select-box .csb-menu .places-list .active > .sublist { + display: block; +} +.c-select-box .csb-menu .places-list .sublist { + display: none; +} +.c-select-box .csb-menu .places-list .sublist.parent { display: block; } .c-select-box .csb-menu .q-sel { width: 190px; float: right; - margin-top: 1em; } @@ -11320,6 +11332,12 @@ hr + .rq-note { .pw-subj{ min-height: 480px; } +.pw-subj .csb-menu .level .sublist{ + display: none; +} +.pw-subj .csb-menu .level.active .sublist{ + display: block; +} .pw-subj .csb-menu .level1{ display: none; } @@ -12013,6 +12031,21 @@ hr + .rq-note { .mt-0{ margin-top: 0; } + button.gray{ + background: #dbdbdb; /* Old browsers */ + background: -moz-linear-gradient(top, #dbdbdb 0%, #bdbdbd 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#dbdbdb), color-stop(100%,#bdbdbd)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #dbdbdb 0%,#bdbdbd 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #dbdbdb 0%,#bdbdbd 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #dbdbdb 0%,#bdbdbd 100%); /* IE10+ */ + background: linear-gradient(to bottom, #dbdbdb 0%,#bdbdbd 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#dbdbdb', endColorstr='#bdbdbd',GradientType=0 ); /* IE6-9 */ + + } + button.gray:hover{ + background: #dbdbdb; /* Old browsers */ + + } @@ -12020,16 +12053,16 @@ hr + .rq-note { # Модальное окно выбора тематики \******************************/ -.pw-subj .q-sel{ - top: 0; - position: absolute; - right: 0; - margin-top: 1em; + .pw-subj .q-sel{ + top: 0; + position: absolute; + right: 0; + margin-top: 1em; -} -.search_form .scroll-container{ - overflow: hidden; -} + } + .search_form .scroll-container{ + overflow: hidden; + } /******************************\ # Модальное окно общий вид \******************************/ @@ -12246,7 +12279,7 @@ hr + .rq-note { # блок умный поиск catalog_search.html \************************/ - .in-search-form .clear-all-button, .search-form-wrap .clear-all-button{ + .mp-search .clear-all-button, .search-form-wrap .clear-all-button{ display: none; width: 17px; height: 17px; @@ -12255,19 +12288,19 @@ hr + .rq-note { vertical-align: top; margin-top: 2px; } - .in-search-form .clear-all-button.active, .search-form-wrap .clear-all-button.active{ + .mp-search .clear-all-button.active, .search-form-wrap .clear-all-button.active{ display: inline-block; } - .in-search-form .clear-all-button:active, .search-form-wrap .clear-all-button:active{ + .mp-search .clear-all-button:active, .search-form-wrap .clear-all-button:active{ background-position: -385px -89px; } - .in-search-form .pw-period .pwf-field.err input{ + .mp-search .pw-period .pwf-field.err input{ border-width: 2px; border-color: #D80000; } - .in-search-form .ui-menu .ui-menu-item .subj-category{ + .mp-search .ui-menu .ui-menu-item .subj-category{ display: inline-block; color: #a2a2a2; font-size: 15px; @@ -12278,14 +12311,21 @@ hr + .rq-note { text-decoration: none; min-height: 0; font-weight: 400; + white-space: normal; + } + .mp-search .ui-autocomplete{ + width: 533px; + } + .mp-search .ui-menu .ui-menu-item{ + white-space: nowrap; } - .in-search-form .ui-menu .ui-menu-item a{ + .mp-search .ui-menu .ui-menu-item a{ display: inline-block; } - .in-search-form .ui-menu li{ + .mp-search .ui-menu li{ margin-bottom: 4px; } - .in-search-form .ui-menu{ + .mp-search .ui-menu{ line-height: 15px; } diff --git a/templates/client/static_client/js/_modules/block.search.js b/templates/client/static_client/js/_modules/block.search.js index d762c4a4..3762241d 100644 --- a/templates/client/static_client/js/_modules/block.search.js +++ b/templates/client/static_client/js/_modules/block.search.js @@ -257,12 +257,8 @@ if (EXPO.searchBlock){ $sublist = $parent.children('.sublist'); if(!param){ - if($label.hasClass('active')){ - $label.removeClass('active'); - }else{ - $label.addClass('active'); - } if(this.checked){ + $label.addClass('active'); var text = $(this).closest('.level').find('.trigger').first().text(), tplObj = {'text':text,'id':checkboxId}; @@ -307,6 +303,7 @@ if (EXPO.searchBlock){ //!uncheck event }else { + $label.removeClass('active'); self._destroyTag(checkboxId); if(!$selectedItemsWrap.children('.dna-clone').length){ $selectedItemsWrap.removeClass('visible'); @@ -359,7 +356,7 @@ if (EXPO.searchBlock){ } return false; }); - $('.clear', $modal).on('click', function () { + $('.modal-clear', $modal).on('click', function () { self.resetList(); return false; }); @@ -371,6 +368,8 @@ if (EXPO.searchBlock){ // кнопка "очистить параметры" $modalTrigger.siblings('.'+self.opt.clearAllButtonClass).on('click', function () { self.resetList(); + EXPO.searchBlock.exhibitionField.clearValue(); + }); }); }; @@ -702,8 +701,10 @@ if (EXPO.searchBlock){ $('#'+key, self.$selfContainer).prop('checked', false).trigger('change'); dna.destroy(self.itemsSelected[key]); + } } + $('.level.active',self.$modalInst).removeClass('active'); self.$selectedItemsWrap.removeClass('visible'); }, // кнопка применить @@ -789,12 +790,18 @@ if (EXPO.searchBlock){ DOMParentCheckbox = DOMParent.querySelector('.csb-menu-input'); $('.csb-menu-input', $sublist).each(function () { var DOMCheckboxWrap = common.closest(this,'custom-radio-check'); - if(!this.selected){ + if(!this.checked){ if(DOMParentCheckbox.checked){ this.checked = true; common.addClass(DOMCheckboxWrap,'active'); } + }else{ + if(!DOMParentCheckbox.checked){ + + this.checked = false; + common.removeClass(DOMCheckboxWrap,'active'); + } } }); $waiter.hide(); @@ -848,6 +855,8 @@ if (EXPO.searchBlock){ DOMSublistInner = DOMParentRow.querySelector('.'+sublistClass), DOMHighestItem = common.closest(this, highestItemClass), DOMHighestCheckbox = DOMHighestItem.querySelector('.'+checkboxClass), + DOMHighestSublist = DOMHighestItem.querySelector('.'+sublistClass), + selectSublist = function (it) { var DOMParentItem = common.closest(it, itemClass) || this, DOMSublist = DOMParentItem.querySelector('.'+sublistClass); @@ -861,6 +870,7 @@ if (EXPO.searchBlock){ DOMSublist = DOMParentItem.querySelector('.'+sublistClass); $('.'+checkboxClass, DOMSublist).each(function () { unSelectItem(this); + }); }, @@ -895,9 +905,14 @@ if (EXPO.searchBlock){ }, unSelectItem = function (it) { - var itFakeCheckbox = common.closest(it, fakeCheckboxClass); + var itFakeCheckbox = common.closest(it, fakeCheckboxClass), + DOMitem = common.closest(it, itemClass); common.removeClass(itFakeCheckbox, activeClass); it.checked = false; + // if there is children items + if(DOMitem.querySelector('.'+sublistClass) && !common.hasClass(DOMitem,highestItemClass)){ + unSelectSublist(it); + } }, allChildrenSelected = function () { //var DOMselected = DOMSublist.querySelectorAll('.'+checkboxClass+':checked'), @@ -922,7 +937,7 @@ if (EXPO.searchBlock){ } }, - // Функционал добавления тегов: если есть в панели выбранный элемент либо его дочерние то удалить эти эдементы и разместить выбранный; иначе разместить выбранные. + // Функционал добавления тегов: если есть в панели выбранный элемент либо его дочерние то удалить эти эдементы; refreshTags = function (it) { var DOMSublist = common.closest(it,sublistClass); var DOMItem = common.closest(it,itemClass); @@ -957,7 +972,6 @@ if (EXPO.searchBlock){ } allTagsLength = ARRAllTagsIds.length; sublistIdsLength = ARRSublistIds.length; - // добавить текущий тег //если найден дочерний тег то он будет удален, либо текущий тег for(i = 0; i < allTagsLength; i++){ @@ -975,6 +989,13 @@ if (EXPO.searchBlock){ deleteTag(it); } } + // удаление дочерних тегов 2го уровня + if(DOMSublistInner.querySelectorAll('.final-tire')){ + $('.'+fakeCheckboxClass+'.'+activeClass, DOMSublistInner.querySelectorAll('.final-tire')).each(function () { + deleteTag($('.'+checkboxClass,this)[0]); + + }); + } }else{ // удаление дубликатов текущего элемента for(i = 0; i < allTagsLength; i++){ @@ -1011,7 +1032,7 @@ if (EXPO.searchBlock){ } }, createTagList = function (sublist) { - var $selected = $(DOMSublist).children('li').children('.'+fakeCheckboxClass).find('.'+checkboxClass+':checked'); + var $selected = $(sublist).children('li').children('.'+fakeCheckboxClass).find('.'+checkboxClass+':checked'); $selected.each(function () { createTag(this); }); @@ -1034,7 +1055,12 @@ if (EXPO.searchBlock){ if(!self.strictMode){ if(this.checked){ + if($(DOMSublistInner).find('.'+checkboxClass)[0]){ + if(DOMSublistInner && $(DOMSublistInner).find('.'+checkboxClass)[0].value != '~~id~~'){ + refreshTags(this); + } + } //если выбраны все дочерние if(allChildrenSelected()){ selectParent(this); @@ -1056,9 +1082,7 @@ if (EXPO.searchBlock){ if(DOMSublistInner){ selectSublist(this); } - if(DOMSublistInner && $(DOMSublistInner).find('.'+checkboxClass)[0].value != '~~id~~'){ - refreshTags(this); - } + }else{ //Если выбран родитель @@ -1069,10 +1093,12 @@ if (EXPO.searchBlock){ deleteTag(DOMParentCheckbox); createTagList(DOMSublist); if(DOMHighestCheckbox.checked){ + unSelectItem(DOMHighestCheckbox); - refreshTags(DOMHighestCheckbox); deleteTag(DOMHighestCheckbox); + createTagList(DOMHighestSublist); } + }else{ unSelectItem(this); refreshTags(this); @@ -1116,7 +1142,7 @@ if (EXPO.searchBlock){ /** * clear all button behavior */ - $('.clear',$modal).on('click', function () { + $('.modal-clear',$modal).on('click', function () { self.resetList(); return false; }); @@ -1143,6 +1169,7 @@ if (EXPO.searchBlock){ }); $modalTrigger.siblings('.'+self.opt.clearAllButtonClass).on('click', function () { self.resetList(); + EXPO.searchBlock.placesField.clearValue() }); }); @@ -1390,11 +1417,13 @@ if (EXPO.searchBlock){ var self = this; for (var key in self.itemsSelected) { if (self.itemsSelected.hasOwnProperty(key)) { - $('#'+key, self.$selfContainer).prop('checked', false).trigger('change'); + $('#'+key, self.$selfContainer).prop('checked', false).closest('.custom-radio-check').removeClass('active'); dna.destroy(self.itemsSelected[key]); } } + $('.level.active',this.$modal).removeClass('active'); + this._refreshText(); self.selectedWrap.removeClass('visible'); }, /** @@ -1583,6 +1612,21 @@ if (EXPO.searchBlock){ * @public */ applyHandler: function (it) { + }, + _refreshText: function () { + var selectedString, + $modalTrigger = $('#'+this.opt.modalTrigger), + cutLength = 16; + selectedString = getSelectedToString(this.opt.selectedItemsContainer,cutLength); + if(selectedString && selectedString != '~~text~~' && selectedString != '~~text~~...'){ + $modalTrigger.text(selectedString); + $modalTrigger.siblings('.'+this.opt.clearAllButtonClass).addClass('active'); + + }else{ + $modalTrigger.text($modalTrigger.data('default')); + $modalTrigger.siblings('.'+this.opt.clearAllButtonClass).removeClass('active'); + + } } }; @@ -1599,6 +1643,7 @@ if (EXPO.searchBlock){ $modal = $('#'+self.opt.id), $modalTrigger = $('#'+self.opt.modalTrigger), applyBtnClass = self.opt.applyBtnClass, + $activeField, /** * make string from input:text values * @returns {string} @@ -1669,11 +1714,11 @@ if (EXPO.searchBlock){ /** * swap values between date fields */ - if(thatValInt > itValInt && thatValInt != 0 && thatValInt){ + if(itValInt > thatValInt && itId == self.opt.dateFrom){ bfr = document.getElementById(itId).value; document.getElementById(itId).value = document.getElementById(thatId).value; document.getElementById(thatId).value = bfr; - }else if(thatValInt < itValInt && thatValInt != 0 && thatValInt){ + }else if(itValInt < thatValInt && itId == self.opt.dateTo){ bfr = document.getElementById(thatId).value; document.getElementById(thatId).value = document.getElementById(itId).value; document.getElementById(itId).value = bfr; @@ -1685,51 +1730,58 @@ if (EXPO.searchBlock){ this.$dateTo = $dateTo; this.$modalTrigger = $modalTrigger; - $(function () { - $.datepicker.setDefaults($.datepicker.regional["ru"]); - - $dateFrom.datepicker({ - dateFormat: 'dd.mm.yy', - showOn: 'button', - showOtherMonths: true, - constrainInput: true, - onClose: function( selectedDate ) { - $dateTo.datepicker( "option", "minDate", selectedDate ); - } - }).inputmask("99.99.9999",{ - showMaskOnHover:false, - 'oncomplete': function () { - checkInterval(this); - } - }); - $dateTo.datepicker({ - dateFormat: 'dd.mm.yy', - showOn: 'button', - showOtherMonths: true, - constrainInput: true, - onClose: function( selectedDate ) { - $dateFrom.datepicker( "option", "maxDate", selectedDate ); - } - }).inputmask("99.99.9999",{ - showMaskOnHover:false, - 'oncomplete': function () { - checkInterval(this); - } - }); - $('input[type="text"]',$modal).on('change', function () { - var stringToset = inputsTostring(); + $(function () { + $.datepicker.setDefaults($.datepicker.regional["ru"]); + + $dateFrom.datepicker({ + dateFormat: 'dd.mm.yy', + showOn: 'button', + showOtherMonths: true, + constrainInput: true, + onClose: function( selectedDate ) { + $dateTo.datepicker( "option", "minDate", selectedDate ); + } + }).inputmask("99.99.9999",{ + showMaskOnHover:false, + insertMode:false, + 'oncomplete': function () { + $activeField = this; + } + }); + $dateTo.datepicker({ + dateFormat: 'dd.mm.yy', + showOn: 'button', + showOtherMonths: true, + constrainInput: true, + onClose: function( selectedDate ) { + $dateFrom.datepicker( "option", "maxDate", selectedDate ); + } + }).inputmask("99.99.9999",{ + showMaskOnHover:false, + insertMode:false, + 'oncomplete': function () { + $activeField = this; + } + }); + $('input[type="text"]',$modal).on('change', function () { + var stringToset = inputsTostring(); + if (self.validate()){ triggerSetText(stringToset); + } - }); - $('.'+applyBtnClass, $modal).on('click', function () { - self.applyHandler(this); - return false; - }); - $modalTrigger.siblings('.'+self.opt.clearAllButtonClass).on('click', function () { - $(this).removeClass('active'); - self.resetList(); - }); }); + $('.'+applyBtnClass, $modal).on('click', function () { + if($activeField){ + checkInterval($activeField); + } + self.applyHandler(this); + return false; + }); + $modalTrigger.siblings('.'+self.opt.clearAllButtonClass).on('click', function () { + $(this).removeClass('active'); + self.resetList(); + }); + }); }; /** @@ -1998,6 +2050,9 @@ if (EXPO.searchBlock){ */ pullData: function (handler) { + }, + clearValue: function () { + this.$field.val(''); } }; diff --git a/templates/client/static_client/js/_modules/page.events.feed.js b/templates/client/static_client/js/_modules/page.events.feed.js index c62afba8..ec85b645 100644 --- a/templates/client/static_client/js/_modules/page.events.feed.js +++ b/templates/client/static_client/js/_modules/page.events.feed.js @@ -312,12 +312,9 @@ if (EXPO.events.feed) { } return false; }); - $('#'+self.opt.deleteId).on('click',function () { - $('.' + self.opt.deleteTagClass, $modal).trigger('click'); - }); - $('.clear', $modal).on('click', function () { - self.resetList(); - return false; + $('.del-on-page').on('click',function () { + var dataCheckboxId = $(this).attr('data-checkbox-id'); + $('.' + self.opt.deleteTagClass+'[data-checkbox-id="'+dataCheckboxId+'"]', $modal).trigger('click'); }); self._autocompleteInit(); $('.' + applyBtnClass, $modal).on('click', function () { @@ -326,8 +323,10 @@ if (EXPO.events.feed) { }); // кнопка "очистить параметры" - $modalTrigger.siblings('.' + self.opt.clearAllButtonClass).on('click', function () { + $('.'+self.opt.clearAllButtonClass,$modal).on('click', function (e) { + e.preventDefault(); self.resetList(); + return false; }); }); }; @@ -665,14 +664,17 @@ if (EXPO.events.feed) { var self = this; for (var key in self.itemsSelected) { if (self.itemsSelected.hasOwnProperty(key)) { - $('#' + key, self.$selfContainer).prop('checked', false).trigger('change'); + $('#'+key, self.$selfContainer).prop('checked', false).closest('.custom-radio-check').removeClass('active'); dna.destroy(self.itemsSelected[key]); + dna.destroy(self.tagsBoxItems[key]); + } } - $('.sublist', self.$modalInst).addClass('hidden'); - $('.level', self.$modalInst).removeClass('active'); - self.$selectedItemsWrap.removeClass('visible'); + $('.level.active',this.$modal).removeClass('active'); + this._refreshLabel(); + + this.$selectedItemsWrap.removeClass('visible'); }, /** * render label text, if there is no selected element then text will be default @@ -689,6 +691,7 @@ if (EXPO.events.feed) { }, // кнопка применить applyHandler: function (it) { + EXPO.events.feed.modalWindow.close(); } @@ -827,39 +830,42 @@ if (EXPO.events.feed) { DOMParentRow = com.closest(this, itemClass), - DOMParentItem = com.hasClass(DOMParentRow, highestItemClass) == false ? com.closest(DOMParentRow.parentNode, itemClass) : DOMParentRow, - DOMParentCheckbox = DOMParentItem.querySelector('.' + checkboxClass), - DOMSublist = DOMParentItem.querySelector('.' + sublistClass), - DOMSublistInner = DOMParentRow.querySelector('.' + sublistClass), + DOMParentItem = com.hasClass(DOMParentRow, highestItemClass) == false?com.closest(DOMParentRow.parentNode, itemClass):DOMParentRow, + DOMParentCheckbox = DOMParentItem.querySelector('.'+checkboxClass), + DOMSublist = DOMParentItem.querySelector('.'+sublistClass), + DOMSublistInner = DOMParentRow.querySelector('.'+sublistClass), DOMHighestItem = com.closest(this, highestItemClass), - DOMHighestCheckbox = DOMHighestItem.querySelector('.' + checkboxClass), + DOMHighestCheckbox = DOMHighestItem.querySelector('.'+checkboxClass), + DOMHighestSublist = DOMHighestItem.querySelector('.'+sublistClass), + selectSublist = function (it) { var DOMParentItem = com.closest(it, itemClass) || this, - DOMSublist = DOMParentItem.querySelector('.' + sublistClass); - $('.' + checkboxClass, DOMSublist).each(function () { + DOMSublist = DOMParentItem.querySelector('.'+sublistClass); + $('.'+checkboxClass, DOMSublist).each(function () { selectItem(this); }); }, unSelectSublist = function (it) { var DOMParentItem = com.closest(it, itemClass) || this, - DOMSublist = DOMParentItem.querySelector('.' + sublistClass); - $('.' + checkboxClass, DOMSublist).each(function () { + DOMSublist = DOMParentItem.querySelector('.'+sublistClass); + $('.'+checkboxClass, DOMSublist).each(function () { unSelectItem(this); + }); }, selectParent = function (it) { var DOMParentRow = com.closest(it, itemClass), DOMParentItem; - if (com.hasClass(DOMParentRow, 'level1')) { + if(com.hasClass(DOMParentRow,'level1')){ DOMParentItem = DOMParentRow; - } else { + }else{ DOMParentItem = com.closest(DOMParentRow.parentNode, itemClass); } - com.addClass(DOMParentItem.querySelector('.' + fakeCheckboxClass), activeClass); - DOMParentItem.querySelector('.' + checkboxClass).checked = true; + com.addClass(DOMParentItem.querySelector('.'+fakeCheckboxClass), activeClass); + DOMParentItem.querySelector('.'+checkboxClass).checked = true; //it.selected = true; @@ -868,8 +874,8 @@ if (EXPO.events.feed) { var DOMParentRow = com.closest(it, itemClass), DOMParentItem = com.closest(DOMParentRow.parentNode, itemClass) || DOMParentRow; - com.removeClass(DOMParentItem.querySelector('.' + fakeCheckboxClass), activeClass); - DOMParentItem.querySelector('.' + checkboxClass).checked = false; + com.removeClass(DOMParentItem.querySelector('.'+fakeCheckboxClass), activeClass); + DOMParentItem.querySelector('.'+checkboxClass).checked = false; //it.checked = false; }, @@ -880,97 +886,110 @@ if (EXPO.events.feed) { }, unSelectItem = function (it) { - var itFakeCheckbox = com.closest(it, fakeCheckboxClass); + var itFakeCheckbox = com.closest(it, fakeCheckboxClass), + DOMitem = com.closest(it, itemClass); com.removeClass(itFakeCheckbox, activeClass); it.checked = false; + // if there is children items + if(DOMitem.querySelector('.'+sublistClass) && !com.hasClass(DOMitem,highestItemClass)){ + unSelectSublist(it); + } }, allChildrenSelected = function () { //var DOMselected = DOMSublist.querySelectorAll('.'+checkboxClass+':checked'), - var DOMSublistParent = com.closest(DOMSublist, sublistClass), - $selected = $(DOMSublist).children('li').children('.' + fakeCheckboxClass).find('.' + checkboxClass + ':checked'), + var DOMSublistParent = com.closest(DOMSublist,sublistClass), + $selected = $(DOMSublist).children('li').children('.'+fakeCheckboxClass).find('.'+checkboxClass+':checked'), selectedCount = $selected.length, //allCount = DOMSublist.querySelectorAll('.'+checkboxClass).length; - allCount = $(DOMSublist).children('li').children('.' + fakeCheckboxClass).find('.' + checkboxClass).length; + allCount = $(DOMSublist).children('li').children('.'+fakeCheckboxClass).find('.'+checkboxClass).length; - if (allCount == selectedCount && selectedCount != 0) { + if(allCount == selectedCount && selectedCount != 0){ return true; - } else { + } else{ return false; } }, parentSelected = function () { - var parentCheckbox = DOMParentItem.querySelector('.' + checkboxClass); - if (parentCheckbox.checked) { + var parentCheckbox = DOMParentItem.querySelector('.'+checkboxClass); + if(parentCheckbox.checked){ return true; - } else { + }else{ return false; } }, - // Функционал добавления тегов: если есть в панели выбранный элемент либо его дочерние то удалить эти эдементы и разместить выбранный; иначе разместить выбранные. + // Функционал добавления тегов: если есть в панели выбранный элемент либо его дочерние то удалить эти эдементы; refreshTags = function (it) { - var DOMSublist = com.closest(it, sublistClass); - var DOMItem = com.closest(it, itemClass); - var DOMSublistInner = DOMItem.querySelector('.' + sublistClass); - var DOMAllTags = DOMTagsWrapper.querySelectorAll('.' + tagClass); + var DOMSublist = com.closest(it,sublistClass); + var DOMItem = com.closest(it,itemClass); + var DOMSublistInner = DOMItem.querySelector('.'+sublistClass); + var DOMAllTags = DOMTagsWrapper.querySelectorAll('.'+tagClass); var ARRsublist; - var ARRsublistChildren = DOMSublist.querySelector('.' + sublistClass) ? $('.' + checkboxClass + ':checked', DOMSublist.querySelector('.' + sublistClass)) : null; - var ARRsublistChildrenLength = ARRsublistChildren ? ARRsublistChildren.length : null; + var ARRsublistChildren = DOMSublist.querySelector('.'+sublistClass)?$('.'+checkboxClass+':checked',DOMSublist.querySelector('.'+sublistClass)):null; + var ARRsublistChildrenLength = ARRsublistChildren?ARRsublistChildren.length:null; var ARRSublistIds = []; var ARRAllTagsIds = []; var allTagsLength = 0; var sublistIdsLength = 0; var itId = it.getAttribute('id'); - var i = 0, j = 0, t = 0, tmp, k = 0; + var i = 0, j= 0, t= 0, tmp, k = 0; var tagId; - var tagText = DOMParentRow.querySelector('.' + triggerClass).innerHTML; + var tagText = DOMParentRow.querySelector('.'+triggerClass).innerHTML; // если есть дочерние элементы - if (DOMSublistInner) { - ARRsublist = $(DOMSublistInner).children('li').children('.' + fakeCheckboxClass).find('.' + checkboxClass + ':checked') + if(DOMSublistInner){ + ARRsublist = $(DOMSublistInner).children('li').children('.'+fakeCheckboxClass).find('.'+checkboxClass+':checked') //получаем массив id жлементовЮ для которых есть тег - for (k; k < ARRsublist.length; k++) { + for(k; k < ARRsublist.length; k++){ tmp = ARRsublist[k].getAttribute('id'); ARRSublistIds.push(tmp); } //очистк - for (t; t < DOMAllTags.length; t++) { - tmp = DOMAllTags[t].querySelector('.' + tagButtonClass).getAttribute(tagIdAttribute); - if (tmp != '~~id~~') { + for(t; t see jquery.inputmask.extensions.js - onKeyUp: $.noop, //override to implement autocomplete on certain keys for example - onKeyDown: $.noop, //override to implement autocomplete on certain keys for example - showMaskOnHover: true, //show the mask-placeholder when hovering the empty input - //numeric basic properties - numericInput: false, //numericInput input direction style (input shifts to the left while holding the caret position) - radixPoint: ".", // | "," - //numeric basic properties - definitions: { - '9': { - validator: "[0-9]", - cardinality: 1 - }, - 'a': { - validator: "[A-Za-z\u0410-\u044F\u0401\u0451]", - cardinality: 1 - }, - '*': { - validator: "[A-Za-z\u0410-\u044F\u0401\u04510-9]", - cardinality: 1 - } - }, - keyCode: { - ALT: 18, - BACKSPACE: 8, - CAPS_LOCK: 20, - COMMA: 188, - COMMAND: 91, - COMMAND_LEFT: 91, - COMMAND_RIGHT: 93, - CONTROL: 17, - DELETE: 46, - DOWN: 40, - END: 35, - ENTER: 13, - ESCAPE: 27, - HOME: 36, - INSERT: 45, - LEFT: 37, - MENU: 93, - NUMPAD_ADD: 107, - NUMPAD_DECIMAL: 110, - NUMPAD_DIVIDE: 111, - NUMPAD_ENTER: 108, - NUMPAD_MULTIPLY: 106, - NUMPAD_SUBTRACT: 109, - PAGE_DOWN: 34, - PAGE_UP: 33, - PERIOD: 190, - RIGHT: 39, - SHIFT: 16, - SPACE: 32, - TAB: 9, - UP: 38, - WINDOWS: 91 - }, - ignorables: [8, 9, 13, 16, 17, 18, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 46, 91, 93, 108] - }, - val: $.fn.val //store the original jquery val function - }; - - $.fn.inputmask = function (fn, options) { - var opts = $.extend(true, {}, $.inputmask.defaults, options); - var pasteEvent = isInputEventSupported('paste') ? 'paste' : 'input'; - - var iphone = navigator.userAgent.match(/iphone/i) != null; - var android = navigator.userAgent.match(/android.*mobile safari.*/i) != null; - if (android) { - var browser = navigator.userAgent.match(/mobile safari.*/i); - var version = parseInt(new RegExp(/[0-9]+/).exec(browser)); - android = version <= 533; - } - var caretposCorrection = null; - - if (typeof fn == "string") { - switch (fn) { - case "mask": - //init buffer - var _buffer = getMaskTemplate(); - var tests = getTestingChain(); - - return this.each(function () { - mask(this); - }); - break; - case "unmaskedvalue": - var tests = this.data('inputmask')['tests']; - var _buffer = this.data('inputmask')['_buffer']; - opts.greedy = this.data('inputmask')['greedy']; - opts.repeat = this.data('inputmask')['repeat']; - opts.definitions = this.data('inputmask')['definitions']; - return unmaskedvalue(this); - break; - case "remove": - var tests, _buffer; - return this.each(function () { - var $input = $(this), input = this; - setTimeout(function () { - if ($input.data('inputmask')) { - tests = $input.data('inputmask')['tests']; - _buffer = $input.data('inputmask')['_buffer']; - opts.greedy = $input.data('inputmask')['greedy']; - opts.repeat = $input.data('inputmask')['repeat']; - opts.definitions = $input.data('inputmask')['definitions']; - //writeout the unmaskedvalue - input._valueSet(unmaskedvalue($input, true)); - //clear data - $input.removeData('inputmask'); - //unbind all events - $input.unbind(".inputmask"); - $input.removeClass('focus.inputmask'); - //restore the value property - var valueProperty; - if (Object.getOwnPropertyDescriptor) - valueProperty = Object.getOwnPropertyDescriptor(input, "value"); - if (valueProperty && valueProperty.get) { - if (input._valueGet) { - Object.defineProperty(input, "value", { - get: input._valueGet, - set: input._valueSet - }); - } - } else if (document.__lookupGetter__ && input.__lookupGetter__("value")) { - if (input._valueGet) { - input.__defineGetter__("value", input._valueGet); - input.__defineSetter__("value", input._valueSet); - } - } - delete input._valueGet; - delete input._valueSet; - } - }, 0); - }); - break; - case "getemptymask": //return the default (empty) mask value, usefull for setting the default value in validation - if (this.data('inputmask')) - return this.data('inputmask')['_buffer'].join(''); - else return ""; - case "hasMaskedValue": //check wheter the returned value is masked or not; currently only works reliable when using jquery.val fn to retrieve the value - return this.data('inputmask') ? !this.data('inputmask')['autoUnmask'] : false; - default: - //check if the fn is an alias - if (!resolveAlias(fn)) { - //maybe fn is a mask so we try - //set mask - opts.mask = fn; - } - //init buffer - var _buffer = getMaskTemplate(); - var tests = getTestingChain(); - - return this.each(function () { - mask(this); - }); - - break; - } - } - if (typeof fn == "object") { - opts = $.extend(true, {}, $.inputmask.defaults, fn); - resolveAlias(opts.alias); //resolve aliases - //init buffer - var _buffer = getMaskTemplate(); - var tests = getTestingChain(); - - return this.each(function () { - mask(this); - }); + if ($.fn.inputmask === undefined) { + + //helper functions + function isInputEventSupported(eventName) { + var el = document.createElement('input'), + evName = 'on' + eventName, + isSupported = (evName in el); + if (!isSupported) { + el.setAttribute(evName, 'return;'); + isSupported = typeof el[evName] == 'function'; } - - //helper functions - function isInputEventSupported(eventName) { - var el = document.createElement('input'), - eventName = 'on' + eventName, - isSupported = (eventName in el); - if (!isSupported) { - el.setAttribute(eventName, 'return;'); - isSupported = typeof el[eventName] == 'function'; - } + el = null; + return isSupported; + } + + function isInputTypeSupported(inputType) { + var isSupported = inputType == "text" || inputType == "tel"; + if (!isSupported) { + var el = document.createElement('input'); + el.setAttribute("type", inputType); + isSupported = el.type === "text"; //apply mask only if the type is not natively supported el = null; - return isSupported; } - - function resolveAlias(aliasStr) { - var aliasDefinition = opts.aliases[aliasStr]; - if (aliasDefinition) { - if (aliasDefinition.alias) resolveAlias(aliasDefinition.alias); //alias is another alias - $.extend(true, opts, aliasDefinition); //merge alias definition in the options - $.extend(true, opts, options); //reapply extra given options - return true; - } - return false; + return isSupported; + } + + function resolveAlias(aliasStr, options, opts) { + var aliasDefinition = opts.aliases[aliasStr]; + if (aliasDefinition) { + if (aliasDefinition.alias) resolveAlias(aliasDefinition.alias, undefined, opts); //alias is another alias + $.extend(true, opts, aliasDefinition); //merge alias definition in the options + $.extend(true, opts, options); //reapply extra given options + return true; } + return false; + } + + function generateMaskSet(opts) { + var ms = undefined; + + function analyseMask(mask) { + var tokenizer = /(?:[?*+]|\{[0-9\+\*]+(?:,[0-9\+\*]*)?\})\??|[^.?*+^${[]()|\\]+|./g, + escaped = false; + + function maskToken(isGroup, isOptional, isQuantifier, isAlternator) { + this.matches = []; + this.isGroup = isGroup || false; + this.isOptional = isOptional || false; + this.isQuantifier = isQuantifier || false; + this.isAlternator = isAlternator || false; + this.quantifier = { min: 1, max: 1 }; + }; - function getMaskTemplate() { - var escaped = false, outCount = 0; - if (opts.mask.length == 1 && opts.greedy == false) { - opts.placeholder = ""; - } //hide placeholder with single non-greedy mask - var singleMask = $.map(opts.mask.split(""), function (element, index) { - var outElem = []; - if (element == opts.escapeChar) { - escaped = true; + //test definition => {fn: RegExp/function, cardinality: int, optionality: bool, newBlockMarker: bool, casing: null/upper/lower, def: definitionSymbol, placeholder: placeholder, mask: real maskDefinition} + function insertTestDefinition(mtoken, element, position) { + var maskdef = opts.definitions[element]; + var newBlockMarker = mtoken.matches.length == 0; + position = position != undefined ? position : mtoken.matches.length; + if (maskdef && !escaped) { + maskdef["placeholder"] = $.isFunction(maskdef["placeholder"]) ? maskdef["placeholder"].call(this, opts) : maskdef["placeholder"]; + var prevalidators = maskdef["prevalidator"], prevalidatorsL = prevalidators ? prevalidators.length : 0; + for (var i = 1; i < maskdef.cardinality; i++) { + var prevalidator = prevalidatorsL >= i ? prevalidators[i - 1] : [], validator = prevalidator["validator"], cardinality = prevalidator["cardinality"]; + mtoken.matches.splice(position++, 0, { fn: validator ? typeof validator == 'string' ? new RegExp(validator) : new function () { this.test = validator; } : new RegExp("."), cardinality: cardinality ? cardinality : 1, optionality: mtoken.isOptional, newBlockMarker: newBlockMarker, casing: maskdef["casing"], def: maskdef["definitionSymbol"] || element, placeholder: maskdef["placeholder"], mask: element }); + } + mtoken.matches.splice(position++, 0, { fn: maskdef.validator ? typeof maskdef.validator == 'string' ? new RegExp(maskdef.validator) : new function () { this.test = maskdef.validator; } : new RegExp("."), cardinality: maskdef.cardinality, optionality: mtoken.isOptional, newBlockMarker: newBlockMarker, casing: maskdef["casing"], def: maskdef["definitionSymbol"] || element, placeholder: maskdef["placeholder"], mask: element }); + } else { + mtoken.matches.splice(position++, 0, { fn: null, cardinality: 0, optionality: mtoken.isOptional, newBlockMarker: newBlockMarker, casing: null, def: element, placeholder: undefined, mask: element }); + escaped = false; } - else if ((element != opts.optionalmarker.start && element != opts.optionalmarker.end) || escaped) { - var maskdef = opts.definitions[element]; - if (maskdef && !escaped) { - for (var i = 0; i < maskdef.cardinality; i++) { - outElem.push(getPlaceHolder(outCount + i)); + } + + var currentToken = new maskToken(), + match, + m, + openenings = [], + maskTokens = [], + openingToken, + currentOpeningToken, + alternator, + lastMatch; + + while (match = tokenizer.exec(mask)) { + m = match[0]; + switch (m.charAt(0)) { + case opts.optionalmarker.end: + // optional closing + case opts.groupmarker.end: + // Group closing + openingToken = openenings.pop(); + if (openenings.length > 0) { + currentOpeningToken = openenings[openenings.length - 1]; + currentOpeningToken["matches"].push(openingToken); + if (currentOpeningToken.isAlternator) { //handle alternator (a) | (b) case + alternator = openenings.pop(); + for (var mndx = 0; mndx < alternator.matches.length; mndx++) { + alternator.matches[mndx].isGroup = false; //don't mark alternate groups as group + } + if (openenings.length > 0) { + currentOpeningToken = openenings[openenings.length - 1]; + currentOpeningToken["matches"].push(alternator); + } else { + currentToken.matches.push(alternator); + } + } + } else { + currentToken.matches.push(openingToken); + } + break; + case opts.optionalmarker.start: + // optional opening + openenings.push(new maskToken(false, true)); + break; + case opts.groupmarker.start: + // Group opening + openenings.push(new maskToken(true)); + break; + case opts.quantifiermarker.start: + //Quantifier + var quantifier = new maskToken(false, false, true); + + m = m.replace(/[{}]/g, ""); + var mq = m.split(","), + mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]), + mq1 = mq.length == 1 ? mq0 : (isNaN(mq[1]) ? mq[1] : parseInt(mq[1])); + if (mq1 == "*" || mq1 == "+") { + mq0 = mq1 == "*" ? 0 : 1; + } + quantifier.quantifier = { min: mq0, max: mq1 }; + if (openenings.length > 0) { + var matches = openenings[openenings.length - 1]["matches"]; + match = matches.pop(); + if (!match["isGroup"]) { + var groupToken = new maskToken(true); + groupToken.matches.push(match); + match = groupToken; + } + matches.push(match); + matches.push(quantifier); + } else { + match = currentToken.matches.pop(); + if (!match["isGroup"]) { + var groupToken = new maskToken(true); + groupToken.matches.push(match); + match = groupToken; + } + currentToken.matches.push(match); + currentToken.matches.push(quantifier); + } + break; + case opts.escapeChar: + escaped = true; + break; + case opts.alternatormarker: + if (openenings.length > 0) { + currentOpeningToken = openenings[openenings.length - 1]; + lastMatch = currentOpeningToken.matches.pop(); + } else { + lastMatch = currentToken.matches.pop(); + } + if (lastMatch.isAlternator) { + openenings.push(lastMatch); + } else { + alternator = new maskToken(false, false, false, true); + alternator.matches.push(lastMatch); + openenings.push(alternator); + } + break; + default: + if (openenings.length > 0) { + currentOpeningToken = openenings[openenings.length - 1]; + if (currentOpeningToken.matches.length > 0) { + lastMatch = currentOpeningToken.matches[currentOpeningToken.matches.length - 1]; + if (lastMatch["isGroup"]) { //this is not a group but a normal mask => convert + lastMatch.isGroup = false; + insertTestDefinition(lastMatch, opts.groupmarker.start, 0); + insertTestDefinition(lastMatch, opts.groupmarker.end); + } + } + insertTestDefinition(currentOpeningToken, m); + if (currentOpeningToken.isAlternator) { //handle alternator a | b case + alternator = openenings.pop(); + for (var mndx = 0; mndx < alternator.matches.length; mndx++) { + alternator.matches[mndx].isGroup = false; //don't mark alternate groups as group + } + if (openenings.length > 0) { + currentOpeningToken = openenings[openenings.length - 1]; + currentOpeningToken["matches"].push(alternator); + } else { + currentToken.matches.push(alternator); + } + } + } else { + if (currentToken.matches.length > 0) { + lastMatch = currentToken.matches[currentToken.matches.length - 1]; + if (lastMatch["isGroup"]) { //this is not a group but a normal mask => convert + lastMatch.isGroup = false; + insertTestDefinition(lastMatch, opts.groupmarker.start, 0); + insertTestDefinition(lastMatch, opts.groupmarker.end); + } + } + insertTestDefinition(currentToken, m); } - } else { - outElem.push(element); - escaped = false; - } - outCount += outElem.length; - return outElem; } - }); + } - //allocate repetitions - var repeatedMask = singleMask.slice(); - for (var i = 1; i < opts.repeat && opts.greedy; i++) { - repeatedMask = repeatedMask.concat(singleMask.slice()); + if (currentToken.matches.length > 0) { + lastMatch = currentToken.matches[currentToken.matches.length - 1]; + if (lastMatch["isGroup"]) { //this is not a group but a normal mask => convert + lastMatch.isGroup = false; + insertTestDefinition(lastMatch, opts.groupmarker.start, 0); + insertTestDefinition(lastMatch, opts.groupmarker.end); + } + maskTokens.push(currentToken); } - return repeatedMask; + //console.log(JSON.stringify(maskTokens)); + return maskTokens; } - //test definition => {fn: RegExp/function, cardinality: int, optionality: bool, newBlockMarker: bool, offset: int, casing: null/upper/lower, def: definitionSymbol} - function getTestingChain() { - var isOptional = false, escaped = false; - var newBlockMarker = false; //indicates wheter the begin/ending of a block should be indicated - - return $.map(opts.mask.split(""), function (element, index) { - var outElem = []; - - if (element == opts.escapeChar) { - escaped = true; - } else if (element == opts.optionalmarker.start && !escaped) { - isOptional = true; - newBlockMarker = true; - } - else if (element == opts.optionalmarker.end && !escaped) { - isOptional = false; - newBlockMarker = true; + function generateMask(mask, metadata) { + if (mask == undefined || mask == "") + return undefined; + else { + if (mask.length == 1 && opts.greedy == false && opts.repeat != 0) { + opts.placeholder = ""; + } //hide placeholder with single non-greedy mask + if (opts.repeat > 0 || opts.repeat == "*" || opts.repeat == "+") { + var repeatStart = opts.repeat == "*" ? 0 : (opts.repeat == "+" ? 1 : opts.repeat); + mask = opts.groupmarker.start + mask + opts.groupmarker.end + opts.quantifiermarker.start + repeatStart + "," + opts.repeat + opts.quantifiermarker.end; } - else { - var maskdef = opts.definitions[element]; - if (maskdef && !escaped) { - var prevalidators = maskdef["prevalidator"], prevalidatorsL = prevalidators ? prevalidators.length : 0; - for (var i = 1; i < maskdef.cardinality; i++) { - var prevalidator = prevalidatorsL >= i ? prevalidators[i - 1] : [], validator = prevalidator["validator"], cardinality = prevalidator["cardinality"]; - outElem.push({ - fn: validator ? typeof validator == 'string' ? new RegExp(validator) : new function () { - this.test = validator; - } : new RegExp("."), - cardinality: cardinality ? cardinality : 1, - optionality: isOptional, - newBlockMarker: isOptional == true ? newBlockMarker : false, - offset: 0, - casing: maskdef["casing"], - def: element - }); - if (isOptional == true) //reset newBlockMarker - newBlockMarker = false; - } - outElem.push({ - fn: maskdef.validator ? typeof maskdef.validator == 'string' ? new RegExp(maskdef.validator) : new function () { - this.test = maskdef.validator; - } : new RegExp("."), - cardinality: maskdef.cardinality, - optionality: isOptional, - newBlockMarker: newBlockMarker, - offset: 0, - casing: maskdef["casing"], - def: element - }); - } else { - outElem.push({ - fn: null, - cardinality: 0, - optionality: isOptional, - newBlockMarker: newBlockMarker, - offset: 0, - casing: null, - def: element - }); - escaped = false; - } - //reset newBlockMarker - newBlockMarker = false; - return outElem; + if ($.inputmask.masksCache[mask] == undefined) { + $.inputmask.masksCache[mask] = { + "mask": mask, + "maskToken": analyseMask(mask), + "validPositions": {}, + "_buffer": undefined, + "buffer": undefined, + "tests": {}, + "metadata": metadata + }; } - }); - } - function isValid(pos, c, buffer, strict) { //strict true ~ no correction or autofill - if (pos < 0 || pos >= getMaskLength()) return false; - var testPos = determineTestPosition(pos), loopend = c ? 1 : 0, chrs = ''; - for (var i = tests[testPos].cardinality; i > loopend; i--) { - chrs += getBufferElement(buffer, testPos - (i - 1)); + return $.extend(true, {}, $.inputmask.masksCache[mask]); } - - if (c) { - chrs += c; - } - //return is false or a json object => { pos: ??, c: ??} - return tests[testPos].fn != null ? tests[testPos].fn.test(chrs, buffer, pos, strict, opts) : false; } - - function isMask(pos) { - var testPos = determineTestPosition(pos); - var test = tests[testPos]; - - return test != undefined ? test.fn : false; + function preProcessMask(mask) { + mask = mask.toString(); + if (opts.numericInput) { //TODO FIX FOR DYNAMIC MASKS WITH QUANTIFIERS + mask = mask.split('').reverse(); + for (var ndx = 0; ndx < mask.length; ndx++) { + if (mask[ndx] == opts.optionalmarker.start) + mask[ndx] = opts.optionalmarker.end; + else if (mask[ndx] == opts.optionalmarker.end) + mask[ndx] = opts.optionalmarker.start; + else if (mask[ndx] == opts.groupmarker.start) + mask[ndx] = opts.groupmarker.end; + else if (mask[ndx] == opts.groupmarker.end) + mask[ndx] = opts.groupmarker.start; + } + mask = mask.join(''); + } + return mask; } - function determineTestPosition(pos) { - return pos % tests.length; + if ($.isFunction(opts.mask)) { //allow mask to be a preprocessing fn - should return a valid mask + opts.mask = opts.mask.call(this, opts); } - - function getPlaceHolder(pos) { - return opts.placeholder.charAt(pos % opts.placeholder.length); + if ($.isArray(opts.mask)) { + if (opts.mask.length > 1) { + opts.keepStatic = opts.keepStatic == undefined ? true : opts.keepStatic; //enable by default when passing multiple masks when the option is not explicitly specified + var altMask = "("; + $.each(opts.mask, function (ndx, msk) { + if (altMask.length > 1) + altMask += ")|("; + if (msk["mask"] != undefined && !$.isFunction(msk["mask"])) { + altMask += preProcessMask(msk["mask"]); + } else { + altMask += preProcessMask(msk); + } + }); + altMask += ")"; + return generateMask(altMask, opts.mask); + } else opts.mask = opts.mask.pop(); } - function getMaskLength() { - var calculatedLength = _buffer.length; - if (!opts.greedy && opts.repeat > 1) { - calculatedLength += (_buffer.length * (opts.repeat - 1)); + if (opts.mask) { + if (opts.mask["mask"] != undefined && !$.isFunction(opts.mask["mask"])) { + ms = generateMask(preProcessMask(opts.mask["mask"]), opts.mask); + } else { + ms = generateMask(preProcessMask(opts.mask), opts.mask); } - return calculatedLength; } - //pos: from position - function seekNext(buffer, pos) { - var maskL = getMaskLength(); - if (pos >= maskL) return maskL; - var position = pos; - while (++position < maskL && !isMask(position)) { }; - return position; - } - //pos: from position - function seekPrevious(buffer, pos) { - var position = pos; - if (position <= 0) return 0; + return ms; + } + + var ua = navigator.userAgent, + iphone = ua.match(new RegExp("iphone", "i")) !== null, + android = ua.match(new RegExp("android.*safari.*", "i")) !== null, + androidchrome = ua.match(new RegExp("android.*chrome.*", "i")) !== null, + androidfirefox = ua.match(new RegExp("android.*firefox.*", "i")) !== null, + kindle = /Kindle/i.test(ua) || /Silk/i.test(ua) || /KFTT/i.test(ua) || /KFOT/i.test(ua) || /KFJWA/i.test(ua) || /KFJWI/i.test(ua) || /KFSOWI/i.test(ua) || /KFTHWA/i.test(ua) || /KFTHWI/i.test(ua) || /KFAPWA/i.test(ua) || /KFAPWI/i.test(ua), + PasteEventType = isInputEventSupported('paste') ? 'paste' : isInputEventSupported('input') ? 'input' : "propertychange"; + + //if (androidchrome) { + // var browser = navigator.userAgent.match(new RegExp("chrome.*", "i")), + // version = parseInt(new RegExp(/[0-9]+/).exec(browser)); + // androidchrome32 = (version == 32); + //} + + //masking scope + //actionObj definition see below + function maskScope(actionObj, maskset, opts) { + var isRTL = false, + undoValue, + compositionValidPos, + compositionCaretPos, + compositionData, + $el, + skipKeyPressEvent = false, //Safari 5.1.x - modal dialog fires keypress twice workaround + skipInputEvent = false, //skip when triggered from within inputmask + ignorable = false, + maxLength, + firstClick = true; - while (--position > 0 && !isMask(position)) { }; - return position; - } + //maskset helperfunctions - function setBufferElement(buffer, position, element) { - //position = prepareBuffer(buffer, position); - var test = tests[determineTestPosition(position)]; - var elem = element; - if (elem != undefined) { - switch (test.casing) { - case "upper": - elem = element.toUpperCase(); - break; - case "lower": - elem = element.toLowerCase(); - break; + function getMaskTemplate(baseOnInput, minimalPos, includeInput) { + minimalPos = minimalPos || 0; + var maskTemplate = [], ndxIntlzr, pos = 0, test, testPos; + do { + if (baseOnInput === true && getMaskSet()['validPositions'][pos]) { + var validPos = getMaskSet()['validPositions'][pos]; + test = validPos["match"]; + ndxIntlzr = validPos["locator"].slice(); + maskTemplate.push(includeInput === true ? validPos["input"] : getPlaceholder(pos, test)); + } else { + testPos = getTestTemplate(pos, ndxIntlzr, pos - 1); + test = testPos["match"]; + ndxIntlzr = testPos["locator"].slice(); + maskTemplate.push(getPlaceholder(pos, test)); } + pos++; + } while ((maxLength == undefined || pos - 1 < maxLength) && test["fn"] != null || (test["fn"] == null && test["def"] != "") || minimalPos >= pos); + maskTemplate.pop(); //drop the last one which is empty + return maskTemplate; + } + function getMaskSet() { + return maskset; + } + function resetMaskSet(soft) { + var maskset = getMaskSet(); + maskset["buffer"] = undefined; + maskset["tests"] = {}; + if (soft !== true) { + maskset["_buffer"] = undefined; + maskset["validPositions"] = {}; + maskset["p"] = 0; } - - buffer[position] = elem; } - function getBufferElement(buffer, position, autoPrepare) { - if (autoPrepare) position = prepareBuffer(buffer, position); - return buffer[position]; + function getLastValidPosition(closestTo) { + var maskset = getMaskSet(), lastValidPosition = -1, valids = maskset["validPositions"]; + if (closestTo == undefined) closestTo = -1; + var before = lastValidPosition, after = lastValidPosition; + for (var posNdx in valids) { + var psNdx = parseInt(posNdx); + if (closestTo == -1 || valids[psNdx]["match"].fn != null) { + if (psNdx <= closestTo) before = psNdx; + if (psNdx >= closestTo) after = psNdx; + } + } + lastValidPosition = (before != -1 && (closestTo - before) > 1) || after < closestTo ? before : after; + return lastValidPosition; } + function setValidPosition(pos, validTest, fromSetValid) { + if (opts.insertMode && getMaskSet()["validPositions"][pos] != undefined && fromSetValid == undefined) { + //reposition & revalidate others + var positionsClone = $.extend(true, {}, getMaskSet()["validPositions"]), lvp = getLastValidPosition(), i; + for (i = pos; i <= lvp; i++) { //clear selection + delete getMaskSet()["validPositions"][i]; + } + getMaskSet()["validPositions"][pos] = validTest; + var valid = true, j; + for (i = pos; i <= lvp ; i++) { + var t = positionsClone[i]; + if (t != undefined) { + var vps = getMaskSet()["validPositions"]; + if (!opts.keepStatic && vps[i] && (vps[i + 1] != undefined && getTests(i + 1, vps[i].locator.slice(), i).length > 1 || vps[i].alternation != undefined)) + j = i + 1; + else + j = seekNext(i); - //needed to handle the non-greedy mask repetitions - function prepareBuffer(buffer, position, isRTL) { - var j; - if (isRTL) { - while (position < 0 && buffer.length < getMaskLength()) { - j = _buffer.length - 1; - position = _buffer.length; - while (_buffer[j] !== undefined) { - buffer.unshift(_buffer[j--]); + if (positionCanMatchDefinition(j, t["match"].def)) { + valid = valid && (isValid(j, t["input"], true, true) !== false); + } else valid = t["match"].fn == null; } + if (!valid) break; } - } else { - while (buffer[position] == undefined && buffer.length < getMaskLength()) { - j = 0; - while (_buffer[j] !== undefined) { //add a new buffer - buffer.push(_buffer[j++]); - } + + if (!valid) { + getMaskSet()["validPositions"] = $.extend(true, {}, positionsClone); + return false; } - } + } else + getMaskSet()["validPositions"][pos] = validTest; - return position; + return true; } - - function writeBuffer(input, buffer, caretPos) { - input._valueSet(buffer.join('')); - if (caretPos != undefined) { - if (android) { - setTimeout(function () { - caret(input, caretPos); - }, 100); + function stripValidPositions(start, end, nocheck, strict) { + var i, startPos = start; + getMaskSet()["p"] = start; //needed for alternated position after overtype selection + if (getMaskSet()["validPositions"][start] != undefined && getMaskSet()["validPositions"][start].input == opts.radixPoint) { + end++; + startPos++; + } + var endPos = end; + for (i = startPos; i < end; i++) { //clear selection + if (getMaskSet()["validPositions"][i] != undefined) { + if (nocheck === true || opts.canClearPosition(getMaskSet(), i, getLastValidPosition(), strict, opts) != false) + delete getMaskSet()["validPositions"][i]; } - else caret(input, caretPos); } - }; - function clearBuffer(buffer, start, end) { - for (var i = start, maskL = getMaskLength(); i < end && i < maskL; i++) { - setBufferElement(buffer, i, getBufferElement(_buffer.slice(), i)); + + resetMaskSet(true); + for (i = startPos + 1 ; i <= getLastValidPosition() ;) { + while (getMaskSet()["validPositions"][startPos] != undefined) startPos++; + var s = getMaskSet()["validPositions"][startPos]; + if (i < startPos) i = startPos + 1; + var t = getMaskSet()["validPositions"][i]; + if (t != undefined && s == undefined) { + if (positionCanMatchDefinition(startPos, t.match.def) && isValid(startPos, t["input"], true) !== false) { + delete getMaskSet()["validPositions"][i]; + i++; + } + startPos++; + } else i++; } - }; + //remove radixpoint if needed + var lvp = getLastValidPosition(); + if (start <= lvp && getMaskSet()["validPositions"][lvp] != undefined && (getMaskSet()["validPositions"][lvp].input == opts.radixPoint)) + delete getMaskSet()["validPositions"][lvp]; - function setReTargetPlaceHolder(buffer, pos) { - var testPos = determineTestPosition(pos); - setBufferElement(buffer, pos, getBufferElement(_buffer, testPos)); + resetMaskSet(true); } + function getTestTemplate(pos, ndxIntlzr, tstPs) { + var testPositions = getTests(pos, ndxIntlzr, tstPs), + testPos, + lvp = getLastValidPosition(), + lvTest = getMaskSet()["validPositions"][lvp] || getTests(0)[0], + lvTestAltArr = (lvTest.alternation != undefined) ? lvTest["locator"][lvTest.alternation].split(",") : []; + for (var ndx = 0; ndx < testPositions.length; ndx++) { + testPos = testPositions[ndx]; + + if (testPos["match"] && + (((opts.greedy && testPos["match"].optionalQuantifier !== true) + || (testPos["match"].optionality === false || testPos["match"].newBlockMarker === false) && testPos["match"].optionalQuantifier !== true) && + (lvTest.alternation == undefined || + (testPos["locator"][lvTest.alternation] != undefined && checkAlternationMatch(testPos.locator[lvTest.alternation].toString().split(","), lvTestAltArr))))) { + break; + } + } - function checkVal(input, buffer, clearInvalid, skipRadixHandling) { - var isRTL = $(input).data('inputmask')['isRTL'], - inputValue = truncateInput(input._valueGet(), isRTL).split(''); + return testPos; + } + function getTest(pos) { + if (getMaskSet()['validPositions'][pos]) { + return getMaskSet()['validPositions'][pos]["match"]; + } + return getTests(pos)[0]["match"]; + } + function positionCanMatchDefinition(pos, def) { + var valid = false, tests = getTests(pos); + for (var tndx = 0; tndx < tests.length; tndx++) { + if (tests[tndx]["match"] && tests[tndx]["match"].def == def) { + valid = true; + break; + } + } + return valid; + }; + function getTests(pos, ndxIntlzr, tstPs) { + var maskTokens = getMaskSet()["maskToken"], testPos = ndxIntlzr ? tstPs : 0, ndxInitializer = ndxIntlzr || [0], matches = [], insertStop = false; + function ResolveTestFromToken(maskToken, ndxInitializer, loopNdx, quantifierRecurse) { //ndxInitilizer contains a set of indexes to speedup searches in the mtokens + function handleMatch(match, loopNdx, quantifierRecurse) { + if (testPos > 10000) { + alert("jquery.inputmask: There is probably an error in your mask definition or in the code. Create an issue on github with an example of the mask you are using. " + getMaskSet()["mask"]); + return true; + } + if (testPos == pos && match.matches == undefined) { + matches.push({ "match": match, "locator": loopNdx.reverse() }); + return true; + } else if (match.matches != undefined) { + if (match.isGroup && quantifierRecurse !== true) { //when a group pass along to the quantifier + match = handleMatch(maskToken.matches[tndx + 1], loopNdx); + if (match) return true; + } else if (match.isOptional) { + var optionalToken = match; + match = ResolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse); + if (match) { + var latestMatch = matches[matches.length - 1]["match"]; + var isFirstMatch = $.inArray(latestMatch, optionalToken.matches) == 0; + if (isFirstMatch) { + insertStop = true; //insert a stop + } + testPos = pos; //match the position after the group + } + } else if (match.isAlternator) { + var alternateToken = match, malternateMatches = [], maltMatches, + currentMatches = matches.slice(), loopNdxCnt = loopNdx.length; + var altIndex = ndxInitializer.length > 0 ? ndxInitializer.shift() : -1; + if (altIndex == -1 || typeof altIndex == "string") { + var currentPos = testPos, ndxInitializerClone = ndxInitializer.slice(), altIndexArr; + if (typeof altIndex == "string") altIndexArr = altIndex.split(","); + for (var amndx = 0; amndx < alternateToken.matches.length; amndx++) { + matches = []; + match = handleMatch(alternateToken.matches[amndx], [amndx].concat(loopNdx), quantifierRecurse) || match; + maltMatches = matches.slice(); + testPos = currentPos; + matches = []; + //cloneback + for (var i = 0; i < ndxInitializerClone.length; i++) { + ndxInitializer[i] = ndxInitializerClone[i]; + } + //fuzzy merge matches + for (var ndx1 = 0; ndx1 < maltMatches.length; ndx1++) { + var altMatch = maltMatches[ndx1]; + for (var ndx2 = 0; ndx2 < malternateMatches.length; ndx2++) { + var altMatch2 = malternateMatches[ndx2]; + //verify equality + if (altMatch.match.mask == altMatch2.match.mask && (typeof altIndex != "string" || $.inArray(altMatch.locator[loopNdxCnt].toString(), altIndexArr) != -1)) { + maltMatches.splice(ndx1, 1); + altMatch2.locator[loopNdxCnt] = altMatch2.locator[loopNdxCnt] + "," + altMatch.locator[loopNdxCnt]; + altMatch2.alternation = loopNdxCnt; //we pass the alternation index => used in determineLastRequiredPosition + break; + } + } + } + malternateMatches = malternateMatches.concat(maltMatches); + } - if (isRTL) { //align inputValue for RTL/numeric input - var maskL = getMaskLength(); - var inputValueRev = inputValue.reverse(); - inputValueRev.length = maskL; + if (typeof altIndex == "string") { //filter matches + malternateMatches = $.map(malternateMatches, function (lmnt, ndx) { + if (isFinite(ndx)) { + var altLocArr = lmnt.locator[loopNdxCnt].toString().split(","); + var mamatch; + lmnt.locator[loopNdxCnt] = undefined; + lmnt.alternation = undefined; + for (var alndx = 0; alndx < altLocArr.length; alndx++) { + mamatch = $.inArray(altLocArr[alndx], altIndexArr) != -1; + if (mamatch) { //rebuild the locator with valid entries + if (lmnt.locator[loopNdxCnt] != undefined) { + lmnt.locator[loopNdxCnt] += ","; + lmnt.alternation = loopNdxCnt; //only define alternation when there is more then 1 possibility + lmnt.locator[loopNdxCnt] += altLocArr[alndx]; + } else + lmnt.locator[loopNdxCnt] = parseInt(altLocArr[alndx]); + } + } + if (lmnt.locator[loopNdxCnt] != undefined) return lmnt; + } + }); + } - for (var i = 0; i < maskL; i++) { - var targetPosition = determineTestPosition(maskL - (i + 1)); - if (tests[targetPosition].fn == null && inputValueRev[i] != getBufferElement(_buffer, targetPosition)) { - inputValueRev.splice(i, 0, getBufferElement(_buffer, targetPosition)); - inputValueRev.length = maskL; - } else { - inputValueRev[i] = inputValueRev[i] || getBufferElement(_buffer, targetPosition); - } - } - inputValue = inputValueRev.reverse(); - } - clearBuffer(buffer, 0, buffer.length); - buffer.length = _buffer.length; - var lastMatch = -1, checkPosition = -1, np, maskL = getMaskLength(), ivl = inputValue.length, rtlMatch = ivl == 0 ? maskL : -1; - for (var i = 0; i < ivl; i++) { - for (var pos = checkPosition + 1; pos < maskL; pos++) { - if (isMask(pos)) { - var c = inputValue[i]; - if ((np = isValid(pos, c, buffer, !clearInvalid)) !== false) { - if (np !== true) { - pos = np.pos || pos; //set new position from isValid - c = np.c || c; //set new char from isValid + matches = currentMatches.concat(malternateMatches); + //console.log("alternates " + pos + " -> " + JSON.stringify(matches)); + insertStop = true; //insert a stopelemnt when there is an alternate + } else { + match = handleMatch(alternateToken.matches[altIndex], [altIndex].concat(loopNdx), quantifierRecurse); } - setBufferElement(buffer, pos, c); - lastMatch = checkPosition = pos; - } else { - setReTargetPlaceHolder(buffer, pos); - if (c == getPlaceHolder(pos)) { - checkPosition = pos; - rtlMatch = pos; + if (match) return true; + } else if (match.isQuantifier && quantifierRecurse !== true) { + var qt = match; + for (var qndx = (ndxInitializer.length > 0 && quantifierRecurse !== true) ? ndxInitializer.shift() : 0; (qndx < (isNaN(qt.quantifier.max) ? qndx + 1 : qt.quantifier.max)) && testPos <= pos; qndx++) { + var tokenGroup = maskToken.matches[$.inArray(qt, maskToken.matches) - 1]; + match = handleMatch(tokenGroup, [qndx].concat(loopNdx), true); + if (match) { + //get latest match + var latestMatch = matches[matches.length - 1]["match"]; + latestMatch.optionalQuantifier = qndx > (qt.quantifier.min - 1); + var isFirstMatch = $.inArray(latestMatch, tokenGroup.matches) == 0; + + if (isFirstMatch) { //search for next possible match + if (qndx > (qt.quantifier.min - 1)) { + insertStop = true; + testPos = pos; //match the position after the group + break; //stop quantifierloop + } else return true; + } else { + return true; + } + } } + } else { + match = ResolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse); + if (match) + return true; } - break; - } else { //nonmask - setReTargetPlaceHolder(buffer, pos); - if (lastMatch == checkPosition) //once outsync the nonmask cannot be the lastmatch - lastMatch = pos; - checkPosition = pos; - if (inputValue[i] == getBufferElement(buffer, pos)) + } else testPos++; + } + + for (var tndx = (ndxInitializer.length > 0 ? ndxInitializer.shift() : 0) ; tndx < maskToken.matches.length; tndx++) { + if (maskToken.matches[tndx]["isQuantifier"] !== true) { + var match = handleMatch(maskToken.matches[tndx], [tndx].concat(loopNdx), quantifierRecurse); + if (match && testPos == pos) { + return match; + } else if (testPos > pos) { break; + } } } } - //Truncate buffer when using non-greedy masks - if (opts.greedy == false) { - var newBuffer = truncateInput(buffer.join(''), isRTL).split(''); - while (buffer.length != newBuffer.length) { //map changes into the original buffer - isRTL ? buffer.shift() : buffer.pop(); + + //if (disableCache !== true && getMaskSet()['tests'][pos] && !getMaskSet()['validPositions'][pos]) { + // return getMaskSet()['tests'][pos]; + //} + if (ndxIntlzr == undefined) { + var previousPos = pos - 1, test; + while ((test = getMaskSet()['validPositions'][previousPos]) == undefined && previousPos > -1) { + previousPos--; + } + if (test != undefined && previousPos > -1) { + testPos = previousPos; + ndxInitializer = test["locator"].slice(); + } else { + previousPos = pos - 1; + while ((test = getMaskSet()['tests'][previousPos]) == undefined && previousPos > -1) { + previousPos--; + } + if (test != undefined && previousPos > -1) { + testPos = previousPos; + ndxInitializer = test[0]["locator"].slice(); + } } } - - if (clearInvalid) { - writeBuffer(input, buffer); + for (var mtndx = ndxInitializer.shift() ; mtndx < maskTokens.length; mtndx++) { + var match = ResolveTestFromToken(maskTokens[mtndx], ndxInitializer, [mtndx]); + if ((match && testPos == pos) || testPos > pos) { + break; + } } - return isRTL ? (opts.numericInput ? ($.inArray(opts.radixPoint, buffer) != -1 && skipRadixHandling !== true ? $.inArray(opts.radixPoint, buffer) : seekNext(buffer, maskL)) : seekNext(buffer, rtlMatch)) : seekNext(buffer, lastMatch); - } + if (matches.length == 0 || insertStop) + matches.push({ "match": { fn: null, cardinality: 0, optionality: true, casing: null, def: "" }, "locator": [] }); - function escapeRegex(str) { - var specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\']; - return str.replace(new RegExp('(\\' + specials.join('|\\') + ')', 'gim'), '\\$1'); - } - function truncateInput(inputValue, rtl) { - return rtl ? inputValue.replace(new RegExp("^(" + escapeRegex(_buffer.join('')) + ")*"), "") : inputValue.replace(new RegExp("(" + escapeRegex(_buffer.join('')) + ")*$"), ""); + getMaskSet()['tests'][pos] = $.extend(true, [], matches); //set a clone to prevent overwriting some props + //console.log(pos + " - " + JSON.stringify(matches)); + return getMaskSet()['tests'][pos]; } - - function clearOptionalTail(input, buffer) { - checkVal(input, buffer, false); - var tmpBuffer = buffer.slice(); - if ($(input).data('inputmask')['isRTL']) { - for (var pos = 0; pos <= tmpBuffer.length - 1; pos++) { - var testPos = determineTestPosition(pos); - if (tests[testPos].optionality) { - if (getPlaceHolder(pos) == buffer[pos] || !isMask(pos)) - tmpBuffer.splice(0, 1); - else break; - } else break; - } - } else { - for (var pos = tmpBuffer.length - 1; pos >= 0; pos--) { - var testPos = determineTestPosition(pos); - if (tests[testPos].optionality) { - if (getPlaceHolder(pos) == buffer[pos] || !isMask(pos)) - tmpBuffer.pop(); - else break; - } else break; - } + function getBufferTemplate() { + if (getMaskSet()['_buffer'] == undefined) { + //generate template + getMaskSet()["_buffer"] = getMaskTemplate(false, 1); } - writeBuffer(input, tmpBuffer); + return getMaskSet()['_buffer']; } - - //functionality fn - function unmaskedvalue($input, skipDatepickerCheck) { - var input = $input[0]; - if (tests && (skipDatepickerCheck === true || !$input.hasClass('hasDatepicker'))) { - var buffer = _buffer.slice(); - checkVal(input, buffer); - return $.map(buffer, function (element, index) { - return isMask(index) && element != getBufferElement(_buffer.slice(), index) ? element : null; - }).join(''); - } - else { - return input._valueGet(); + function getBuffer() { + if (getMaskSet()['buffer'] == undefined) { + getMaskSet()['buffer'] = getMaskTemplate(true, getLastValidPosition(), true); } + return getMaskSet()['buffer']; } - - function caret(input, begin, end) { - var npt = input.jquery && input.length > 0 ? input[0] : input; - if (typeof begin == 'number') { - end = (typeof end == 'number') ? end : begin; - if (opts.insertMode == false && begin == end) end++; //set visualization for insert/overwrite mode - if (npt.setSelectionRange) { - npt.setSelectionRange(begin, end); - } else if (npt.createTextRange) { - var range = npt.createTextRange(); - range.collapse(true); - range.moveEnd('character', end); - range.moveStart('character', begin); - range.select(); - } - npt.focus(); - if (android && end != npt.selectionEnd) caretposCorrection = { - begin: begin, - end: end - }; + function refreshFromBuffer(start, end, buffer) { + buffer = buffer || getBuffer().slice(); //pass or work on clone + if (start === true) { + resetMaskSet(); + start = 0; + end = buffer.length; } else { - var caretpos = android ? caretposCorrection : null, caretposCorrection = null; - if (caretpos == null) { - if (npt.setSelectionRange) { - begin = npt.selectionStart; - end = npt.selectionEnd; - } else if (document.selection && document.selection.createRange) { - var range = document.selection.createRange(); - begin = 0 - range.duplicate().moveStart('character', -100000); - end = begin + range.text.length; - } - caretpos = { - begin: begin, - end: end - }; + for (var i = start; i < end; i++) { + delete getMaskSet()["validPositions"][i]; + delete getMaskSet()["tests"][i]; } - return caretpos; } - }; - function mask(el) { - var $input = $(el); - if (!$input.is(":input")) return; - - //correct greedy setting if needed - opts.greedy = opts.greedy ? opts.greedy : opts.repeat == 0; - - //handle maxlength attribute - var maxLength = $input.prop('maxLength'); - if (getMaskLength() > maxLength && maxLength > -1) { //FF sets no defined max length to -1 - if (maxLength < _buffer.length) _buffer.length = maxLength; - if (opts.greedy == false) { - opts.repeat = Math.round(maxLength / _buffer.length); + for (var i = start; i < end; i++) { + if (buffer[i] != opts.skipOptionalPartCharacter) { + isValid(i, buffer[i], true, true); } } - $input.prop('maxLength', getMaskLength() * 2); - - //store tests & original buffer in the input element - used to get the unmasked value - $input.data('inputmask', { - 'tests': tests, - '_buffer': _buffer, - 'greedy': opts.greedy, - 'repeat': opts.repeat, - 'autoUnmask': opts.autoUnmask, - 'definitions': opts.definitions, - 'isRTL': false - }); - - patchValueProperty(el); + } + function casing(elem, test) { + switch (test.casing) { + case "upper": + elem = elem.toUpperCase(); + break; + case "lower": + elem = elem.toLowerCase(); + break; + } - //init vars - var buffer = _buffer.slice(), - undoBuffer = el._valueGet(), - skipKeyPressEvent = false, //Safari 5.1.x - modal dialog fires keypress twice workaround - ignorable = false, - lastPosition = -1, - firstMaskPos = seekNext(buffer, -1), - lastMaskPos = seekPrevious(buffer, getMaskLength()), - isRTL = false; - if (el.dir == "rtl" || opts.numericInput) { - el.dir = "ltr" - $input.css("text-align", "right"); - $input.removeAttr("dir"); - var inputData = $input.data('inputmask'); - inputData['isRTL'] = true; - $input.data('inputmask', inputData); - isRTL = true; - } - - //unbind all events - to make sure that no other mask will interfere when re-masking - $input.unbind(".inputmask"); - $input.removeClass('focus.inputmask'); - //bind events - $input.bind("mouseenter.inputmask", function () { - var $input = $(this), input = this; - if (!$input.hasClass('focus.inputmask') && opts.showMaskOnHover) { - var nptL = input._valueGet().length; - if (nptL < buffer.length) { - if (nptL == 0) - buffer = _buffer.slice(); - writeBuffer(input, buffer); - } - } - }).bind("blur.inputmask", function () { - var $input = $(this), input = this, nptValue = input._valueGet(); - $input.removeClass('focus.inputmask'); - if (nptValue != undoBuffer) { - $input.change(); + return elem; + } + function checkAlternationMatch(altArr1, altArr2) { + var altArrC = opts.greedy ? altArr2 : altArr2.slice(0, 1), + isMatch = false; + for (var alndx = 0; alndx < altArr1.length; alndx++) { + if ($.inArray(altArr1[alndx], altArrC) != -1) { + isMatch = true; + break; } - if (opts.clearMaskOnLostFocus) { - if (nptValue == _buffer.join('')) - input._valueSet(''); - else { //clearout optional tail of the mask - clearOptionalTail(input, buffer); + } + return isMatch; + } + function isValid(pos, c, strict, fromSetValid) { //strict true ~ no correction or autofill + strict = strict === true; //always set a value to strict to prevent possible strange behavior in the extensions + + function _isValid(position, c, strict, fromSetValid) { + var rslt = false; + $.each(getTests(position), function (ndx, tst) { + var test = tst["match"]; + var loopend = c ? 1 : 0, chrs = '', buffer = getBuffer(); + for (var i = test.cardinality; i > loopend; i--) { + chrs += getBufferElement(position - (i - 1)); } - } - if (!isComplete(input)) { - $input.trigger("incomplete"); - if (opts.clearIncomplete) { - if (opts.clearMaskOnLostFocus) - input._valueSet(''); - else { - buffer = _buffer.slice(); - writeBuffer(input, buffer); + if (c) { + chrs += c; + } + + //return is false or a json object => { pos: ??, c: ??} or true + rslt = test.fn != null ? + test.fn.test(chrs, getMaskSet(), position, strict, opts) + : (c == test["def"] || c == opts.skipOptionalPartCharacter) && test["def"] != "" ? //non mask + { c: test["def"], pos: position } + : false; + + if (rslt !== false) { + var elem = rslt.c != undefined ? rslt.c : c; + elem = (elem == opts.skipOptionalPartCharacter && test["fn"] === null) ? test["def"] : elem; + + var validatedPos = position; + if (rslt["remove"] != undefined) { //remove position + stripValidPositions(rslt["remove"], rslt["remove"] + 1, true); + } + + if (rslt["refreshFromBuffer"]) { + var refresh = rslt["refreshFromBuffer"]; + strict = true; + refreshFromBuffer(refresh === true ? refresh : refresh["start"], refresh["end"]); + if (rslt.pos == undefined && rslt.c == undefined) { + rslt.pos = getLastValidPosition(); + return false;//breakout if refreshFromBuffer && nothing to insert + } + validatedPos = rslt.pos != undefined ? rslt.pos : position; + if (validatedPos != position) { + rslt = $.extend(rslt, isValid(validatedPos, elem, true)); //revalidate new position strict + return false; + } + + } else if (rslt !== true && rslt.pos != undefined && rslt["pos"] != position) { //their is a position offset + validatedPos = rslt["pos"]; + refreshFromBuffer(position, validatedPos); + if (validatedPos != position) { + rslt = $.extend(rslt, isValid(validatedPos, elem, true)); //revalidate new position strict + return false; + } } + + if (rslt != true && rslt.pos == undefined && rslt.c == undefined) { + return false; //breakout if nothing to insert + } + + if (ndx > 0) { + resetMaskSet(true); + } + + if (!setValidPosition(validatedPos, $.extend({}, tst, { "input": casing(elem, test) }), fromSetValid)) + rslt = false; + return false; //break from $.each } - } - }).bind("focus.inputmask", function () { - var $input = $(this), input = this; - if (!$input.hasClass('focus.inputmask') && !opts.showMaskOnHover) { - var nptL = input._valueGet().length; - if (nptL < buffer.length) { - if (nptL == 0) - buffer = _buffer.slice(); - caret(input, checkVal(input, buffer, true)); + }); + + return rslt; + } + function alternate(pos, c, strict, fromSetValid) { + var validPsClone = $.extend(true, {}, getMaskSet()["validPositions"]), + lastAlt, + alternation; + //find last alternation + for (lastAlt = getLastValidPosition() ; lastAlt >= 0; lastAlt--) { + if (getMaskSet()["validPositions"][lastAlt] && getMaskSet()["validPositions"][lastAlt].alternation != undefined) { + alternation = getMaskSet()["validPositions"][lastAlt].alternation; + break; } } - $input.addClass('focus.inputmask'); - undoBuffer = input._valueGet(); - }).bind("mouseleave.inputmask", function () { - var $input = $(this), input = this; - if (opts.clearMaskOnLostFocus) { - if (!$input.hasClass('focus.inputmask')) { - if (input._valueGet() == _buffer.join('') || input._valueGet() == '') - input._valueSet(''); - else { //clearout optional tail of the mask - clearOptionalTail(input, buffer); + if (alternation != undefined) { + //find first decision making position + for (var decisionPos in getMaskSet()["validPositions"]) { + if (parseInt(decisionPos) > parseInt(lastAlt) && getMaskSet()["validPositions"][decisionPos].alternation === undefined) { + var altPos = getMaskSet()["validPositions"][decisionPos], + decisionTaker = altPos.locator[alternation], + altNdxs = getMaskSet()["validPositions"][lastAlt].locator[alternation].split(","); + + for (var mndx = 0; mndx < altNdxs.length; mndx++) { + if (decisionTaker < altNdxs[mndx]) { + var possibilityPos, possibilities; + for (var dp = decisionPos - 1; dp >= 0; dp--) { + possibilityPos = getMaskSet()["validPositions"][dp]; + if (possibilityPos != undefined) { + possibilities = possibilityPos.locator[alternation]; //store to reset + possibilityPos.locator[alternation] = altNdxs[mndx]; + break; + } + } + if (decisionTaker != possibilityPos.locator[alternation]) { + var buffer = getBuffer().slice(); //work on clone + for (var i = decisionPos; i < getLastValidPosition() + 1; i++) { + delete getMaskSet()["validPositions"][i]; + delete getMaskSet()["tests"][i]; + } + resetMaskSet(true); //clear getbuffer + opts.keepStatic = !opts.keepStatic; //disable keepStatic on getMaskLength + for (var i = decisionPos; i < buffer.length; i++) { + if (buffer[i] != opts.skipOptionalPartCharacter) { + isValid(getLastValidPosition() + 1, buffer[i], false, true); + } + } + possibilityPos.locator[alternation] = possibilities; //reset forceddecision ~ needed for proper delete + var isValidRslt = isValid(pos, c, strict, fromSetValid); + opts.keepStatic = !opts.keepStatic; //enable keepStatic on getMaskLength + if (!isValidRslt) { + resetMaskSet(); + getMaskSet()["validPositions"] = $.extend(true, {}, validPsClone); + } else + return isValidRslt; + } + } + } + break; } } } - }).bind("click.inputmask", function () { - var input = this; - setTimeout(function () { - var selectedCaret = caret(input); - if (selectedCaret.begin == selectedCaret.end) { - var clickPosition = selectedCaret.begin; - lastPosition = checkVal(input, buffer, false); - if (isRTL) - caret(input, clickPosition > lastPosition && (isValid(clickPosition, buffer[clickPosition], buffer, true) !== false || !isMask(clickPosition)) ? clickPosition : lastPosition); - else - caret(input, clickPosition < lastPosition && (isValid(clickPosition, buffer[clickPosition], buffer, true) !== false || !isMask(clickPosition)) ? clickPosition : lastPosition); + return false; + } + //set alternator choice on previous skipped placeholder positions + function trackbackAlternations(originalPos, newPos) { + var vp = getMaskSet()["validPositions"][newPos], + targetLocator = vp.locator, + tll = targetLocator.length; + + for (var ps = originalPos; ps < newPos; ps++) { + if (!isMask(ps)) { + var tests = getTests(ps), + bestMatch = tests[0], equality = -1; + $.each(tests, function (ndx, tst) { + for (var i = 0; i < tll; i++) { + if (tst.locator[i] && checkAlternationMatch(tst.locator[i].toString().split(','), targetLocator[i].toString().split(',')) && equality < i) { + equality = i; + bestMatch = tst; + } + } + }); + setValidPosition(ps, $.extend({}, bestMatch, { "input": bestMatch["match"].def }), true) } - }, 0); - }).bind('dblclick.inputmask', function () { - var input = this; - setTimeout(function () { - caret(input, 0, lastPosition); - }, 0); - }).bind("keydown.inputmask", keydownEvent - ).bind("keypress.inputmask", keypressEvent - ).bind("keyup.inputmask", keyupEvent - ).bind(pasteEvent + ".inputmask, dragdrop.inputmask, drop.inputmask", function () { - var input = this; - setTimeout(function () { - caret(input, checkVal(input, buffer, true)); - }, 0); - }).bind('setvalue.inputmask', function () { - var input = this; - undoBuffer = input._valueGet(); - checkVal(input, buffer, true); - if (input._valueGet() == _buffer.join('')) - input._valueSet(''); - }).bind('complete.inputmask', opts.oncomplete) - .bind('incomplete.inputmask', opts.onincomplete) - .bind('cleared.inputmask', opts.oncleared); - - //apply mask - lastPosition = checkVal(el, buffer, true); - - // Wrap document.activeElement in a try/catch block since IE9 throw "Unspecified error" if document.activeElement is undefined when we are in an IFrame. - var activeElement; - try { - activeElement = document.activeElement; - } catch (e) { } - if (activeElement === el) { //position the caret when in focus - $input.addClass('focus.inputmask'); - caret(el, lastPosition); - } else if (opts.clearMaskOnLostFocus) { - if (el._valueGet() == _buffer.join('')) { - el._valueSet(''); - } else { - clearOptionalTail(el, buffer); + } + } + //Check for a nonmask before the pos + var buffer = getBuffer(); + //find previous valid + for (var pndx = pos - 1; pndx > -1; pndx--) { + if (getMaskSet()["validPositions"][pndx]) + break; + } + ////fill missing nonmask and valid placeholders + pndx++; + for (; pndx < pos; pndx++) { + //console.log("missing " + pndx + " " + buffer[pndx] + " ismask " + isMask(pndx) + " plchldr " + getPlaceholder(pndx) + " nrt " + getTests(pndx).len); + if (getMaskSet()["validPositions"][pndx] == undefined + && (((!isMask(pndx) + || buffer[pndx] != getPlaceholder(pndx)) + && getTests(pndx).length > 1) + || (buffer[pndx] == opts.radixPoint || buffer[pndx] == "0" && $.inArray(opts.radixPoint, buffer) < pndx))) //special case for decimals ~ = placeholder but yet valid input + { + //console.log("inject " + pndx + " " + buffer[pndx]); + _isValid(pndx, buffer[pndx], true); } } - installEventRuler(el); + var maskPos = pos; + var result = false; - //private functions - function isComplete(npt) { - var complete = true, nptValue = npt._valueGet(), ml = nptValue.length; - for (var i = 0; i < ml; i++) { - if (isMask(i) && nptValue.charAt(i) == getPlaceHolder(i)) { - complete = false; - break; + if (fromSetValid && maskPos >= getMaskLength()) { + resetMaskSet(true); //masklenght can be altered on the process => reset to get the actual length + } + if (maskPos < getMaskLength()) { + result = _isValid(maskPos, c, strict, fromSetValid); + if (!strict && result === false) { + var currentPosValid = getMaskSet()["validPositions"][maskPos]; + if (currentPosValid && currentPosValid["match"].fn == null && (currentPosValid["match"].def == c || c == opts.skipOptionalPartCharacter)) { + result = { "caret": seekNext(maskPos) }; + } else if ((opts.insertMode || getMaskSet()["validPositions"][seekNext(maskPos)] == undefined) && !isMask(maskPos)) { //does the input match on a further position? + for (var nPos = maskPos + 1, snPos = seekNext(maskPos) ; nPos <= snPos; nPos++) { + result = _isValid(nPos, c, strict, fromSetValid); + if (result !== false) { + trackbackAlternations(maskPos, nPos); + maskPos = nPos; + break; + } + } } } - return complete; } + if (result === false && opts.keepStatic && isComplete(buffer)) { //try fuzzy alternator logic + result = alternate(pos, c, strict, fromSetValid); + } + if (result === true) result = { "pos": maskPos }; + return result; + } + function isMask(pos) { + var test = getTest(pos); + return test.fn != null ? test.fn : false; + } + function getMaskLength() { + var maskLength; + maxLength = $el.prop('maxLength'); + if (maxLength == -1) maxLength = undefined; /* FF sets no defined max length to -1 */ + //if (opts.greedy == false) { //FIXME TODO + var pos, lvp = getLastValidPosition(), testPos = getMaskSet()["validPositions"][lvp], + ndxIntlzr = testPos != undefined ? testPos["locator"].slice() : undefined; + for (pos = lvp + 1; testPos == undefined || (testPos["match"]["fn"] != null || (testPos["match"]["fn"] == null && testPos["match"]["def"] != "")) ; pos++) { + testPos = getTestTemplate(pos, ndxIntlzr, pos - 1); + ndxIntlzr = testPos["locator"].slice(); + } + maskLength = pos; + //} else + // maskLength = getBuffer().length; + return (maxLength == undefined || maskLength < maxLength) ? maskLength : maxLength; + } + function seekNext(pos) { + var maskL = getMaskLength(); + if (pos >= maskL) return maskL; + var position = pos; + while (++position < maskL && !isMask(position) && (opts.nojumps !== true || opts.nojumpsThreshold > position)) { + } + return position; + } + function seekPrevious(pos) { + var position = pos; + if (position <= 0) return 0; - function installEventRuler(npt) { - var events = $._data(npt).events; - - $.each(events, function (eventType, eventHandlers) { - $(npt).bind(eventType + ".inputmask", function (event) { - if (this.readOnly || this.disabled) { - event.stopPropagation(); - event.stopImmediatePropagation(); - event.preventDefault(); - return false; + while (--position > 0 && !isMask(position)) { + }; + return position; + } + function getBufferElement(position) { + return getMaskSet()["validPositions"][position] == undefined ? getPlaceholder(position) : getMaskSet()["validPositions"][position]["input"]; + } + function writeBuffer(input, buffer, caretPos, event, triggerInputEvent) { + if (event && $.isFunction(opts.onBeforeWrite)) { + var result = opts.onBeforeWrite.call(input, event, buffer, caretPos, opts); + if (result) { + if (result["refreshFromBuffer"]) { + var refresh = result["refreshFromBuffer"]; + refreshFromBuffer(refresh === true ? refresh : refresh["start"], refresh["end"], result["buffer"]); + + resetMaskSet(true); + } + caretPos = result.caret || caretPos; + } + } + input._valueSet(buffer.join('')); + if (caretPos != undefined) { + caret(input, caretPos); + } + if (triggerInputEvent === true) { + skipInputEvent = true; + $(input).trigger("input"); + } + } + function getPlaceholder(pos, test) { + test = test || getTest(pos); + return test["placeholder"] != undefined ? test["placeholder"] : (test["fn"] == null ? test["def"] : opts.placeholder.charAt(pos % opts.placeholder.length)); + } + function checkVal(input, writeOut, strict, nptvl) { + function isTemplateMatch() { + var isMatch = false; + var charCodeNdx = getBufferTemplate().slice(initialNdx, seekNext(initialNdx)).join('').indexOf(charCodes); + if (charCodeNdx != -1 && !isMask(initialNdx)) { + isMatch = true; + var bufferTemplateArr = getBufferTemplate().slice(initialNdx, initialNdx + charCodeNdx); + for (var i = 0; i < bufferTemplateArr.length; i++) { + if (bufferTemplateArr[i] != " ") { + isMatch = false; break; } - }); - //!! the bound handlers are executed in the order they where bound - //reorder the events - var ourHandler = eventHandlers[eventHandlers.length - 1]; - for (var i = eventHandlers.length - 1; i > 0; i--) { - eventHandlers[i] = eventHandlers[i - 1]; } - eventHandlers[0] = ourHandler; - }); + } + + return isMatch; + } + var inputValue = nptvl != undefined ? nptvl.slice() : input._valueGet().split(''); + resetMaskSet(); + getMaskSet()["p"] = seekNext(-1); + if (writeOut) input._valueSet(""); //initial clear + + var staticInput = getBufferTemplate().slice(0, seekNext(-1)).join(''), matches = inputValue.join('').match(new RegExp(escapeRegex(staticInput), "g")); + if (matches && matches.length > 0) { + inputValue.splice(0, staticInput.length * matches.length); } - function patchValueProperty(npt) { - var valueProperty; - if (Object.getOwnPropertyDescriptor) - valueProperty = Object.getOwnPropertyDescriptor(npt, "value"); - if (valueProperty && valueProperty.get) { - if (!npt._valueGet) { - - npt._valueGet = valueProperty.get; - npt._valueSet = valueProperty.set; - - Object.defineProperty(npt, "value", { - get: function () { - var $self = $(this), inputData = $(this).data('inputmask'); - return inputData && inputData['autoUnmask'] ? $self.inputmask('unmaskedvalue') : this._valueGet() != inputData['_buffer'].join('') ? this._valueGet() : ''; - }, - set: function (value) { - this._valueSet(value); - $(this).triggerHandler('setvalue.inputmask'); - } - }); - } - } else if (document.__lookupGetter__ && npt.__lookupGetter__("value")) { - if (!npt._valueGet) { - npt._valueGet = npt.__lookupGetter__("value"); - npt._valueSet = npt.__lookupSetter__("value"); + var charCodes = "", initialNdx = 0; + $.each(inputValue, function (ndx, charCode) { + var keypress = $.Event("keypress"); + keypress.which = charCode.charCodeAt(0); + charCodes += charCode; + var lvp = getLastValidPosition(), lvTest = getMaskSet()["validPositions"][lvp], nextTest = getTestTemplate(lvp + 1, lvTest ? lvTest.locator.slice() : undefined, lvp); + if (!isTemplateMatch() || strict) { + var pos = strict ? ndx : (nextTest["match"].fn == null && nextTest["match"].optionality && (lvp + 1) < getMaskSet()["p"] ? lvp + 1 : getMaskSet()["p"]); + keypressEvent.call(input, keypress, true, false, strict, pos); + initialNdx = pos + 1; + charCodes = ""; + } else { + keypressEvent.call(input, keypress, true, false, true, lvp + 1); + } - npt.__defineGetter__("value", function () { - var $self = $(this), inputData = $(this).data('inputmask'); - return inputData && inputData['autoUnmask'] ? $self.inputmask('unmaskedvalue') : this._valueGet() != inputData['_buffer'].join('') ? this._valueGet() : ''; - }); - npt.__defineSetter__("value", function (value) { - this._valueSet(value); - $(this).triggerHandler('setvalue.inputmask'); - }); + }); + if (writeOut) { + writeBuffer(input, getBuffer(), $(input).is(":focus") ? seekNext(getLastValidPosition(0)) : undefined, $.Event("checkval")); + } + } + function escapeRegex(str) { + return $.inputmask.escapeRegex.call(this, str); + } + function unmaskedvalue($input) { + if ($input.data('_inputmask') && !$input.hasClass('hasDatepicker')) { + var umValue = [], vps = getMaskSet()["validPositions"]; + for (var pndx in vps) { + if (vps[pndx]["match"] && vps[pndx]["match"].fn != null) { + umValue.push(vps[pndx]["input"]); } - } else { - if (!npt._valueGet) { - npt._valueGet = function () { - return this.value; - } - npt._valueSet = function (value) { - this.value = value; + } + var unmaskedValue = (isRTL ? umValue.reverse() : umValue).join(''); + var bufferValue = (isRTL ? getBuffer().slice().reverse() : getBuffer()).join(''); + if ($.isFunction(opts.onUnMask)) { + unmaskedValue = (opts.onUnMask.call($input, bufferValue, unmaskedValue, opts) || unmaskedValue); + } + return unmaskedValue; + } else { + return $input[0]._valueGet(); + } + } + function TranslatePosition(pos) { + if (isRTL && typeof pos == 'number' && (!opts.greedy || opts.placeholder != "")) { + var bffrLght = getBuffer().length; + pos = bffrLght - pos; + } + return pos; + } + function caret(input, begin, end) { + var npt = input.jquery && input.length > 0 ? input[0] : input, range; + if (typeof begin == 'number') { + begin = TranslatePosition(begin); + end = TranslatePosition(end); + end = (typeof end == 'number') ? end : begin; + + if (!$(npt).is(":visible")) { return; } + + var scrollCalc = $(npt).css("font-size").replace("px", "") * end; + npt.scrollLeft = scrollCalc > npt.scrollWidth ? scrollCalc : 0; + if (opts.insertMode == false && begin == end) end++; //set visualization for insert/overwrite mode + if (npt.setSelectionRange) { + npt.selectionStart = begin; + npt.selectionEnd = end; + } else if (npt.createTextRange) { + range = npt.createTextRange(); + range.collapse(true); + range.moveEnd('character', end); + range.moveStart('character', begin); + range.select(); + } + } else { + if (npt.setSelectionRange) { + begin = npt.selectionStart; + end = npt.selectionEnd; + } else if (document.selection && document.selection.createRange) { + range = document.selection.createRange(); + begin = 0 - range.duplicate().moveStart('character', -100000); + end = begin + range.text.length; + } + return { "begin": TranslatePosition(begin), "end": TranslatePosition(end) }; + } + } + function determineLastRequiredPosition(returnDefinition) { + var buffer = getBuffer(), bl = buffer.length, + pos, lvp = getLastValidPosition(), positions = {}, lvTest = getMaskSet()["validPositions"][lvp], + ndxIntlzr = lvTest != undefined ? lvTest["locator"].slice() : undefined, testPos; + for (pos = lvp + 1; pos < buffer.length; pos++) { + testPos = getTestTemplate(pos, ndxIntlzr, pos - 1); + ndxIntlzr = testPos["locator"].slice(); + positions[pos] = $.extend(true, {}, testPos); + } + + var lvTestAltArr = lvTest && lvTest.alternation != undefined ? lvTest["locator"][lvTest.alternation].split(",") : []; + for (pos = bl - 1; pos > lvp; pos--) { + testPos = positions[pos]["match"]; + if ((testPos.optionality || + testPos.optionalQuantifier || + (lvTest && lvTest.alternation != undefined && positions[pos]["locator"][lvTest.alternation] != undefined && $.inArray(positions[pos]["locator"][lvTest.alternation].toString(), lvTestAltArr) != -1)) + && buffer[pos] == getPlaceholder(pos, testPos)) { + bl--; + } else break; + } + return returnDefinition ? { "l": bl, "def": positions[bl] ? positions[bl]["match"] : undefined } : bl; + } + function clearOptionalTail(buffer) { + var rl = determineLastRequiredPosition(), lmib = buffer.length - 1; + for (; lmib > rl; lmib--) { + if (isMask(lmib)) break; //fixme ismask is not good enough + } + buffer.splice(rl, lmib + 1 - rl); + } + function isComplete(buffer) { //return true / false / undefined (repeat *) + if ($.isFunction(opts.isComplete)) return opts.isComplete.call($el, buffer, opts); + if (opts.repeat == "*") return undefined; + var complete = false, lrp = determineLastRequiredPosition(true), aml = seekPrevious(lrp["l"]), lvp = getLastValidPosition(); + + if (lvp == aml) { + if (lrp["def"] == undefined || lrp["def"].newBlockMarker || lrp["def"].optionalQuantifier) { + complete = true; + for (var i = 0; i <= aml; i++) { + var mask = isMask(i); + if ((mask && (buffer[i] == undefined || buffer[i] == getPlaceholder(i))) || (!mask && buffer[i] != getPlaceholder(i))) { + complete = false; + break; } } - if ($.fn.val.inputmaskpatch != true) { - $.fn.val = function () { - if (arguments.length == 0) { - var $self = $(this); - if ($self.data('inputmask')) { - if ($self.data('inputmask')['autoUnmask']) - return $self.inputmask('unmaskedvalue'); - else { - var result = $.inputmask.val.apply($self); - return result != $self.data('inputmask')['_buffer'].join('') ? result : ''; + } + } + return complete; + } + function isSelection(begin, end) { + return isRTL ? (begin - end) > 1 || ((begin - end) == 1 && opts.insertMode) : + (end - begin) > 1 || ((end - begin) == 1 && opts.insertMode); + } + function installEventRuler(npt) { + var events = $._data(npt).events; + + $.each(events, function (eventType, eventHandlers) { + $.each(eventHandlers, function (ndx, eventHandler) { + if (eventHandler.namespace == "inputmask") { + if (eventHandler.type != "setvalue") { + var handler = eventHandler.handler; + eventHandler.handler = function (e) { + //console.log("triggered " + e.type); + if (this.disabled || (this.readOnly && !(e.type == "keydown" && e.ctrlKey && e.keyCode == 67))) + e.preventDefault(); + else { + switch (e.type) { + case "input": + if (skipInputEvent === true) { + skipInputEvent = false; + return e.preventDefault(); + } + break; + case "keydown": + //Safari 5.1.x - modal dialog fires keypress twice workaround + skipKeyPressEvent = false; + break; + case "keypress": + if (skipKeyPressEvent === true) + return e.preventDefault(); + skipKeyPressEvent = true; + + break; + case "compositionstart": + break; + case "compositionupdate": + skipInputEvent = true; + break; + case "compositionend": + break; } - } else return $.inputmask.val.apply($self); + //console.log("executed " + e.type); + return handler.apply(this, arguments); + } + }; + } + } + }); + }); + } + function patchValueProperty(npt) { + var valueGet; + var valueSet; + function PatchValhook(type) { + if ($.valHooks[type] == undefined || $.valHooks[type].inputmaskpatch != true) { + var valhookGet = $.valHooks[type] && $.valHooks[type].get ? $.valHooks[type].get : function (elem) { return elem.value; }; + var valhookSet = $.valHooks[type] && $.valHooks[type].set ? $.valHooks[type].set : function (elem, value) { + elem.value = value; + return elem; + }; + + $.valHooks[type] = { + get: function (elem) { + var $elem = $(elem); + if ($elem.data('_inputmask')) { + if ($elem.data('_inputmask')['opts'].autoUnmask) + return $elem.inputmask('unmaskedvalue'); + else { + var result = valhookGet(elem), + inputData = $elem.data('_inputmask'), + maskset = inputData['maskset'], + bufferTemplate = maskset['_buffer']; + bufferTemplate = bufferTemplate ? bufferTemplate.join('') : ''; + return result != bufferTemplate ? result : ''; + } + } else return valhookGet(elem); + }, + set: function (elem, value) { + var $elem = $(elem), inputData = $elem.data('_inputmask'), result; + if (inputData) { + result = valhookSet(elem, $.isFunction(inputData['opts'].onBeforeMask) ? (inputData['opts'].onBeforeMask.call(el, value, inputData['opts']) || value) : value); + $elem.triggerHandler('setvalue.inputmask'); } else { - var args = arguments; - return this.each(function () { - var $self = $(this); - var result = $.inputmask.val.apply($self, args); - if ($self.data('inputmask')) $self.triggerHandler('setvalue.inputmask'); - return result; - }); + result = valhookSet(elem, value); } - }; - $.extend($.fn.val, { - inputmaskpatch: true - }); + return result; + }, + inputmaskpatch: true + }; + } + } + function getter() { + var $self = $(this), inputData = $(this).data('_inputmask'); + if (inputData) { + return inputData['opts'].autoUnmask ? $self.inputmask('unmaskedvalue') : (valueGet.call(this) != getBufferTemplate().join('') ? valueGet.call(this) : ''); + } else return valueGet.call(this); + } + function setter(value) { + var inputData = $(this).data('_inputmask'); + if (inputData) { + valueSet.call(this, $.isFunction(inputData['opts'].onBeforeMask) ? (inputData['opts'].onBeforeMask.call(el, value, inputData['opts']) || value) : value); + $(this).triggerHandler('setvalue.inputmask'); + } else { + valueSet.call(this, value); + } + } + function InstallNativeValueSetFallback(npt) { + $(npt).bind("mouseenter.inputmask", function (event) { + var $input = $(this), input = this, value = input._valueGet(); + if (value != "" && value != getBuffer().join('')) { + this._valueSet($.isFunction(opts.onBeforeMask) ? (opts.onBeforeMask.call(el, value, opts) || value) : value); + $input.triggerHandler('setvalue.inputmask'); + } + }); + //!! the bound handlers are executed in the order they where bound + //reorder the events - the mouseenter event is internally mapped to the mouseover event + var events = $._data(npt).events; + var handlers = events["mouseover"]; + if (handlers) { + var ourHandler = handlers[handlers.length - 1]; + for (var i = handlers.length - 1; i > 0; i--) { + handlers[i] = handlers[i - 1]; } + handlers[0] = ourHandler; } } - //shift chars to left from start to end and put c at end position if defined - function shiftL(start, end, c) { - while (!isMask(start) && start - 1 >= 0) start--; - for (var i = start; i < end && i < getMaskLength(); i++) { - if (isMask(i)) { - setReTargetPlaceHolder(buffer, i); - var j = seekNext(buffer, i); - var p = getBufferElement(buffer, j); - if (p != getPlaceHolder(j)) { - if (j < getMaskLength() && isValid(i, p, buffer, true) !== false && tests[determineTestPosition(i)].def == tests[determineTestPosition(j)].def) { - setBufferElement(buffer, i, getBufferElement(buffer, j)); - setReTargetPlaceHolder(buffer, j); //cleanup next position - } else { - if (isMask(i)) - break; + + if (!npt._valueGet) { + //var valueProperty; + if (Object.getOwnPropertyDescriptor) + var valueProperty = Object.getOwnPropertyDescriptor(npt, "value"); + if (valueProperty && valueProperty.configurable && false) { //experimental for chrome + npt._value = valueProperty.value; + valueGet = function () { + return this._value || ""; + } + valueSet = function (value) { + this._value = value; + this.select(); + this.setRangeText(value); + this.selectionStart = this.selectionEnd; + } + + Object.defineProperty(npt, "value", { + get: getter, + set: setter + }); + } else if (document.__lookupGetter__ && npt.__lookupGetter__("value")) { + valueGet = npt.__lookupGetter__("value"); + valueSet = npt.__lookupSetter__("value"); + + npt.__defineGetter__("value", getter); + npt.__defineSetter__("value", setter); + } else { //jquery.val + valueGet = function () { return npt.value; } + valueSet = function (value) { npt.value = value; } + PatchValhook(npt.type); + InstallNativeValueSetFallback(npt); + } + npt._valueGet = function (overruleRTL) { + return isRTL && overruleRTL !== true ? valueGet.call(this).split('').reverse().join('') : valueGet.call(this); + }; + npt._valueSet = function (value) { + valueSet.call(this, isRTL ? value.split('').reverse().join('') : value); + }; + } + } + function handleRemove(input, k, pos, strict) { + function generalize() { + if (opts.keepStatic) { + resetMaskSet(true); + var validInputs = [], + lastAlt; + //find last alternation + for (lastAlt = getLastValidPosition() ; lastAlt >= 0; lastAlt--) { + if (getMaskSet()["validPositions"][lastAlt]) { + if (getMaskSet()["validPositions"][lastAlt].alternation != undefined) { + break; } - } else if (c == undefined) break; - } else { - setReTargetPlaceHolder(buffer, i); + validInputs.push(getMaskSet()["validPositions"][lastAlt].input); + delete getMaskSet()["validPositions"][lastAlt]; + } + } + if (lastAlt > 0) { + while (validInputs.length > 0) { + getMaskSet()["p"] = seekNext(getLastValidPosition()); + var keypress = $.Event("keypress"); + keypress.which = validInputs.pop().charCodeAt(0); + keypressEvent.call(input, keypress, true, false, false, getMaskSet()["p"]); + } } } - if (c != undefined) - setBufferElement(buffer, isRTL ? end : seekPrevious(buffer, end), c); - - buffer = truncateInput(buffer.join(''), isRTL).split(''); - if (buffer.length == 0) buffer = _buffer.slice(); - - return start; //return the used start position - } - function shiftR(start, end, c, full) { //full => behave like a push right ~ do not stop on placeholders - for (var i = start; i <= end && i < getMaskLength(); i++) { - if (isMask(i)) { - var t = getBufferElement(buffer, i); - setBufferElement(buffer, i, c); - if (t != getPlaceHolder(i)) { - var j = seekNext(buffer, i); - if (j < getMaskLength()) { - if (isValid(j, t, buffer, true) !== false && tests[determineTestPosition(i)].def == tests[determineTestPosition(j)].def) - c = t; - else { - if (isMask(j)) - break; - else c = t; - } - } else break; - } else if (full !== true) break; - } else - setReTargetPlaceHolder(buffer, i); + } + + if (opts.numericInput || isRTL) { + if (k == $.inputmask.keyCode.BACKSPACE) + k = $.inputmask.keyCode.DELETE; + else if (k == $.inputmask.keyCode.DELETE) + k = $.inputmask.keyCode.BACKSPACE; + + if (isRTL) { + var pend = pos.end; + pos.end = pos.begin; + pos.begin = pend; } - var lengthBefore = buffer.length; - buffer = truncateInput(buffer.join(''), isRTL).split(''); - if (buffer.length == 0) buffer = _buffer.slice(); + } - return end - (lengthBefore - buffer.length); //return new start position - }; + if (k == $.inputmask.keyCode.BACKSPACE && (pos.end - pos.begin < 1 || opts.insertMode == false)) + pos.begin = seekPrevious(pos.begin); + else if (k == $.inputmask.keyCode.DELETE && pos.begin == pos.end) + pos.end++; - function keydownEvent(e) { - //Safari 5.1.x - modal dialog fires keypress twice workaround - skipKeyPressEvent = false; + stripValidPositions(pos.begin, pos.end, false, strict); + if (strict !== true) { + generalize(); //revert the alternation + + var lvp = getLastValidPosition(pos.begin); + if (lvp < pos.begin) { + if (lvp == -1) resetMaskSet(); + getMaskSet()["p"] = seekNext(lvp); + } else { + getMaskSet()["p"] = pos.begin; + } + } + } + //postprocessing of the validpositions according to the buffer manipulations + function handleOnKeyResult(input, keyResult, caretPos) { + if (keyResult && keyResult["refreshFromBuffer"]) { + var refresh = keyResult["refreshFromBuffer"]; + refreshFromBuffer(refresh === true ? refresh : refresh["start"], refresh["end"], keyResult["buffer"]); + + resetMaskSet(true); + if (caretPos != undefined) { + writeBuffer(input, getBuffer()); + caret(input, keyResult.caret || caretPos.begin, keyResult.caret || caretPos.end); + } + } + } + function keydownEvent(e) { + var input = this, $input = $(input), k = e.keyCode, pos = caret(input); + + //backspace, delete, and escape get special treatment + if (k == $.inputmask.keyCode.BACKSPACE || k == $.inputmask.keyCode.DELETE || (iphone && k == 127) || (e.ctrlKey && k == 88 && !isInputEventSupported("cut"))) { //backspace/delete + e.preventDefault(); //stop default action but allow propagation + if (k == 88) undoValue = getBuffer().join(''); + handleRemove(input, k, pos); + writeBuffer(input, getBuffer(), getMaskSet()["p"], e, undoValue != getBuffer().join('')); + if (input._valueGet() == getBufferTemplate().join('')) + $input.trigger('cleared'); + else if (isComplete(getBuffer()) === true) + $input.trigger("complete"); + if (opts.showTooltip) { //update tooltip + $input.prop("title", getMaskSet()["mask"]); + } + } else if (k == $.inputmask.keyCode.END || k == $.inputmask.keyCode.PAGE_DOWN) { //when END or PAGE_DOWN pressed set position at lastmatch + setTimeout(function () { + var caretPos = seekNext(getLastValidPosition()); + if (!opts.insertMode && caretPos == getMaskLength() && !e.shiftKey) caretPos--; + caret(input, e.shiftKey ? pos.begin : caretPos, caretPos); + }, 0); + } else if ((k == $.inputmask.keyCode.HOME && !e.shiftKey) || k == $.inputmask.keyCode.PAGE_UP) { //Home or page_up + caret(input, 0, e.shiftKey ? pos.begin : 0); + } else if ((opts.undoOnEscape && k == $.inputmask.keyCode.ESCAPE) || (k == 90 && e.ctrlKey)) { //escape && undo + checkVal(input, true, false, undoValue.split('')); + $input.click(); + } else if (k == $.inputmask.keyCode.INSERT && !(e.shiftKey || e.ctrlKey)) { //insert + opts.insertMode = !opts.insertMode; + caret(input, !opts.insertMode && pos.begin == getMaskLength() ? pos.begin - 1 : pos.begin); + } else if (opts.insertMode == false && !e.shiftKey) { + if (k == $.inputmask.keyCode.RIGHT) { + setTimeout(function () { + var caretPos = caret(input); + caret(input, caretPos.begin); + }, 0); + } else if (k == $.inputmask.keyCode.LEFT) { + setTimeout(function () { + var caretPos = caret(input); + caret(input, isRTL ? caretPos.begin + 1 : caretPos.begin - 1); + }, 0); + } + } - var input = this, k = e.keyCode, pos = caret(input); + ignorable = $.inArray(k, opts.ignorables) != -1; + } + function keypressEvent(e, checkval, writeOut, strict, ndx) { + var input = this, $input = $(input); - //set input direction according the position to the radixPoint - if (opts.numericInput) { - var nptStr = input._valueGet(); - var radixPosition = nptStr.indexOf(opts.radixPoint); - if (radixPosition != -1) { - isRTL = pos.begin <= radixPosition || pos.end <= radixPosition; + var k = e.which || e.charCode || e.keyCode; + if (checkval !== true && (!(e.ctrlKey && e.altKey) && (e.ctrlKey || e.metaKey || ignorable))) { + return true; + } else { + if (k) { + //special treat the decimal separator + if (k == 46 && e.shiftKey == false && opts.radixPoint == ",") k = 44; + var pos = checkval ? { begin: ndx, end: ndx } : caret(input), forwardPosition, c = String.fromCharCode(k); + + //should we clear a possible selection?? + var isSlctn = isSelection(pos.begin, pos.end); + if (isSlctn) { + getMaskSet()["undoPositions"] = $.extend(true, {}, getMaskSet()["validPositions"]); //init undobuffer for recovery when not valid + handleRemove(input, $.inputmask.keyCode.DELETE, pos, true); + pos.begin = getMaskSet()["p"]; + if (!opts.insertMode) { //preserve some space + opts.insertMode = !opts.insertMode; + setValidPosition(pos.begin, strict); + opts.insertMode = !opts.insertMode; + } + isSlctn = !opts.multi; } - } - //backspace, delete, and escape get special treatment - if (k == opts.keyCode.BACKSPACE || k == opts.keyCode.DELETE || (iphone && k == 127)) {//backspace/delete - var maskL = getMaskLength(); - if (pos.begin == 0 && pos.end == maskL) { - buffer = _buffer.slice(); - writeBuffer(input, buffer); - caret(input, checkVal(input, buffer, false)); - } else if ((pos.end - pos.begin) > 1 || ((pos.end - pos.begin) == 1 && opts.insertMode)) { - clearBuffer(buffer, pos.begin, pos.end); - writeBuffer(input, buffer, isRTL ? checkVal(input, buffer, false) : pos.begin); - } else { - var beginPos = pos.begin - (k == opts.keyCode.DELETE ? 0 : 1); - if (beginPos < firstMaskPos && k == opts.keyCode.DELETE) { - beginPos = firstMaskPos; + getMaskSet()["writeOutBuffer"] = true; + var p = isRTL && !isSlctn ? pos.end : pos.begin; + var valResult = isValid(p, c, strict); + if (valResult !== false) { + if (valResult !== true) { + p = valResult.pos != undefined ? valResult.pos : p; //set new position from isValid + c = valResult.c != undefined ? valResult.c : c; //set new char from isValid } - if (beginPos >= firstMaskPos) { - if (opts.numericInput && opts.greedy && k == opts.keyCode.DELETE && buffer[beginPos] == opts.radixPoint) { - beginPos = seekNext(buffer, beginPos); - isRTL = false; + resetMaskSet(true); + if (valResult.caret != undefined) + forwardPosition = valResult.caret; + else { + var vps = getMaskSet()["validPositions"]; + if (!opts.keepStatic && (vps[p + 1] != undefined && getTests(p + 1, vps[p].locator.slice(), p).length > 1 || vps[p].alternation != undefined)) + forwardPosition = p + 1; + else + forwardPosition = seekNext(p); + } + getMaskSet()["p"] = forwardPosition; //needed for checkval + } + + if (writeOut !== false) { + var self = this; + setTimeout(function () { opts.onKeyValidation.call(self, valResult, opts); }, 0); + if (getMaskSet()["writeOutBuffer"] && valResult !== false) { + var buffer = getBuffer(); + writeBuffer(input, buffer, checkval ? undefined : opts.numericInput ? seekPrevious(forwardPosition) : forwardPosition, e, checkval !== true); + if (checkval !== true) { + setTimeout(function () { //timeout needed for IE + if (isComplete(buffer) === true) + $input.trigger("complete"); + }, 0); } - if (isRTL) { - beginPos = shiftR(firstMaskPos, beginPos, getPlaceHolder(beginPos), true); - beginPos = (opts.numericInput && opts.greedy && k == opts.keyCode.BACKSPACE && buffer[beginPos + 1] == opts.radixPoint) ? beginPos + 1 : seekNext(buffer, beginPos); - } else beginPos = shiftL(beginPos, maskL); - writeBuffer(input, buffer, beginPos); + } else if (isSlctn) { + getMaskSet()["buffer"] = undefined; + getMaskSet()["validPositions"] = getMaskSet()["undoPositions"]; } + } else if (isSlctn) { + getMaskSet()["buffer"] = undefined; + getMaskSet()["validPositions"] = getMaskSet()["undoPositions"]; } - if (input._valueGet() == _buffer.join('')) - $(input).trigger('cleared'); - return false; - } else if (k == opts.keyCode.END || k == opts.keyCode.PAGE_DOWN) { //when END or PAGE_DOWN pressed set position at lastmatch - setTimeout(function () { - var caretPos = checkVal(input, buffer, false, true); - if (!opts.insertMode && caretPos == getMaskLength() && !e.shiftKey) caretPos--; - caret(input, e.shiftKey ? pos.begin : caretPos, caretPos); - }, 0); - return false; - } else if (k == opts.keyCode.HOME || k == opts.keyCode.PAGE_UP) {//Home or page_up - caret(input, 0, e.shiftKey ? pos.begin : 0); - return false; - } - else if (k == opts.keyCode.ESCAPE) {//escape - input._valueSet(undoBuffer); - caret(input, 0, checkVal(input, buffer)); - return false; - } else if (k == opts.keyCode.INSERT) {//insert - opts.insertMode = !opts.insertMode; - caret(input, !opts.insertMode && pos.begin == getMaskLength() ? pos.begin - 1 : pos.begin); - return false; - } else if (e.ctrlKey && k == 88) { - setTimeout(function () { - caret(input, checkVal(input, buffer, true)); - }, 0); - } else if (!opts.insertMode) { //overwritemode - if (k == opts.keyCode.RIGHT) {//right - var caretPos = pos.begin == pos.end ? pos.end + 1 : pos.end; - caretPos = caretPos < getMaskLength() ? caretPos : pos.end; - caret(input, e.shiftKey ? pos.begin : caretPos, e.shiftKey ? caretPos + 1 : caretPos); - return false; - } else if (k == opts.keyCode.LEFT) {//left - var caretPos = pos.begin - 1; - caretPos = caretPos > 0 ? caretPos : 0; - caret(input, caretPos, e.shiftKey ? pos.end : caretPos); - return false; + if (opts.showTooltip) { //update tooltip + $input.prop("title", getMaskSet()["mask"]); } - } - opts.onKeyDown.call(this, e, opts); //extra stuff to execute on keydown - ignorable = $.inArray(k, opts.ignorables) != -1; + if (checkval && $.isFunction(opts.onBeforeWrite)) { + var result = opts.onBeforeWrite.call(this, e, getBuffer(), forwardPosition, opts); + if (result && result["refreshFromBuffer"]) { + var refresh = result["refreshFromBuffer"]; + refreshFromBuffer(refresh === true ? refresh : refresh["start"], refresh["end"], result["buffer"]); + + resetMaskSet(true); + if (result.caret) { + getMaskSet()["p"] = result.caret; + } + } + } + e.preventDefault(); + } } + } + function keyupEvent(e) { + var $input = $(this), input = this, k = e.keyCode, buffer = getBuffer(); + opts.onKeyUp.call(this, e, buffer, opts); + } + function pasteEvent(e) { + var input = this, $input = $(input), inputValue = input._valueGet(true), caretPos = caret(input); + //paste event for IE8 and lower I guess ;-) + if (e.type == "propertychange" && input._valueGet().length <= getMaskLength()) { + return true; + } else if (e.type == "paste") { + var valueBeforeCaret = inputValue.substr(0, caretPos.begin), + valueAfterCaret = inputValue.substr(caretPos.end, inputValue.length); - function keypressEvent(e) { - //Safari 5.1.x - modal dialog fires keypress twice workaround - if (skipKeyPressEvent) return false; - skipKeyPressEvent = true; + if (valueBeforeCaret == getBufferTemplate().slice(0, caretPos.begin).join('')) valueBeforeCaret = ""; + if (valueAfterCaret == getBufferTemplate().slice(caretPos.end).join('')) valueAfterCaret = ""; + + if (window.clipboardData && window.clipboardData.getData) { // IE + inputValue = valueBeforeCaret + window.clipboardData.getData('Text') + valueAfterCaret; + } else if (e.originalEvent && e.originalEvent.clipboardData && e.originalEvent.clipboardData.getData) { + inputValue = valueBeforeCaret + e.originalEvent.clipboardData.getData('text/plain') + valueAfterCaret; + } + } - var input = this, $input = $(input); + var pasteValue = $.isFunction(opts.onBeforePaste) ? (opts.onBeforePaste.call(input, inputValue, opts) || inputValue) : inputValue; + checkVal(input, true, false, isRTL ? pasteValue.split('').reverse() : pasteValue.split('')); + $input.click(); + if (isComplete(getBuffer()) === true) + $input.trigger("complete"); - e = e || window.event; - var k = e.which || e.charCode || e.keyCode; + return false; + } + //function mobileInputEvent(e) { + // var input = this; + + // //backspace in chrome32 only fires input event - detect & treat + // var caretPos = caret(input), + // currentValue = input._valueGet(); + + // currentValue = currentValue.replace(new RegExp("(" + escapeRegex(getBufferTemplate().join('')) + ")*"), ""); + // //correct caretposition for chrome + // if (caretPos.begin > currentValue.length) { + // caret(input, currentValue.length); + // caretPos = caret(input); + // } + // if ((getBuffer().length - currentValue.length) == 1 && currentValue.charAt(caretPos.begin) != getBuffer()[caretPos.begin] + // && currentValue.charAt(caretPos.begin + 1) != getBuffer()[caretPos.begin] + // && !isMask(caretPos.begin)) { + // e.keyCode = $.inputmask.keyCode.BACKSPACE; + // keydownEvent.call(input, e); + // } + // e.preventDefault(); + //} + function inputFallBackEvent(e) { //fallback when keypress & compositionevents fail + var input = this; + checkVal(input, true, false); + + if (isComplete(getBuffer()) === true) + $(input).trigger("complete"); + + e.preventDefault(); + } + function compositionStartEvent(e) { + var input = this; + undoValue = getBuffer().join(''); + if (compositionData == "" || e.originalEvent.data.indexOf(compositionData) != 0) { + compositionCaretPos = caret(input); + } + } + function compositionUpdateEvent(e) { + var input = this, caretPos = compositionCaretPos || caret(input); + if (e.originalEvent.data.indexOf(compositionData) == 0) { + resetMaskSet(); + caretPos = { begin: 0, end: 0 }; + } + var newData = e.originalEvent.data; + caret(input, caretPos.begin, caretPos.end); + for (var i = 0; i < newData.length; i++) { + var keypress = $.Event("keypress"); + keypress.which = newData.charCodeAt(i); + skipKeyPressEvent = false; + ignorable = false; + keypressEvent.call(input, keypress); //needs update + } + setTimeout(function () { + var forwardPosition = getMaskSet()["p"]; + writeBuffer(input, getBuffer(), opts.numericInput ? seekPrevious(forwardPosition) : forwardPosition); + }, 0); + compositionData = e.originalEvent.data; + } + function compositionEndEvent(e) { + //pickup by inputfallback + } + function mask(el) { + $el = $(el); + if ($el.is(":input") && isInputTypeSupported($el.attr("type"))) { + //store tests & original buffer in the input element - used to get the unmasked value + $el.data('_inputmask', { + 'maskset': maskset, + 'opts': opts, + 'isRTL': false + }); - if (opts.numericInput && k == opts.radixPoint.charCodeAt(opts.radixPoint.length - 1)) { - var nptStr = input._valueGet(); - var radixPosition = nptStr.indexOf(opts.radixPoint); - caret(input, seekNext(buffer, radixPosition != -1 ? radixPosition : getMaskLength())); + //show tooltip + if (opts.showTooltip) { + $el.prop("title", getMaskSet()["mask"]); } - if (e.ctrlKey || e.altKey || e.metaKey || ignorable) {//Ignore - return true; - } else { - if (k) { - $input.trigger('input'); - - var pos = caret(input), c = String.fromCharCode(k), maskL = getMaskLength(); - clearBuffer(buffer, pos.begin, pos.end); - - if (isRTL) { - var p = opts.numericInput ? pos.end : seekPrevious(buffer, pos.end), np; - if ((np = isValid(p == maskL || getBufferElement(buffer, p) == opts.radixPoint ? seekPrevious(buffer, p) : p, c, buffer, false)) !== false) { - if (np !== true) { - p = np.pos || pos; //set new position from isValid - c = np.c || c; //set new char from isValid - } + if (el.dir == "rtl" || opts.rightAlign) + $el.css("text-align", "right"); - var firstUnmaskedPosition = firstMaskPos; - if (opts.insertMode == true) { - if (opts.greedy == true) { - var bfrClone = buffer.slice(); - while (getBufferElement(bfrClone, firstUnmaskedPosition, true) != getPlaceHolder(firstUnmaskedPosition) && firstUnmaskedPosition <= p) { - firstUnmaskedPosition = firstUnmaskedPosition == maskL ? (maskL + 1) : seekNext(buffer, firstUnmaskedPosition); - } - } + if (el.dir == "rtl" || opts.numericInput) { + el.dir = "ltr"; + $el.removeAttr("dir"); + var inputData = $el.data('_inputmask'); + inputData['isRTL'] = true; + $el.data('_inputmask', inputData); + isRTL = true; + } - if (firstUnmaskedPosition <= p && (opts.greedy || buffer.length < maskL)) { - if (buffer[firstMaskPos] != getPlaceHolder(firstMaskPos) && buffer.length < maskL) { - var offset = prepareBuffer(buffer, -1, isRTL); - if (pos.end != 0) p = p + offset; - maskL = buffer.length; - } - shiftL(firstUnmaskedPosition, opts.numericInput ? seekPrevious(buffer, p) : p, c); - } else return false; - } else setBufferElement(buffer, opts.numericInput ? seekPrevious(buffer, p) : p, c); - writeBuffer(input, buffer, opts.numericInput && p == 0 ? seekNext(buffer, p) : p); - setTimeout(function () { //timeout needed for IE - if (isComplete(input)) - $input.trigger("complete"); - }, 0); - } else if (android) writeBuffer(input, buffer, pos.begin); + //unbind all events - to make sure that no other mask will interfere when re-masking + $el.unbind(".inputmask"); + //bind events + $el.closest('form').bind("submit", function (e) { //trigger change on submit if any + if (undoValue != getBuffer().join('')) { + $el.change(); + } + if ($el[0]._valueGet && $el[0]._valueGet() == getBufferTemplate().join('')) { + $el[0]._valueSet(''); //clear masktemplete on submit and still has focus + } + if (opts.removeMaskOnSubmit) { + $el.inputmask("remove"); + } + }).bind('reset', function () { + setTimeout(function () { + $el.triggerHandler('setvalue.inputmask'); + }, 0); + }); + $el.bind("mouseenter.inputmask", function () { + var $input = $(this), input = this; + if (!$input.is(":focus") && opts.showMaskOnHover) { + if (input._valueGet() != getBuffer().join('')) { + writeBuffer(input, getBuffer()); } - else { - var p = seekNext(buffer, pos.begin - 1), np; - prepareBuffer(buffer, p, isRTL); - if ((np = isValid(p, c, buffer, false)) !== false) { - if (np !== true) { - p = np.pos || p; //set new position from isValid - c = np.c || c; //set new char from isValid + } + }).bind("blur.inputmask", function (e) { + var $input = $(this), input = this; + if ($input.data('_inputmask')) { + var nptValue = input._valueGet(), buffer = getBuffer().slice(); + firstClick = true; + if (undoValue != buffer.join('')) { + $input.change(); + undoValue = buffer.join(''); + } + if (nptValue != '') { + if (opts.clearMaskOnLostFocus) { + if (nptValue == getBufferTemplate().join('')) + buffer = []; + else { //clearout optional tail of the mask + clearOptionalTail(buffer); } - if (opts.insertMode == true) { - var lastUnmaskedPosition = getMaskLength(); - var bfrClone = buffer.slice(); - while (getBufferElement(bfrClone, lastUnmaskedPosition, true) != getPlaceHolder(lastUnmaskedPosition) && lastUnmaskedPosition >= p) { - lastUnmaskedPosition = lastUnmaskedPosition == 0 ? -1 : seekPrevious(buffer, lastUnmaskedPosition); + } + if (isComplete(buffer) === false) { + $input.trigger("incomplete"); + if (opts.clearIncomplete) { + resetMaskSet(); + if (opts.clearMaskOnLostFocus) + buffer = []; + else { + buffer = getBufferTemplate().slice(); + } - if (lastUnmaskedPosition >= p) - shiftR(p, buffer.length, c); - else return false; } - else setBufferElement(buffer, p, c); - var next = seekNext(buffer, p); - writeBuffer(input, buffer, next); + } - setTimeout(function () { //timeout needed for IE - if (isComplete(input)) - $input.trigger("complete"); - }, 0); - } else if (android) writeBuffer(input, buffer, pos.begin); + writeBuffer(input, buffer, undefined, e); + } + } + }).bind("focus.inputmask", function (e) { + var $input = $(this), input = this, nptValue = input._valueGet(); + if (opts.showMaskOnFocus && (!opts.showMaskOnHover || (opts.showMaskOnHover && nptValue == ''))) { + if (input._valueGet() != getBuffer().join('')) { + writeBuffer(input, getBuffer(), seekNext(getLastValidPosition())); } - return false; } + undoValue = getBuffer().join(''); + }).bind("mouseleave.inputmask", function () { + var $input = $(this), input = this; + if (opts.clearMaskOnLostFocus) { + var buffer = getBuffer().slice(), nptValue = input._valueGet(); + if (!$input.is(":focus") && nptValue != $input.attr("placeholder") && nptValue != '') { + if (nptValue == getBufferTemplate().join('')) + buffer = []; + else { //clearout optional tail of the mask + clearOptionalTail(buffer); + } + writeBuffer(input, buffer); + } + } + }).bind("click.inputmask", function () { + var $input = $(this), input = this; + if ($input.is(":focus")) { + var selectedCaret = caret(input); + if (selectedCaret.begin == selectedCaret.end) { + if (opts.radixFocus && opts.radixPoint != "" && $.inArray(opts.radixPoint, getBuffer()) != -1 && (firstClick || getBuffer().join('') == getBufferTemplate().join(''))) { + caret(input, $.inArray(opts.radixPoint, getBuffer())); + firstClick = false; + } else { + var clickPosition = isRTL ? TranslatePosition(selectedCaret.begin) : selectedCaret.begin, + lastPosition = seekNext(getLastValidPosition(clickPosition)); + if (clickPosition < lastPosition) { + caret(input, isMask(clickPosition) ? clickPosition : seekNext(clickPosition)); + } else { + caret(input, lastPosition); + } + } + } + } + }).bind('dblclick.inputmask', function () { + var input = this; + setTimeout(function () { + caret(input, 0, seekNext(getLastValidPosition())); + }, 0); + }).bind(PasteEventType + ".inputmask dragdrop.inputmask drop.inputmask", pasteEvent + ).bind('setvalue.inputmask', function () { + var input = this; + checkVal(input, true, false); + undoValue = getBuffer().join(''); + if ((opts.clearMaskOnLostFocus || opts.clearIncomplete) && input._valueGet() == getBufferTemplate().join('')) + input._valueSet(''); + }).bind('cut.inputmask', function (e) { + skipInputEvent = true; //stop inputFallback + var input = this, $input = $(input), pos = caret(input); + + handleRemove(input, $.inputmask.keyCode.DELETE, pos); + writeBuffer(input, getBuffer(), getMaskSet()["p"], e, undoValue != getBuffer().join('')); + + if (input._valueGet() == getBufferTemplate().join('')) + $input.trigger('cleared'); + + if (opts.showTooltip) { //update tooltip + $input.prop("title", getMaskSet()["mask"]); + } + }).bind('complete.inputmask', opts.oncomplete + ).bind('incomplete.inputmask', opts.onincomplete + ).bind('cleared.inputmask', opts.oncleared); + + $el.bind("keydown.inputmask", keydownEvent + ).bind("keypress.inputmask", keypressEvent + ).bind("keyup.inputmask", keyupEvent); + + if (!androidfirefox) { + $el.bind("compositionstart.inputmask", compositionStartEvent + ).bind("compositionupdate.inputmask", compositionUpdateEvent + ).bind("compositionend.inputmask", compositionEndEvent); } + + if (PasteEventType === "paste") { + $el.bind("input.inputmask", inputFallBackEvent); + } + + //if (android || androidfirefox || androidchrome || kindle) { + // $el.unbind("input.inputmask"); + // $el.bind("input.inputmask", mobileInputEvent); + //} + + patchValueProperty(el); + + //apply mask + var initialValue = $.isFunction(opts.onBeforeMask) ? (opts.onBeforeMask.call(el, el._valueGet(), opts) || el._valueGet()) : el._valueGet(); + checkVal(el, true, false, initialValue.split('')); + var buffer = getBuffer().slice(); + undoValue = buffer.join(''); + // Wrap document.activeElement in a try/catch block since IE9 throw "Unspecified error" if document.activeElement is undefined when we are in an IFrame. + var activeElement; + try { + activeElement = document.activeElement; + } catch (e) { + } + if (isComplete(buffer) === false) { + if (opts.clearIncomplete) + resetMaskSet(); + } + if (opts.clearMaskOnLostFocus) { + if (buffer.join('') == getBufferTemplate().join('')) { + buffer = []; + } else { + clearOptionalTail(buffer); + } + } + writeBuffer(el, buffer); + if (activeElement === el) { //position the caret when in focus + caret(el, seekNext(getLastValidPosition())); + } + + installEventRuler(el); + } + } + + //action object + if (actionObj != undefined) { + switch (actionObj["action"]) { + case "isComplete": + $el = $(actionObj["el"]); + maskset = $el.data('_inputmask')['maskset']; + opts = $el.data('_inputmask')['opts']; + return isComplete(actionObj["buffer"]); + case "unmaskedvalue": + $el = actionObj["$input"]; + maskset = $el.data('_inputmask')['maskset']; + opts = $el.data('_inputmask')['opts']; + isRTL = actionObj["$input"].data('_inputmask')['isRTL']; + return unmaskedvalue(actionObj["$input"]); + case "mask": + undoValue = getBuffer().join(''); + mask(actionObj["el"]); + break; + case "format": + $el = $({}); + $el.data('_inputmask', { + 'maskset': maskset, + 'opts': opts, + 'isRTL': opts.numericInput + }); + if (opts.numericInput) { + isRTL = true; + } + var valueBuffer = ($.isFunction(opts.onBeforeMask) ? (opts.onBeforeMask.call($el, actionObj["value"], opts) || actionObj["value"]) : actionObj["value"]).split(''); + checkVal($el, false, false, isRTL ? valueBuffer.reverse() : valueBuffer); + $.isFunction(opts.onBeforeWrite) && opts.onBeforeWrite.call(this, undefined, getBuffer(), 0, opts); + + if (actionObj["metadata"]) { + return { + value: isRTL ? getBuffer().slice().reverse().join('') : getBuffer().join(''), + metadata: $el.inputmask("getmetadata") + } + } + + return isRTL ? getBuffer().slice().reverse().join('') : getBuffer().join(''); + case "isValid": + $el = $({}); + $el.data('_inputmask', { + 'maskset': maskset, + 'opts': opts, + 'isRTL': opts.numericInput + }); + if (opts.numericInput) { + isRTL = true; + } + var valueBuffer = actionObj["value"].split(''); + checkVal($el, false, true, isRTL ? valueBuffer.reverse() : valueBuffer); + var buffer = getBuffer(); + var rl = determineLastRequiredPosition(), lmib = buffer.length - 1; + for (; lmib > rl; lmib--) { + if (isMask(lmib)) break; + } + buffer.splice(rl, lmib + 1 - rl); + + return isComplete(buffer) && actionObj["value"] == buffer.join(''); + case "getemptymask": + $el = $(actionObj["el"]); + maskset = $el.data('_inputmask')['maskset']; + opts = $el.data('_inputmask')['opts']; + return getBufferTemplate(); + case "remove": + var el = actionObj["el"]; + $el = $(el); + maskset = $el.data('_inputmask')['maskset']; + opts = $el.data('_inputmask')['opts']; + //writeout the unmaskedvalue + el._valueSet(unmaskedvalue($el)); + //unbind all events + $el.unbind(".inputmask"); + //clear data + $el.removeData('_inputmask'); + //restore the value property + var valueProperty; + if (Object.getOwnPropertyDescriptor) + valueProperty = Object.getOwnPropertyDescriptor(el, "value"); + if (valueProperty && valueProperty.get) { + if (el._valueGet) { + Object.defineProperty(el, "value", { + get: el._valueGet, + set: el._valueSet + }); + } + } else if (document.__lookupGetter__ && el.__lookupGetter__("value")) { + if (el._valueGet) { + el.__defineGetter__("value", el._valueGet); + el.__defineSetter__("value", el._valueSet); + } + } + try { //try catch needed for IE7 as it does not supports deleting fns + delete el._valueGet; + delete el._valueSet; + } catch (e) { + el._valueGet = undefined; + el._valueSet = undefined; + + } + break; + case "getmetadata": + $el = $(actionObj["el"]); + maskset = $el.data('_inputmask')['maskset']; + opts = $el.data('_inputmask')['opts']; + if ($.isArray(maskset["metadata"])) { + //find last alternation + var alternation, lvp = getLastValidPosition(); + for (var firstAlt = lvp; firstAlt >= 0; firstAlt--) { + if (getMaskSet()["validPositions"][firstAlt] && getMaskSet()["validPositions"][firstAlt].alternation != undefined) { + alternation = getMaskSet()["validPositions"][firstAlt].alternation; + break; + } + } + if (alternation != undefined) { + return maskset["metadata"][getMaskSet()["validPositions"][lvp].locator[alternation]]; + } else return maskset["metadata"][0]; + } + + return maskset["metadata"]; } + } + } + + $.inputmask = { + //options default + defaults: { + placeholder: "_", + optionalmarker: { start: "[", end: "]" }, + quantifiermarker: { start: "{", end: "}" }, + groupmarker: { start: "(", end: ")" }, + alternatormarker: "|", + escapeChar: "\\", + mask: null, + oncomplete: $.noop, //executes when the mask is complete + onincomplete: $.noop, //executes when the mask is incomplete and focus is lost + oncleared: $.noop, //executes when the mask is cleared + repeat: 0, //repetitions of the mask: * ~ forever, otherwise specify an integer + greedy: true, //true: allocated buffer for the mask and repetitions - false: allocate only if needed + autoUnmask: false, //automatically unmask when retrieving the value with $.fn.val or value if the browser supports __lookupGetter__ or getOwnPropertyDescriptor + removeMaskOnSubmit: false, //remove the mask before submitting the form. + clearMaskOnLostFocus: true, + insertMode: true, //insert the input or overwrite the input + clearIncomplete: false, //clear the incomplete input on blur + aliases: {}, //aliases definitions => see jquery.inputmask.extensions.js + alias: null, + onKeyUp: $.noop, //callback to implement autocomplete on certain keys for example + onBeforeMask: undefined, //executes before masking the initial value to allow preprocessing of the initial value. args => initialValue, opts => return processedValue + onBeforePaste: undefined, //executes before masking the pasted value to allow preprocessing of the pasted value. args => pastedValue, opts => return processedValue + onBeforeWrite: undefined, //executes before writing to the masked element. args => event, opts + onUnMask: undefined, //executes after unmasking to allow postprocessing of the unmaskedvalue. args => maskedValue, unmaskedValue, opts + showMaskOnFocus: true, //show the mask-placeholder when the input has focus + showMaskOnHover: true, //show the mask-placeholder when hovering the empty input + onKeyValidation: $.noop, //executes on every key-press with the result of isValid. Params: result, opts + skipOptionalPartCharacter: " ", //a character which can be used to skip an optional part of a mask + showTooltip: false, //show the activemask as tooltip + numericInput: false, //numericInput input direction style (input shifts to the left while holding the caret position) + rightAlign: false, //align to the right + undoOnEscape: true, //pressing escape reverts the value to the value before focus + //numeric basic properties + radixPoint: "", //".", // | "," + radixFocus: false, //position caret to radixpoint on initial click + //numeric basic properties + nojumps: false, //do not jump over fixed parts in the mask + nojumpsThreshold: 0, //start nojumps as of + keepStatic: undefined, //try to keep the mask static while typing. Decisions to alter the mask will be posponed if possible - undefined see auto selection for multi masks + definitions: { + '9': { + validator: "[0-9]", + cardinality: 1, + definitionSymbol: "*" + }, + 'a': { + validator: "[A-Za-z\u0410-\u044F\u0401\u0451\u00C0-\u00FF\u00B5]", + cardinality: 1, + definitionSymbol: "*" + }, + '*': { + validator: "[0-9A-Za-z\u0410-\u044F\u0401\u0451\u00C0-\u00FF\u00B5]", + cardinality: 1 + } + }, + //specify keyCodes which should not be considered in the keypress event, otherwise the preventDefault will stop their default behavior especially in FF + ignorables: [8, 9, 13, 19, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 93, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123], + isComplete: undefined, //override for isComplete - args => buffer, opts - return true || false + canClearPosition: $.noop //hook to alter the clear behavior in the stripValidPositions args => maskset, position, lastValidPosition, opts => return true|false + }, + keyCode: { + ALT: 18, BACKSPACE: 8, CAPS_LOCK: 20, COMMA: 188, COMMAND: 91, COMMAND_LEFT: 91, COMMAND_RIGHT: 93, CONTROL: 17, DELETE: 46, DOWN: 40, END: 35, ENTER: 13, ESCAPE: 27, HOME: 36, INSERT: 45, LEFT: 37, MENU: 93, NUMPAD_ADD: 107, NUMPAD_DECIMAL: 110, NUMPAD_DIVIDE: 111, NUMPAD_ENTER: 108, + NUMPAD_MULTIPLY: 106, NUMPAD_SUBTRACT: 109, PAGE_DOWN: 34, PAGE_UP: 33, PERIOD: 190, RIGHT: 39, SHIFT: 16, SPACE: 32, TAB: 9, UP: 38, WINDOWS: 91 + }, + masksCache: {}, + escapeRegex: function (str) { + var specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^']; + return str.replace(new RegExp('(\\' + specials.join('|\\') + ')', 'gim'), '\\$1'); + }, + format: function (value, options, metadata) { + var opts = $.extend(true, {}, $.inputmask.defaults, options); + resolveAlias(opts.alias, options, opts); + return maskScope({ "action": "format", "value": value, "metadata": metadata }, generateMaskSet(opts), opts); + }, + isValid: function (value, options) { + var opts = $.extend(true, {}, $.inputmask.defaults, options); + resolveAlias(opts.alias, options, opts); + return maskScope({ "action": "isValid", "value": value }, generateMaskSet(opts), opts); + } + }; - function keyupEvent(e) { - var $input = $(this), input = this; - var k = e.keyCode; - opts.onKeyUp.call(this, e, opts); //extra stuff to execute on keyup - if (k == opts.keyCode.TAB && $input.hasClass('focus.inputmask') && input._valueGet().length == 0) { - buffer = _buffer.slice(); - writeBuffer(input, buffer); - if (!isRTL) caret(input, 0); - undoBuffer = input._valueGet(); + $.fn.inputmask = function (fn, options) { + function importAttributeOptions(npt, opts, importedOptionsContainer) { + var $npt = $(npt); + if ($npt.data("inputmask-alias")) { + resolveAlias($npt.data("inputmask-alias"), {}, opts); + } + for (var option in opts) { + var optionData = $npt.data("inputmask-" + option.toLowerCase()); + if (optionData != undefined) { + if (option == "mask" && optionData.indexOf("[") == 0) { + opts[option] = optionData.replace(/[\s[\]]/g, "").split("','"); + opts[option][0] = opts[option][0].replace("'", ""); + opts[option][opts[option].length - 1] = opts[option][opts[option].length - 1].replace("'", ""); + } else + opts[option] = typeof optionData == "boolean" ? optionData : optionData.toString(); + if (importedOptionsContainer) + importedOptionsContainer[option] = opts[option]; } } + return opts; + } + var opts = $.extend(true, {}, $.inputmask.defaults, options), + maskset; + + if (typeof fn === "string") { + switch (fn) { + case "mask": + //resolve possible aliases given by options + resolveAlias(opts.alias, options, opts); + maskset = generateMaskSet(opts); + if (maskset == undefined) { return this; } + + return this.each(function () { + maskScope({ "action": "mask", "el": this }, $.extend(true, {}, maskset), importAttributeOptions(this, opts)); + }); + case "unmaskedvalue": + var $input = $(this); + if ($input.data("_inputmask")) { + return maskScope({ "action": "unmaskedvalue", "$input": $input }); + } else return $input.val(); + case "remove": + return this.each(function () { + var $input = $(this); + if ($input.data("_inputmask")) { + maskScope({ "action": "remove", "el": this }); + } + }); + case "getemptymask": //return the default (empty) mask value, usefull for setting the default value in validation + if (this.data("_inputmask")) { + return maskScope({ "action": "getemptymask", "el": this }); + } + else return ""; + case "hasMaskedValue": //check wheter the returned value is masked or not; currently only works reliable when using jquery.val fn to retrieve the value + return this.data("_inputmask") ? !this.data("_inputmask")['opts'].autoUnmask : false; + case "isComplete": + if (this.data("_inputmask")) { + return maskScope({ "action": "isComplete", "buffer": this[0]._valueGet().split(''), "el": this }); + } else return true; + case "getmetadata": //return mask metadata if exists + if (this.data("_inputmask")) { + return maskScope({ "action": "getmetadata", "el": this }); + } + else return undefined; + default: + resolveAlias(opts.alias, options, opts); + //check if the fn is an alias + if (!resolveAlias(fn, options, opts)) { + //maybe fn is a mask so we try + //set mask + opts.mask = fn; + } + maskset = generateMaskSet(opts); + if (maskset == undefined) { return this; } + return this.each(function () { + maskScope({ "action": "mask", "el": this }, $.extend(true, {}, maskset), importAttributeOptions(this, opts)); + }); + } + } else if (typeof fn == "object") { + opts = $.extend(true, {}, $.inputmask.defaults, fn); + resolveAlias(opts.alias, fn, opts); //resolve aliases + maskset = generateMaskSet(opts); + if (maskset == undefined) { return this; } + return this.each(function () { + maskScope({ "action": "mask", "el": this }, $.extend(true, {}, maskset), importAttributeOptions(this, opts)); + }); + } else if (fn == undefined) { + //look for data-inputmask atribute - the attribute should only contain optipns + return this.each(function () { + var attrOptions = $(this).attr("data-inputmask"); + if (attrOptions && attrOptions != "") { + try { + attrOptions = attrOptions.replace(new RegExp("'", "g"), '"'); + var dataoptions = $.parseJSON("{" + attrOptions + "}"); + $.extend(true, dataoptions, options); + opts = $.extend(true, {}, $.inputmask.defaults, dataoptions); + opts = importAttributeOptions(this, opts); + resolveAlias(opts.alias, dataoptions, opts); + opts.alias = undefined; + $(this).inputmask("mask", opts); + } catch (ex) { } //need a more relax parseJSON + } + if ($(this).attr("data-inputmask-mask") || $(this).attr("data-inputmask-alias")) { + opts = $.extend(true, {}, $.inputmask.defaults, {}); + var dataOptions = {}; + opts = importAttributeOptions(this, opts, dataOptions); + resolveAlias(opts.alias, dataOptions, opts); + opts.alias = undefined; + $(this).inputmask("mask", opts); + } + }); } }; } + return $.fn.inputmask; })(jQuery); \ No newline at end of file diff --git a/templates/client/static_client/js_min/_modules/block.search.min.js b/templates/client/static_client/js_min/_modules/block.search.min.js index 3e07e1d4..a40e0d17 100644 --- a/templates/client/static_client/js_min/_modules/block.search.min.js +++ b/templates/client/static_client/js_min/_modules/block.search.min.js @@ -1 +1 @@ -var EXPO=EXPO||{};EXPO.searchBlock?console.warn("WARNING: EXPO.searchBlock is already defined!"):EXPO.searchBlock=function(){var e={};e.settings={place:{id:"pw-place",selectedItemTemplate:"csb-selected",ajaxUrl:"http://hit.expomap.ru/search-form/"},subject:{id:"pw-subj",ajaxUrl:"http://hit.expomap.ru/search-form/"}},e.lang={};var t=EXPO.common,i=function(e){var t=Object.keys(e).map(function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])}).join("&");return"?"+t},n=function(e,t,i){e||(e=""),$.ajax({type:"GET",url:t,data:e,success:function(e){return"function"!=typeof i?e:void i(e)}})},a=function(e,t,i){return e.hasOwnProperty(t)&&(e[i]=e[t]),this},s=function(e){var t,i=0;for(t in e)e.hasOwnProperty(t)&&i++;return i},l=function(e,t){var i=$("#"+e),n="",a=EXPO.searchBlock.settings.closerText,s=EXPO.searchBlock.settings.closerTextSingle,l="";return $element=i.find(".csbs-text"),$element.length>2?$element.eq(0).text().length2&&d?(n({term:t,form:o},l.opt.autoCompleteUrl,u),d=!1):0!=t.length||d||l.$inputFilter.hasClass("ui-autocomplete-input")&&(l.$inputFilter.placeComplete("destroy"),d=!0),!1}).click(function(){return!1})},_renderSublist:function(e,t,i){var n=this,a=0,s=t+"-sub",l=function(e){if(e.length){for(n.sublist[s]={},a;aw;w++)for(o=_[w],T=0;x>T;T++)o==C[T]&&A(a[T]);for(w=0;y>w;w++)o=_[w],o==S&&A(i)}else for(w=0;y>w;w++)o=_[w],o==S&&A(S)},A=function(e){var t=e.getAttribute("id");i._destroyTag(t),O()},M=function(e){var a=t.closest(e,n),s=a.querySelector("."+u),l=s.innerHTML,r=e.getAttribute("id"),o={id:r,text:l};i._addTag(r,o),O()},O=function(){o.find("."+h).length&&"~~id~~"!=o.find("."+h)[0].getAttribute(m)?o.addClass("visible"):o.removeClass("visible")},P=function(){var t=$(b).children("li").children("."+e).find("."+l+":checked");t.each(function(){M(this)})},q=function(){var t=$(b).children("li").children("."+e).find("."+l+":checked");t.each(function(){A(this)})};i.strictMode?this.checked?(T(this),D(this),M(this)):(I(this),D(this),A(this)):this.checked?(B()?(S(this),T(this),D(v),M(v),q(b),v.getAttribute("id")!=_.getAttribute("id")||_.checked||(T(_),D(_),M(_))):(T(this),D(this),M(this)),k&&y(this),k&&"~~id~~"!=$(k).find("."+l)[0].value&&D(this)):(F()?(w(this),I(this),D(v),A(v),P(b),_.checked&&(I(_),D(_),A(_))):(I(this),D(this),A(this)),k&&(x(this),D(this))),p()}),$(".csbs-del",o).on("click",function(){var e=$(this).attr("data-checkbox-id"),t=$("#"+e);return t.prop("checked",!1),t.trigger("change"),dna.destroy(i.itemsSelected[e]),o.children(".dna-clone").length||o.removeClass("visible"),!1}),$(".clear",a).on("click",function(){return i.resetList(),!1}),$(".q-sel a",a).on("click",function(){var e=$(this),t=e.attr("data-name"),a=e.attr("data-id"),s={name:t,id:a},l=function(e){i._loadParentTree(e,function(){i._checkCheckBox(a)})};return n(s,i.opt.getParentUrl,l),!1}),$("."+h,a).on("click",function(){return i.applyHandler(this),!1}),d.siblings("."+i.opt.clearAllButtonClass).on("click",function(){i.resetList()})})};c.prototype={_getAjax:function(e,t){var i=this;e||(e=""),$.ajax({type:"GET",url:i.opt.ajaxUrl,data:e,success:function(e){return"function"!=typeof t?(i.rawData=e,e):(i.rawData=e,void t(e))}})},_renderSublist:function(e,t,i){var n=this,a=0,s=t+"-sub",l=function(e){if(e.length){for(n.curDNA[s]={},a;a2&&o?(n({term:t,form:l},s.opt.autoCompleteUrl,d),o=!1):0!=t.length||o||s.$inputFilter.hasClass("ui-autocomplete-input")&&(s.$inputFilter.autocomplete("destroy"),o=!0),!1}).click(function(){return!1})},_loadParentTree:function(e,t,i){var n,a,l,o,c=this,d=e,h=$("#id_"+d.id),u=function(e){var n=$("#id_"+d.id),h=function(){r.hide(),i||0===i?t(i):t()};r.hide(),n.length&&s(c.curDNA[a+"-sub"])==e&&(l={name:d.name,id:d.id},r.show(),o=$("#id_"+d.id).closest(".level").children(".trigger").attr("data-template-id"),c._renderNested(l,h,o,d.id))},p=function(){r.hide(),i||0===i?t(i):t()};r.show(),d.hasOwnProperty("parent")?h.length?(l={name:d.name,id:d.id},o=h.closest(".level").children(".trigger").attr("data-template-id"),c._renderNested(l,function(){r.hide(),t()},o,d.id)):(n={name:d.parent.name,id:d.parent.id},a=$("#id_"+d.parent.id).closest(".level").children(".trigger").attr("data-template-id"),c._renderSublist(n,a,u)):(n={name:d.name,id:d.id},a=$("#id_"+d.id).closest(".level").children(".trigger").attr("data-template-id"),c._renderSublist(n,a,p))},applyHandler:function(){}};var d=function(e){this.opt=e;var t=this,i=$("#"+t.opt.dateFrom),n=$("#"+t.opt.dateTo),a=$("#"+t.opt.id),s=$("#"+t.opt.modalTrigger),l=t.opt.applyBtnClass,r=function(){var e="",t=s.data("lng-to"),a=s.data("lng-from"),l=$.trim(n.val()),r=$.trim(i.val());return""!=l&&""!=r?e=a+": "+r+" "+t+": "+l+".":""!=l&&""==r?e=t+": "+l+".":""==l&&""!=r&&(e=a+": "+r+"."),e},o=function(e){""!=e?(s.text(e).siblings(".trigger-label").addClass("hidden"),s.siblings("."+t.opt.clearAllButtonClass).addClass("active")):(s.text(s.data("default")).siblings(".trigger-label").removeClass("hidden"),s.siblings("."+t.opt.clearAllButtonClass).removeClass("active"))},c=function(e){var a,s,l,r,o=e.getAttribute("id"),c=e.value,d=Date.parse(c);t.validate()&&($(e).parent(".pwf-field").removeClass("err"),o==t.opt.dateFrom?(a=n[0].getAttribute("id"),s=n[0].value):(a=i[0].getAttribute("id"),s=i[0].value),l=Date.parse(s),l>d&&0!=l&&l?(r=document.getElementById(o).value,document.getElementById(o).value=document.getElementById(a).value,document.getElementById(a).value=r):d>l&&0!=l&&l&&(r=document.getElementById(a).value,document.getElementById(a).value=document.getElementById(o).value,document.getElementById(o).value=r))};this.$dateFrom=i,this.$dateTo=n,this.$modalTrigger=s,$(function(){$.datepicker.setDefaults($.datepicker.regional.ru),i.datepicker({dateFormat:"dd.mm.yy",showOn:"button",showOtherMonths:!0,constrainInput:!0,onClose:function(e){n.datepicker("option","minDate",e)}}).inputmask("99.99.9999",{showMaskOnHover:!1,oncomplete:function(){c(this)}}),n.datepicker({dateFormat:"dd.mm.yy",showOn:"button",showOtherMonths:!0,constrainInput:!0,onClose:function(e){i.datepicker("option","maxDate",e)}}).inputmask("99.99.9999",{showMaskOnHover:!1,oncomplete:function(){c(this)}}),$('input[type="text"]',a).on("change",function(){var e=r();o(e)}),$("."+l,a).on("click",function(){return t.applyHandler(this),!1}),s.siblings("."+t.opt.clearAllButtonClass).on("click",function(){$(this).removeClass("active"),t.resetList()})})};d.prototype={resetList:function(){this.$dateFrom.val(""),this.$dateTo.val(""),this.$modalTrigger.text(this.$modalTrigger.attr("data-default"))},validate:function(){var e=this.$dateTo.val(),t=this.$dateFrom.val(),i=e.split("."),n=t.split("."),a=[],s=!0;return a[0]=Date.parse(i[1]+"."+i[0]+"."+i[2]),a[1]=Date.parse(n[1]+"."+n[0]+"."+n[2]),a[0]||""==$.trim(e)?this.$dateTo.parent(".pwf-field").removeClass("err"):(this.$dateTo.parent(".pwf-field").addClass("err"),s=!1),a[1]||""==$.trim(t)?this.$dateFrom.parent(".pwf-field").removeClass("err"):(this.$dateFrom.parent(".pwf-field").addClass("err"),s=!1),s},applyHandler:function(){}};var h=function(e){this.opt=e,this.opt.anyChar=!1;var i=this,s=!0;this.$field=$("#"+i.opt.id),this.DOMcompleteWrap=document.getElementById(i.opt.autoCompleteWrapId),this.afterClear,this.rawData={items:[],set:function(e){this.items=e,this._rawDataChange()},get:function(){return this.items},_rawDataChange:function(){var e,t=this;for(e=0;e2?n(a,i.opt.autoCompleteUrl,function(e){i.$field.hasClass("ui-autocomplete-input")&&i.$field[i.completeName]("destroy"),i.rawData.set(e),i._initAutoComplete(),i.showList("")}):0===text.length&&i.$field.hasClass("ui-autocomplete-input")&&(i.$field[i.completeName]("destroy"),t.removeClass(i.DOMcompleteWrap,"full-visible"),i._resetmodals(i.afterClear)):text.length>2&&s?(n(a,i.opt.autoCompleteUrl,function(e){i.rawData.set(e),i._initAutoComplete(),i.showList("")}),s=!1):0!=text.length||s?i.$field.hasClass("ui-autocomplete-input")&&i.showList(text):i.$field.hasClass("ui-autocomplete-input")&&(i.$field[i.completeName]("destroy"),t.removeClass(i.DOMcompleteWrap,"full-visible"),i._resetmodals(i.afterClear),s=!0),!1}).click(function(){return!1})};return h.prototype={_initAutoComplete:function(){var e=this;e.$field[e.completeName]({source:e.rawData.get(),minLength:0,appendTo:e.DOMcompleteWrap,select:function(t,i){e._afterSelect(t,i)},close:function(){t.removeClass(e.DOMcompleteWrap,"full-visible")},open:function(){t.addClass(e.DOMcompleteWrap,"full-visible")}})},_afterSelect:function(e,t){var i=this;e.preventDefault(),t.item.url?window.location=t.item.url:t.item.label.length&&(i.$field[0].value=t.item.label,i.selectCheckBoxes(t.item.id,t.item.name))},_resetmodals:function(e){return e?void e():0},selectHandler:function(){},selectCheckBoxes:function(){},showList:function(e){self=this,this.$field[self.completeName]("search",e)},pullData:function(){}},e.init=function(e){$.extend(this.lang,e.lang),e.lang=null,$.extend(this.settings,e);var i=this,a=function(){$(i.DOMform).find('input[name="~~name~~"]').remove()};"None"!=this.settings.searchData&&this.settings.searchData&&(this.previousSearch=JSON.parse(this.settings.searchData)),this.DOMform=document.getElementById(this.settings.formId),$(this.DOMform).on("submit",function(){a()}),$.widget("custom.exibitionComplete",$.ui.autocomplete,{_renderMenu:function(e,t){var i=this,n="";$.each(t,function(t,a){a.cat!=n&&a.cat&&(e.append("
  • "+a.cat+"
  • "),n=a.cat),i._renderItemData(e,a)})}}),$.widget("custom.exibitionComplete",$.ui.autocomplete,{_renderMenu:function(e,t){var i=this,n="";$.each(t,function(t,a){a.cat!=n&&a.cat&&(e.append("
  • "+a.cat+"
  • "),n=a.cat),i._renderItemData(e,a)})}}),$.widget("custom.placeComplete",$.ui.autocomplete,{_renderItem:function(e,t){return $("
  • ").append($("").text(t.label)).append(' ('+t.cat+")").appendTo(e)}}),this.exhibitionField=new h(i.settings.firstField),this.exhibitionField.completeName="exibitionComplete",this.exhibitionField.opt.anyChar=!0,this.placesModal=new c(i.settings.place),this.subjModal=new o(i.settings.subject),this.periodModal=new d(i.settings.period),this.exhibitionField.selectCheckBoxes=function(e,t){var i,a,s=this,l=t;"th"==t?i=document.getElementById(s.opt.prefix+e):"tg"==t&&(i=document.getElementById(s.opt.prefixInner+e),l="th"),r.show(),i?(r.hide(),$(i).prop("checked",!0),$(i).trigger("change")):(a={name:t,id:e},n(a,EXPO.searchBlock.subjModal.opt.getParentUrl,function(i){EXPO.searchBlock.subjModal._loadParentTree(i,function(){EXPO.searchBlock.subjModal._checkCheckBox(e,t)})}))},this.placesField=new h(i.settings.placeField),this.placesField.dataForm=EXPO.searchBlock.placesModal.$inputFilter.attr("data-form"),this.placesField.selectCheckBoxes=function(e,t){var i,a,s=this;i=document.getElementById(s.opt.prefix+e),i?(r.hide(),$(i).prop("checked",!0),$(i).trigger("change")):(a={name:t,id:e},n(a,EXPO.searchBlock.placesModal.opt.getParentUrl,function(t){EXPO.searchBlock.placesModal._loadParentTree(t,function(){EXPO.searchBlock.placesModal._checkCheckBox(e,!0)})}))},this.exhibitionField.afterClear=function(){i.subjModal.resetList()},this.placesField.afterClear=function(){i.placesModal.resetList()},this.modalWindow=new t.Modal(i.settings.modal),this.periodModal.applyHandler=function(){this.validate()&&(r.show(),$(i.DOMform).submit())},this.placesModal.applyHandler=function(){r.show(),$(i.DOMform).submit()},this.subjModal.applyHandler=function(){r.show(),$(i.DOMform).submit()},$("."+i.settings.modalTriggerClass).on("click",function(e){return e.preventDefault(),i.modalWindow.pullData(this.getAttribute("href")),i.modalWindow.open(),!1}),$(function(){if(i.previousSearch)for(var e=0;e2?$element.eq(0).text().length2&&d?(a({term:t,form:o},l.opt.autoCompleteUrl,u),d=!1):0!=t.length||d||l.$inputFilter.hasClass("ui-autocomplete-input")&&(l.$inputFilter.placeComplete("destroy"),d=!0),!1}).click(function(){return!1})},_renderSublist:function(e,t,i){var a=this,n=0,s=t+"-sub",l=function(e){if(e.length){for(a.sublist[s]={},n;nw;w++)for(p=y[w],I=0;S>I;I++)p==_[I]&&M(r[I]);for(w=0;x>w;w++)p=y[w],p==T&&M(i);C.querySelectorAll(".final-tire")&&$("."+e+"."+n,C.querySelectorAll(".final-tire")).each(function(){M($("."+l,this)[0])})}else for(w=0;x>w;w++)p=y[w],p==T&&M(T)},M=function(e){var t=e.getAttribute("id");i._destroyTag(t),P()},O=function(e){var n=t.closest(e,a),s=n.querySelector("."+u),l=s.innerHTML,r=e.getAttribute("id"),o={id:r,text:l};i._addTag(r,o),P()},P=function(){o.find("."+h).length&&"~~id~~"!=o.find("."+h)[0].getAttribute(m)?o.addClass("visible"):o.removeClass("visible")},q=function(t){var i=$(t).children("li").children("."+e).find("."+l+":checked");i.each(function(){O(this)})},E=function(){var t=$(C).children("li").children("."+e).find("."+l+":checked");t.each(function(){M(this)})};i.strictMode?this.checked?(I(this),D(this),O(this)):(B(this),D(this),M(this)):this.checked?($(k).find("."+l)[0]&&k&&"~~id~~"!=$(k).find("."+l)[0].value&&D(this),F()?(T(this),I(this),D(v),O(v),E(C),v.getAttribute("id")!=_.getAttribute("id")||_.checked||(I(_),D(_),O(_))):(I(this),D(this),O(this)),k&&x(this)):(A()?(w(this),B(this),D(v),M(v),q(C),_.checked&&(B(_),M(_),q(y))):(B(this),D(this),M(this)),k&&(S(this),D(this))),p()}),$(".csbs-del",o).on("click",function(){var e=$(this).attr("data-checkbox-id"),t=$("#"+e);return t.prop("checked",!1),t.trigger("change"),dna.destroy(i.itemsSelected[e]),o.children(".dna-clone").length||o.removeClass("visible"),!1}),$(".modal-clear",n).on("click",function(){return i.resetList(),!1}),$(".q-sel a",n).on("click",function(){var e=$(this),t=e.attr("data-name"),n=e.attr("data-id"),s={name:t,id:n},l=function(e){i._loadParentTree(e,function(){i._checkCheckBox(n)})};return a(s,i.opt.getParentUrl,l),!1}),$("."+h,n).on("click",function(){return i.applyHandler(this),!1}),d.siblings("."+i.opt.clearAllButtonClass).on("click",function(){i.resetList(),EXPO.searchBlock.placesField.clearValue()})})};c.prototype={_getAjax:function(e,t){var i=this;e||(e=""),$.ajax({type:"GET",url:i.opt.ajaxUrl,data:e,success:function(e){return"function"!=typeof t?(i.rawData=e,e):(i.rawData=e,void t(e))}})},_renderSublist:function(e,t,i){var a=this,n=0,s=t+"-sub",l=function(e){if(e.length){for(a.curDNA[s]={},n;n2&&o?(a({term:t,form:l},s.opt.autoCompleteUrl,d),o=!1):0!=t.length||o||s.$inputFilter.hasClass("ui-autocomplete-input")&&(s.$inputFilter.autocomplete("destroy"),o=!0),!1}).click(function(){return!1})},_loadParentTree:function(e,t,i){var a,n,l,o,c=this,d=e,h=$("#id_"+d.id),u=function(e){var a=$("#id_"+d.id),h=function(){r.hide(),i||0===i?t(i):t()};r.hide(),a.length&&s(c.curDNA[n+"-sub"])==e&&(l={name:d.name,id:d.id},r.show(),o=$("#id_"+d.id).closest(".level").children(".trigger").attr("data-template-id"),c._renderNested(l,h,o,d.id))},p=function(){r.hide(),i||0===i?t(i):t()};r.show(),d.hasOwnProperty("parent")?h.length?(l={name:d.name,id:d.id},o=h.closest(".level").children(".trigger").attr("data-template-id"),c._renderNested(l,function(){r.hide(),t()},o,d.id)):(a={name:d.parent.name,id:d.parent.id},n=$("#id_"+d.parent.id).closest(".level").children(".trigger").attr("data-template-id"),c._renderSublist(a,n,u)):(a={name:d.name,id:d.id},n=$("#id_"+d.id).closest(".level").children(".trigger").attr("data-template-id"),c._renderSublist(a,n,p))},applyHandler:function(){},_refreshText:function(){var e,t=$("#"+this.opt.modalTrigger),i=16;e=l(this.opt.selectedItemsContainer,i),e&&"~~text~~"!=e&&"~~text~~..."!=e?(t.text(e),t.siblings("."+this.opt.clearAllButtonClass).addClass("active")):(t.text(t.data("default")),t.siblings("."+this.opt.clearAllButtonClass).removeClass("active"))}};var d=function(e){this.opt=e;var t,i=this,a=$("#"+i.opt.dateFrom),n=$("#"+i.opt.dateTo),s=$("#"+i.opt.id),l=$("#"+i.opt.modalTrigger),r=i.opt.applyBtnClass,o=function(){var e="",t=l.data("lng-to"),i=l.data("lng-from"),s=$.trim(n.val()),r=$.trim(a.val());return""!=s&&""!=r?e=i+": "+r+" "+t+": "+s+".":""!=s&&""==r?e=t+": "+s+".":""==s&&""!=r&&(e=i+": "+r+"."),e},c=function(e){""!=e?(l.text(e).siblings(".trigger-label").addClass("hidden"),l.siblings("."+i.opt.clearAllButtonClass).addClass("active")):(l.text(l.data("default")).siblings(".trigger-label").removeClass("hidden"),l.siblings("."+i.opt.clearAllButtonClass).removeClass("active"))},d=function(e){var t,s,l,r,o=e.getAttribute("id"),c=e.value,d=Date.parse(c);i.validate()&&($(e).parent(".pwf-field").removeClass("err"),o==i.opt.dateFrom?(t=n[0].getAttribute("id"),s=n[0].value):(t=a[0].getAttribute("id"),s=a[0].value),l=Date.parse(s),d>l&&o==i.opt.dateFrom?(r=document.getElementById(o).value,document.getElementById(o).value=document.getElementById(t).value,document.getElementById(t).value=r):l>d&&o==i.opt.dateTo&&(r=document.getElementById(t).value,document.getElementById(t).value=document.getElementById(o).value,document.getElementById(o).value=r))};this.$dateFrom=a,this.$dateTo=n,this.$modalTrigger=l,$(function(){$.datepicker.setDefaults($.datepicker.regional.ru),a.datepicker({dateFormat:"dd.mm.yy",showOn:"button",showOtherMonths:!0,constrainInput:!0,onClose:function(e){n.datepicker("option","minDate",e)}}).inputmask("99.99.9999",{showMaskOnHover:!1,insertMode:!1,oncomplete:function(){t=this}}),n.datepicker({dateFormat:"dd.mm.yy",showOn:"button",showOtherMonths:!0,constrainInput:!0,onClose:function(e){a.datepicker("option","maxDate",e)}}).inputmask("99.99.9999",{showMaskOnHover:!1,insertMode:!1,oncomplete:function(){t=this}}),$('input[type="text"]',s).on("change",function(){var e=o();i.validate()&&c(e)}),$("."+r,s).on("click",function(){return t&&d(t),i.applyHandler(this),!1}),l.siblings("."+i.opt.clearAllButtonClass).on("click",function(){$(this).removeClass("active"),i.resetList()})})};d.prototype={resetList:function(){this.$dateFrom.val(""),this.$dateTo.val(""),this.$modalTrigger.text(this.$modalTrigger.attr("data-default"))},validate:function(){var e=this.$dateTo.val(),t=this.$dateFrom.val(),i=e.split("."),a=t.split("."),n=[],s=!0;return n[0]=Date.parse(i[1]+"."+i[0]+"."+i[2]),n[1]=Date.parse(a[1]+"."+a[0]+"."+a[2]),n[0]||""==$.trim(e)?this.$dateTo.parent(".pwf-field").removeClass("err"):(this.$dateTo.parent(".pwf-field").addClass("err"),s=!1),n[1]||""==$.trim(t)?this.$dateFrom.parent(".pwf-field").removeClass("err"):(this.$dateFrom.parent(".pwf-field").addClass("err"),s=!1),s},applyHandler:function(){}};var h=function(e){this.opt=e,this.opt.anyChar=!1;var i=this,s=!0;this.$field=$("#"+i.opt.id),this.DOMcompleteWrap=document.getElementById(i.opt.autoCompleteWrapId),this.afterClear,this.rawData={items:[],set:function(e){this.items=e,this._rawDataChange()},get:function(){return this.items},_rawDataChange:function(){var e,t=this;for(e=0;e2?a(n,i.opt.autoCompleteUrl,function(e){i.$field.hasClass("ui-autocomplete-input")&&i.$field[i.completeName]("destroy"),i.rawData.set(e),i._initAutoComplete(),i.showList("")}):0===text.length&&i.$field.hasClass("ui-autocomplete-input")&&(i.$field[i.completeName]("destroy"),t.removeClass(i.DOMcompleteWrap,"full-visible"),i._resetmodals(i.afterClear)):text.length>2&&s?(a(n,i.opt.autoCompleteUrl,function(e){i.rawData.set(e),i._initAutoComplete(),i.showList("")}),s=!1):0!=text.length||s?i.$field.hasClass("ui-autocomplete-input")&&i.showList(text):i.$field.hasClass("ui-autocomplete-input")&&(i.$field[i.completeName]("destroy"),t.removeClass(i.DOMcompleteWrap,"full-visible"),i._resetmodals(i.afterClear),s=!0),!1}).click(function(){return!1})};return h.prototype={_initAutoComplete:function(){var e=this;e.$field[e.completeName]({source:e.rawData.get(),minLength:0,appendTo:e.DOMcompleteWrap,select:function(t,i){e._afterSelect(t,i)},close:function(){t.removeClass(e.DOMcompleteWrap,"full-visible")},open:function(){t.addClass(e.DOMcompleteWrap,"full-visible")}})},_afterSelect:function(e,t){var i=this;e.preventDefault(),t.item.url?window.location=t.item.url:t.item.label.length&&(i.$field[0].value=t.item.label,i.selectCheckBoxes(t.item.id,t.item.name))},_resetmodals:function(e){return e?void e():0},selectHandler:function(){},selectCheckBoxes:function(){},showList:function(e){self=this,this.$field[self.completeName]("search",e)},pullData:function(){},clearValue:function(){this.$field.val("")}},e.init=function(e){$.extend(this.lang,e.lang),e.lang=null,$.extend(this.settings,e);var i=this,n=function(){$(i.DOMform).find('input[name="~~name~~"]').remove()};"None"!=this.settings.searchData&&this.settings.searchData&&(this.previousSearch=JSON.parse(this.settings.searchData)),this.DOMform=document.getElementById(this.settings.formId),$(this.DOMform).on("submit",function(){n()}),$.widget("custom.exibitionComplete",$.ui.autocomplete,{_renderMenu:function(e,t){var i=this,a="";$.each(t,function(t,n){n.cat!=a&&n.cat&&(e.append("
  • "+n.cat+"
  • "),a=n.cat),i._renderItemData(e,n)})}}),$.widget("custom.exibitionComplete",$.ui.autocomplete,{_renderMenu:function(e,t){var i=this,a="";$.each(t,function(t,n){n.cat!=a&&n.cat&&(e.append("
  • "+n.cat+"
  • "),a=n.cat),i._renderItemData(e,n)})}}),$.widget("custom.placeComplete",$.ui.autocomplete,{_renderItem:function(e,t){return $("
  • ").append($("").text(t.label)).append(' ('+t.cat+")").appendTo(e)}}),this.exhibitionField=new h(i.settings.firstField),this.exhibitionField.completeName="exibitionComplete",this.exhibitionField.opt.anyChar=!0,this.placesModal=new c(i.settings.place),this.subjModal=new o(i.settings.subject),this.periodModal=new d(i.settings.period),this.exhibitionField.selectCheckBoxes=function(e,t){var i,n,s=this,l=t;"th"==t?i=document.getElementById(s.opt.prefix+e):"tg"==t&&(i=document.getElementById(s.opt.prefixInner+e),l="th"),r.show(),i?(r.hide(),$(i).prop("checked",!0),$(i).trigger("change")):(n={name:t,id:e},a(n,EXPO.searchBlock.subjModal.opt.getParentUrl,function(i){EXPO.searchBlock.subjModal._loadParentTree(i,function(){EXPO.searchBlock.subjModal._checkCheckBox(e,t)})}))},this.placesField=new h(i.settings.placeField),this.placesField.dataForm=EXPO.searchBlock.placesModal.$inputFilter.attr("data-form"),this.placesField.selectCheckBoxes=function(e,t){var i,n,s=this;i=document.getElementById(s.opt.prefix+e),i?(r.hide(),$(i).prop("checked",!0),$(i).trigger("change")):(n={name:t,id:e},a(n,EXPO.searchBlock.placesModal.opt.getParentUrl,function(t){EXPO.searchBlock.placesModal._loadParentTree(t,function(){EXPO.searchBlock.placesModal._checkCheckBox(e,!0)})}))},this.exhibitionField.afterClear=function(){i.subjModal.resetList()},this.placesField.afterClear=function(){i.placesModal.resetList()},this.modalWindow=new t.Modal(i.settings.modal),this.periodModal.applyHandler=function(){this.validate()&&(r.show(),$(i.DOMform).submit())},this.placesModal.applyHandler=function(){r.show(),$(i.DOMform).submit()},this.subjModal.applyHandler=function(){r.show(),$(i.DOMform).submit()},$("."+i.settings.modalTriggerClass).on("click",function(e){return e.preventDefault(),i.modalWindow.pullData(this.getAttribute("href")),i.modalWindow.open(),!1}),$(function(){if(i.previousSearch)for(var e=0;e2&&d?(n({term:t,form:l},o.opt.autoCompleteUrl,u),d=!1):0!=t.length||d||o.$inputFilter.hasClass("ui-autocomplete-input")&&(o.$inputFilter.autocomplete("destroy"),d=!0),!1}).click(function(){return!1})},_renderSublist:function(e,t,i){var n=this,s=0,a=t+"-sub",o=function(e){if(e.length){for(n.sublist[a]={},s;sS;S++)for(c=y[S],T=0;x>T;T++)c==C[T]&&B(s[T]);for(S=0;_>S;S++)c=y[S],c==I&&B(i)}else for(S=0;_>S;S++)c=y[S],c==I&&B(I)},B=function(e){var t=e.getAttribute("id");i._destroyTag(t),A()},M=function(e){var s=t.closest(e,n),a=s.querySelector("."+p),r=a.innerHTML,o=e.getAttribute("id"),l={id:o,text:r};i._addTag(o,l),A()},A=function(){o.children("."+d).length&&"~~id~~"!=o.children("."+d)[0].getAttribute(f)?o.addClass("visible"):o.removeClass("visible")},F=function(){var t=$(b).children("li").children("."+e).find("."+r+":checked");t.each(function(){M(this)})},E=function(){var t=$(b).children("li").children("."+e).find("."+r+":checked");t.each(function(){B(this)})};this.checked?(w()?(I(this),T(this),P(v),M(v),E(b),v.getAttribute("id")!=y.getAttribute("id")||y.checked||(T(y),P(y),M(y))):(T(this),P(this),M(this)),k&&_(this)):(D()?(S(this),O(this),P(v),B(v),F(b),y.checked&&(O(y),P(y),B(y))):(O(this),P(this),B(this)),k&&x(this)),u()}),$("."+i.opt.deleteTagClass,s).on("click",function(){var e=$(this).attr("data-checkbox-id"),t=$("#"+e);return t.prop("checked",!1),t.trigger("change"),i._refreshLabel(),o.children(".dna-clone").length||o.removeClass("visible"),!1}),$("#"+i.opt.deleteId).on("click",function(){$("."+i.opt.deleteTagClass,s).trigger("click")}),$(".clear",s).on("click",function(){return i.resetList(),!1}),$(".q-sel a",s).on("click",function(){var e=$(this),t=e.attr("data-name"),s=e.attr("data-id"),a={name:t,id:s},r=function(e){i._loadParentTree(e,function(){i._checkCheckBox(s)})};return n(a,i.opt.getParentUrl,r),!1}),$("."+d,s).on("click",function(){return i.applyHandler(this),!1}),c.siblings("."+i.opt.clearAllButtonClass).on("click",function(){i.resetList()})})};return c.prototype={_getAjax:function(e,t){var i=this;e||(e=""),$.ajax({type:"GET",url:i.opt.ajaxUrl,data:e,success:function(e){return"function"!=typeof t?(i.rawData=e,e):(i.rawData=e,void t(e))}})},_renderSublist:function(e,t,i){var n=this,s=0,a=t+"-sub",o=function(e){if(e.length){for(n.curDNA[a]={},s;s2&&c?(r.show(),n({term:t,form:o},a.opt.autoCompleteUrl,h),c=!1):0!=t.length||c||a.$inputFilter.hasClass("ui-autocomplete-input")&&(a.$inputFilter.autocomplete("destroy"),c=!0),!1}).click(function(){return!1})},_loadParentTree:function(e,t,i){var n,s,o,l,c=this,d=e,h=$("#id_"+c.opt.prefix+d.id),u=function(e){var n=$("#id_"+c.opt.prefix+d.id),h=function(){r.hide(),i||0===i?t(i):t()};r.hide(),n.length&&a(c.curDNA[s+"-sub"])==e&&(o={name:d.name,id:d.id},r.show(),l=$("#id_"+c.opt.prefix+d.id).closest(".level").children(".trigger").attr("data-template-id"),c._renderNested(o,h,l,d.id))},p=function(){r.hide(),i||0===i?t(i):t()};r.show(),d.hasOwnProperty("parent")?h.length?(o={name:d.name,id:d.id},l=h.closest(".level").children(".trigger").attr("data-template-id"),c._renderNested(o,function(){r.hide(),t()},l,d.id)):(n={name:d.parent.name,id:d.parent.id},s=$("#id_"+c.opt.prefix+d.parent.id).closest(".level").children(".trigger").attr("data-template-id"),c._renderSublist(n,s,u)):(n={name:d.name,id:d.id},s=$("#id_"+c.opt.prefix+d.id).closest(".level").children(".trigger").attr("data-template-id"),c._renderSublist(n,s,p))},applyHandler:function(){},_refreshLabel:function(){var e=this.selectedWrap.children().length;this.$label.text(this.$label.attr(e?"data-selected":"data-default"))}},e.init=function(e){$.extend(this.opt,e);var n=this,s=function(){$(n.DOMform).find('input[name="~~name~~"]').remove()};"None"!=this.opt.searchData&&this.opt.searchData&&(this.previousSearch=JSON.parse(this.opt.searchData)),this.DOMform=document.getElementById(this.opt.formId),this.DOMhint=document.getElementById(this.opt.filter.hintId),$(this.DOMform).on("submit",function(){s()}),this.DOMapplyButton=document.getElementById(this.opt.applyButtonId),this.filterPane=new i(this.opt.filter),$("#"+this.opt.filter.buttonId).on("click",function(){return t.hasClass(this,n.opt.activeClass)?(t.removeClass(this,n.opt.activeClass),n.filterPane.hide()):(t.addClass(this,n.opt.activeClass),n.filterPane.show()),!1}),$("#"+n.opt.bodyId+" ."+n.opt.modalTriggerClass).on("click",function(e){return e.preventDefault(),n.modalWindow.pullData(this.getAttribute("href")),n.modalWindow.open(),!1}),$("#"+n.opt.applyButtonId).on("click",function(){return $(n.DOMform).submit(),!1}),this.modalWindow=new t.Modal(n.opt.modal),this.placesModal=new c(n.opt.place),this.subjModal=new l(n.opt.subject),this.placesModal.applyHandler=function(){n.modalWindow.close(),$(n.DOMform).submit()},this.subjModal.applyHandler=function(){n.modalWindow.close(),$(n.DOMform).submit()},$(function(){if(n.previousSearch.inputs.length){$(n.DOMhint).hide();for(var e=0;e2&&d?(n({term:t,form:c},o.opt.autoCompleteUrl,u),d=!1):0!=t.length||d||o.$inputFilter.hasClass("ui-autocomplete-input")&&(o.$inputFilter.autocomplete("destroy"),d=!0),!1}).click(function(){return!1})},_renderSublist:function(e,t,i){var n=this,s=0,a=t+"-sub",o=function(e){if(e.length){for(n.sublist[a]={},s;sT;T++)for(h=_[T],O=0;S>O;O++)h==C[O]&&A(o[O]);for(T=0;x>T;T++)h=_[T],h==I&&A(i);b.querySelectorAll(".final-tire")&&$("."+e+"."+s,b.querySelectorAll(".final-tire")).each(function(){A($("."+r,this)[0])})}else for(T=0;x>T;T++)h=_[T],h==I&&A(I)},A=function(e){var t=e.getAttribute("id");i._destroyTag(t),q()},M=function(e){var s=t.closest(e,n),a=s.querySelector("."+p),r=a.innerHTML,o=e.getAttribute("id"),c={id:o,text:r};i._addTag(o,c),q()},q=function(){o.find("."+u).length&&"~~id~~"!=o.find("."+u)[0].getAttribute(f)?o.addClass("visible"):o.removeClass("visible")},F=function(t){var i=$(t).children("li").children("."+e).find("."+r+":checked");i.each(function(){M(this)})},E=function(){var t=$(b).children("li").children("."+e).find("."+r+":checked");t.each(function(){A(this)})};i.strictMode?this.checked?(O(this),D(this),M(this)):(P(this),D(this),A(this)):this.checked?($(k).find("."+r)[0]&&k&&"~~id~~"!=$(k).find("."+r)[0].value&&D(this),w()?(I(this),O(this),D(m),M(m),E(b),m.getAttribute("id")!=C.getAttribute("id")||C.checked||(O(C),D(C),M(C))):(O(this),D(this),M(this)),k&&x(this)):(B()?(T(this),P(this),D(m),A(m),F(b),C.checked&&(P(C),A(C),F(_))):(P(this),D(this),A(this)),k&&(S(this),D(this))),h()}),$("."+i.opt.deleteTagClass,s).on("click",function(){var e=$(this).attr("data-checkbox-id"),t=$("#"+e);return t.prop("checked",!1),t.trigger("change"),i._refreshLabel(),o.children(".dna-clone").length||o.removeClass("visible"),!1}),$(".del-on-page").on("click",function(){var e=$(this).attr("data-checkbox-id");$("."+i.opt.deleteTagClass+'[data-checkbox-id="'+e+'"]',s).trigger("click")}),$(".clear",s).on("click",function(){return i.resetList(),!1}),$(".q-sel a",s).on("click",function(){var e=$(this),t=e.attr("data-name"),s=e.attr("data-id"),a={name:t,id:s},r=function(e){i._loadParentTree(e,function(){i._checkCheckBox(s)})};return n(a,i.opt.getParentUrl,r),!1}),$("."+l,s).on("click",function(){return i.applyHandler(this),!1}),$("."+i.opt.clearAllButtonClass,s).on("click",function(e){return e.preventDefault(),i.resetList(),!1})})};return l.prototype={_getAjax:function(e,t){var i=this;e||(e=""),$.ajax({type:"GET",url:i.opt.ajaxUrl,data:e,success:function(e){return"function"!=typeof t?(i.rawData=e,e):(i.rawData=e,void t(e))}})},_renderSublist:function(e,t,i){var n=this,s=0,a=t+"-sub",o=function(e){if(e.length){for(n.curDNA[a]={},s;s2&&l?(r.show(),n({term:t,form:o},a.opt.autoCompleteUrl,h),l=!1):0!=t.length||l||a.$inputFilter.hasClass("ui-autocomplete-input")&&(a.$inputFilter.autocomplete("destroy"),l=!0),!1}).click(function(){return!1})},_loadParentTree:function(e,t,i){var n,s,o,c,l=this,d=e,h=$("#id_"+l.opt.prefix+d.id),u=function(e){var n=$("#id_"+l.opt.prefix+d.id),h=function(){r.hide(),i||0===i?t(i):t()};r.hide(),n.length&&a(l.curDNA[s+"-sub"])==e&&(o={name:d.name,id:d.id},r.show(),c=$("#id_"+l.opt.prefix+d.id).closest(".level").children(".trigger").attr("data-template-id"),l._renderNested(o,h,c,d.id))},p=function(){r.hide(),i||0===i?t(i):t()};r.show(),d.hasOwnProperty("parent")?h.length?(o={name:d.name,id:d.id},c=h.closest(".level").children(".trigger").attr("data-template-id"),l._renderNested(o,function(){r.hide(),t()},c,d.id)):(n={name:d.parent.name,id:d.parent.id},s=$("#id_"+l.opt.prefix+d.parent.id).closest(".level").children(".trigger").attr("data-template-id"),l._renderSublist(n,s,u)):(n={name:d.name,id:d.id},s=$("#id_"+l.opt.prefix+d.id).closest(".level").children(".trigger").attr("data-template-id"),l._renderSublist(n,s,p))},applyHandler:function(){EXPO.events.feed.modalWindow.close()},_refreshLabel:function(){var e=this.selectedWrap.children().length;this.$label.text(this.$label.attr(e?"data-selected":"data-default"))}},e.init=function(e){$.extend(this.opt,e);var n=this,s=function(){$(n.DOMform).find('input[name="~~name~~"]').remove()};"None"!=this.opt.searchData&&this.opt.searchData&&(this.previousSearch=JSON.parse(this.opt.searchData)),this.DOMform=document.getElementById(this.opt.formId),this.DOMhint=document.getElementById(this.opt.filter.hintId),$(this.DOMform).on("submit",function(){s()}),this.DOMapplyButton=document.getElementById(this.opt.applyButtonId),this.filterPane=new i(this.opt.filter),$("#"+this.opt.filter.buttonId).on("click",function(){return t.hasClass(this,n.opt.activeClass)?(t.removeClass(this,n.opt.activeClass),n.filterPane.hide()):(t.addClass(this,n.opt.activeClass),n.filterPane.show()),!1}),$("#"+n.opt.bodyId+" ."+n.opt.modalTriggerClass).on("click",function(e){return e.preventDefault(),n.modalWindow.pullData(this.getAttribute("href")),n.modalWindow.open(),!1}),$("#"+n.opt.applyButtonId).on("click",function(){return $(n.DOMform).submit(),!1}),this.modalWindow=new t.Modal(n.opt.modal),this.placesModal=new l(n.opt.place),this.subjModal=new c(n.opt.subject),$(function(){if(n.previousSearch.inputs.length){$(n.DOMhint).hide();for(var e=0;e