From 56d649946116a8042edc2ae626ae65354e6b1c51 Mon Sep 17 00:00:00 2001 From: Teamcity Date: Wed, 29 Mar 2017 20:10:50 +0500 Subject: [PATCH] Release 2.1.60 --- LICENSE | 1 + app/styles/clearfix.less | 4 +- app/styles/controls/buttonEdit.less | 46 +- app/styles/controls/comboBox.less | 184 +- app/styles/controls/dataGrid.less | 344 +- app/styles/controls/dataNavigation.less | 22 +- .../dateTimePicker/timepicker-seconds.less | 36 +- app/styles/controls/dropdown.less | 18 +- app/styles/controls/fileBox.less | 74 +- app/styles/controls/imageBox.less | 140 +- app/styles/controls/messagebox.less | 94 +- app/styles/controls/panel.less | 34 +- app/styles/controls/popupButton.less | 88 +- app/styles/controls/tabPanel.less | 19 +- app/styles/controls/textbox.less | 24 +- app/styles/controls/treeView.less | 174 +- app/styles/controls/view.less | 4 +- app/styles/loaderIndicator.less | 272 +- app/styles/main.less | 2 +- app/styles/media/images/712.GIF | Bin 26569 -> 0 bytes app/styles/media/images/sort_asc.png | Bin 1118 -> 0 bytes app/styles/media/images/sort_both.png | Bin 1136 -> 0 bytes app/styles/media/images/sort_desc.png | Bin 1127 -> 0 bytes app/styles/mixins/clearfix.less | 12 +- app/styles/mixins/userselect.less | 12 +- app/styles/modal.less | 10 +- bootstrap-framework/js/alert.js | 94 - bootstrap-framework/js/button.js | 120 - bootstrap-framework/js/collapse.js | 211 - bootstrap-framework/js/dropdown.js | 165 - bootstrap-framework/js/modal.js | 356 - bootstrap-framework/js/popover.js | 108 - bootstrap-framework/js/scrollspy.js | 172 - bootstrap-framework/js/tab.js | 155 - bootstrap-framework/js/tooltip.js | 514 - bootstrap-framework/js/transition.js | 59 - bootstrap-framework/less/.csscomb.json | 304 - bootstrap-framework/less/.csslintrc | 19 - bower.json | 20 - example/gulpfile.js/index.js | 2 +- example/www/config.js | 1 + example/www/js/main.js | 135 - example/www/testConfigurations/stab.json | 1 + example/www/testConfigurations/treeview.json | 112 +- example/www/viewExample/tooltip.json | 58 + out/css/main.css | 2 +- out/css/vendor.css | 4 +- out/fonts/FontAwesome.otf | Bin 124988 -> 134808 bytes out/fonts/fontawesome-webfont.eot | Bin 76518 -> 165742 bytes out/fonts/fontawesome-webfont.svg | 3350 +- out/fonts/fontawesome-webfont.ttf | Bin 152796 -> 165548 bytes out/fonts/fontawesome-webfont.woff | Bin 90412 -> 98024 bytes out/fonts/fontawesome-webfont.woff2 | Bin 71896 -> 77160 bytes out/jsonEditor/css/img/jsoneditor-icons.svg | 893 - out/jsonEditor/css/jsoneditor.min.css | 1 - out/jsonEditor/editor.js | 144 - out/jsonEditor/index.html | 28 - out/jsonEditor/jsoneditor.min.js | 48 - out/platform.js | 44602 ++++++++-------- out/platform.min.js | 30 +- out/templates.js | 26 +- out/unitTest.js | 16330 ++++++ out/vendor.js | 494 +- package.json | 37 + 64 files changed, 42548 insertions(+), 27661 deletions(-) delete mode 100644 app/styles/media/images/712.GIF delete mode 100644 app/styles/media/images/sort_asc.png delete mode 100644 app/styles/media/images/sort_both.png delete mode 100644 app/styles/media/images/sort_desc.png delete mode 100644 bootstrap-framework/js/alert.js delete mode 100644 bootstrap-framework/js/button.js delete mode 100644 bootstrap-framework/js/collapse.js delete mode 100644 bootstrap-framework/js/dropdown.js delete mode 100644 bootstrap-framework/js/modal.js delete mode 100644 bootstrap-framework/js/popover.js delete mode 100644 bootstrap-framework/js/scrollspy.js delete mode 100644 bootstrap-framework/js/tab.js delete mode 100644 bootstrap-framework/js/tooltip.js delete mode 100644 bootstrap-framework/js/transition.js delete mode 100644 bootstrap-framework/less/.csscomb.json delete mode 100644 bootstrap-framework/less/.csslintrc delete mode 100644 bower.json delete mode 100644 example/www/js/main.js create mode 100644 example/www/viewExample/tooltip.json delete mode 100644 out/jsonEditor/css/img/jsoneditor-icons.svg delete mode 100644 out/jsonEditor/css/jsoneditor.min.css delete mode 100644 out/jsonEditor/editor.js delete mode 100644 out/jsonEditor/index.html delete mode 100644 out/jsonEditor/jsoneditor.min.js create mode 100644 out/unitTest.js create mode 100644 package.json diff --git a/LICENSE b/LICENSE index dbbe355..9591157 100644 --- a/LICENSE +++ b/LICENSE @@ -659,3 +659,4 @@ specific requirements. if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see . + diff --git a/app/styles/clearfix.less b/app/styles/clearfix.less index d6dd8a6..98afd83 100644 --- a/app/styles/clearfix.less +++ b/app/styles/clearfix.less @@ -1,3 +1,3 @@ -.pl-clearfix { - .clearfix(); +.pl-clearfix { + .clearfix(); } \ No newline at end of file diff --git a/app/styles/controls/buttonEdit.less b/app/styles/controls/buttonEdit.less index 45a7fe1..057bc5c 100644 --- a/app/styles/controls/buttonEdit.less +++ b/app/styles/controls/buttonEdit.less @@ -1,24 +1,24 @@ -.pl-button-edit { - - &-group { - &__control { - &[readonly] { - background-color: @input-bg; - background-image: none; - } - - &[disabled] { - background-color: @input-bg-disabled; - opacity: 1; - } - } - } - &-button { - - &_disabled { - cursor: not-allowed; - .opacity(.65); - .box-shadow(none); - } - } +.pl-button-edit { + + &-group { + &__control { + &[readonly] { + background-color: @input-bg; + background-image: none; + } + + &[disabled] { + background-color: @input-bg-disabled; + opacity: 1; + } + } + } + &-button { + + &_disabled { + cursor: not-allowed; + .opacity(.65); + .box-shadow(none); + } + } } \ No newline at end of file diff --git a/app/styles/controls/comboBox.less b/app/styles/controls/comboBox.less index ac82ac0..63d1658 100644 --- a/app/styles/controls/comboBox.less +++ b/app/styles/controls/comboBox.less @@ -1,92 +1,92 @@ -.pl-combobox { - - .pl-active { - border: 1px solid #c94a4a; - } - - &.pl-focused { - & > .input-group { - & > .pl-control { - border-color: @input-border-focus; - outline: 0; - @color-rgba: rgba(red(@input-border-focus), green(@input-border-focus), blue(@input-border-focus), .6); - .box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}"); - } - } - } -} - -.pl-combobox-filter-text { - &:focus { - border: 1px solid @input-border; - .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); - } -} -.pl-combobox.pl-disabled { - - .pl-control { - background: @input-bg-disabled; - cursor: @cursor-disabled; - } - - .pl-combobox__clear { - cursor: @cursor-disabled; - } - - .pl-combobox__grip { - cursor: @cursor-disabled; - } -} - -.pl-combobox-items { - overflow-y:auto; - max-height: 30vh; - cursor: pointer; - text-indent: 5px; -} - -.pl-combobox-items > span:hover { - background-color: @pl-primary2; -} - -.pl-combobox-items > .pl-combobox-selected { - // border-left: 4px solid #39b3d7; - background-color: @pl-background4; -} - -.pl-combobox-items > .pl-combobox-checked { - background: @table-bg-active; -} - -.pl-combobox-dropdown { - position: relative; - background: #FFFFFF; - border-left: 1px solid #cccccc; - border-right: 1px solid #cccccc; - border-bottom: 1px solid #cccccc; - padding: 5px; - margin-top: 1px; -} - -.pl-combobox-dropdown.dropdown-direction-down { - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; - border-bottom: 1px solid #cccccc; -} - -.pl-combobox-dropdown.dropdown-direction-up { - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-top: 1px solid #cccccc; -} - -.pl-combobox__value { - position: absolute; - left: @padding-base-horizontal; - right: 0; - overflow: hidden; - - &>.pl-label { - max-width: 100%; - } -} +.pl-combobox { + + .pl-active { + border: 1px solid #c94a4a; + } + + &.pl-focused { + & > .input-group { + & > .pl-control { + border-color: @input-border-focus; + outline: 0; + @color-rgba: rgba(red(@input-border-focus), green(@input-border-focus), blue(@input-border-focus), .6); + .box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}"); + } + } + } +} + +.pl-combobox-filter-text { + &:focus { + border: 1px solid @input-border; + .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); + } +} +.pl-combobox.pl-disabled { + + .pl-control { + background: @input-bg-disabled; + cursor: @cursor-disabled; + } + + .pl-combobox__clear { + cursor: @cursor-disabled; + } + + .pl-combobox__grip { + cursor: @cursor-disabled; + } +} + +.pl-combobox-items { + overflow-y:auto; + max-height: 30vh; + cursor: pointer; + text-indent: 5px; +} + +.pl-combobox-items > span:hover { + background-color: @pl-primary2; +} + +.pl-combobox-items > .pl-combobox-selected { + // border-left: 4px solid #39b3d7; + background-color: @pl-background4; +} + +.pl-combobox-items > .pl-combobox-checked { + background: @table-bg-active; +} + +.pl-combobox-dropdown { + position: relative; + background: #FFFFFF; + border-left: 1px solid #cccccc; + border-right: 1px solid #cccccc; + border-bottom: 1px solid #cccccc; + padding: 5px; + margin-top: 1px; +} + +.pl-combobox-dropdown.dropdown-direction-down { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom: 1px solid #cccccc; +} + +.pl-combobox-dropdown.dropdown-direction-up { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-top: 1px solid #cccccc; +} + +.pl-combobox__value { + position: absolute; + left: @padding-base-horizontal; + right: 0; + overflow: hidden; + + &>.pl-label { + max-width: 100%; + } +} diff --git a/app/styles/controls/dataGrid.less b/app/styles/controls/dataGrid.less index 0e5cf70..c966f6f 100644 --- a/app/styles/controls/dataGrid.less +++ b/app/styles/controls/dataGrid.less @@ -1,172 +1,172 @@ -.clearfix() { - &:after { - content: ""; - display: table; - clear: both; - } -} - -.pl-datagrid { - - .sortable { - cursor: pointer; - } - - .sorted { - position: relative; - padding-right: 18px; - } - - .headerTemplate-sorted-asc:after, .headerTemplate-sorted-desc:after { - position: absolute; - right: 5px; - top: calc(~"50% - 10px"); - display: inline-block; - font-family: FontAwesome; - } - - .headerTemplate-sorted-asc:after { - content: "\f0d8"; - } - - .headerTemplate-sorted-desc:after { - content: "\f0d7"; - } - - .sorted-asc, .sorted-desc { - span:after { - display: inline-block; - font-family: FontAwesome; - margin-left: 5px; - } - } - .sorted-asc { - span:after { - content: "\f0d8"; - } - } - - .sorted-desc { - span:after { - content: "\f0d7"; - } - } - - &_layout { - - &_fixed { - .pl-datagrid-table { - table-layout: fixed; - } - - } - } - - &_select { - &_single { - .pl-datagrid-toggle_all { - display: none; - } - } - } - - &_selectors { - - &_show { - .pl-datagrid-row__cell_checker, .pl-datagrid-row__cell_toggle { - width: 40px; - display: table-cell; - } - } - - &_hide { - .pl-datagrid-row__cell_checker, .pl-datagrid-row__cell_toggle { - width: 0; - display: none; - } - } - - } - - &__body { - //overflow-y: scroll; - //overflow-x: auto; - } - - &.verticalAlignment { - &Top { - table > tbody > tr > td { - vertical-align: top; - } - } - - &Center { - table > tbody > tr > td { - vertical-align: middle; - } - } - - &Bottom { - table > tbody > tr > td { - vertical-align: bottom; - } - } - - &Stretch { - table > tbody > tr > td { - vertical-align: middle; - } - } - } - table { - /*table-layout: fixed;*/ - } - - //.pl-toggle-cell{ - // width: 30px; - //} - -} - -.pl-datagrid.verticalAlignmentStretch { - - overflow-x: hidden; - - //При вытягивании по вертикали заголовки колонок становятся фикированными - для этого table-layout = fixed - - .pl-datagrid-table { - table-layout: fixed; - } - - .pl-datagrid__body { - overflow-y: scroll; - overflow-x: auto; - } - -} - - -.pl-datagrid-table { - margin-bottom: 0; - - &_body { - border-top: 0!important; - } -} - -.pl-datagrid-container { - &_head { - overflow-x: hidden; - } -} - -.pl-datagrid-row { - &__cell { - overflow: hidden; - - &_width { - padding: 0!important; - border: 0!important; - } - } -} +.clearfix() { + &:after { + content: ""; + display: table; + clear: both; + } +} + +.pl-datagrid { + + .sortable { + cursor: pointer; + } + + .sorted { + position: relative; + padding-right: 18px; + } + + .headerTemplate-sorted-asc:after, .headerTemplate-sorted-desc:after { + position: absolute; + right: 5px; + top: calc(~"50% - 10px"); + display: inline-block; + font-family: FontAwesome; + } + + .headerTemplate-sorted-asc:after { + content: "\f0d8"; + } + + .headerTemplate-sorted-desc:after { + content: "\f0d7"; + } + + .sorted-asc, .sorted-desc { + span:after { + display: inline-block; + font-family: FontAwesome; + margin-left: 5px; + } + } + .sorted-asc { + span:after { + content: "\f0d8"; + } + } + + .sorted-desc { + span:after { + content: "\f0d7"; + } + } + + &_layout { + + &_fixed { + .pl-datagrid-table { + table-layout: fixed; + } + + } + } + + &_select { + &_single { + .pl-datagrid-toggle_all { + display: none; + } + } + } + + &_selectors { + + &_show { + .pl-datagrid-row__cell_checker, .pl-datagrid-row__cell_toggle { + width: 40px; + display: table-cell; + } + } + + &_hide { + .pl-datagrid-row__cell_checker, .pl-datagrid-row__cell_toggle { + width: 0; + display: none; + } + } + + } + + &__body { + //overflow-y: scroll; + //overflow-x: auto; + } + + &.verticalAlignment { + &Top { + table > tbody > tr > td { + vertical-align: top; + } + } + + &Center { + table > tbody > tr > td { + vertical-align: middle; + } + } + + &Bottom { + table > tbody > tr > td { + vertical-align: bottom; + } + } + + &Stretch { + table > tbody > tr > td { + vertical-align: middle; + } + } + } + table { + /*table-layout: fixed;*/ + } + + //.pl-toggle-cell{ + // width: 30px; + //} + +} + +.pl-datagrid.verticalAlignmentStretch { + + overflow-x: hidden; + + //При вытягивании по вертикали заголовки колонок становятся фикированными - для этого table-layout = fixed + + .pl-datagrid-table { + table-layout: fixed; + } + + .pl-datagrid__body { + overflow-y: scroll; + overflow-x: auto; + } + +} + + +.pl-datagrid-table { + margin-bottom: 0; + + &_body { + border-top: 0!important; + } +} + +.pl-datagrid-container { + &_head { + overflow-x: hidden; + } +} + +.pl-datagrid-row { + &__cell { + overflow: hidden; + + &_width { + padding: 0!important; + border: 0!important; + } + } +} diff --git a/app/styles/controls/dataNavigation.less b/app/styles/controls/dataNavigation.less index 307afee..1d80c11 100644 --- a/app/styles/controls/dataNavigation.less +++ b/app/styles/controls/dataNavigation.less @@ -1,12 +1,12 @@ -.pl-data-navigation { - .clearfix(); - - .pl-data-navigation-pager { - - } - - .pl-data-navigation-size { - float: right; - margin: 20px 0; - } +.pl-data-navigation { + .clearfix(); + + .pl-data-navigation-pager { + + } + + .pl-data-navigation-size { + float: right; + margin: 20px 0; + } } \ No newline at end of file diff --git a/app/styles/controls/dateTimePicker/timepicker-seconds.less b/app/styles/controls/dateTimePicker/timepicker-seconds.less index 28b65aa..9af38e8 100644 --- a/app/styles/controls/dateTimePicker/timepicker-seconds.less +++ b/app/styles/controls/dateTimePicker/timepicker-seconds.less @@ -1,19 +1,19 @@ -.timepicker-seconds { - - cursor: pointer; - - .second { - padding: 10px; - } - - .second-unavailable { - background-color: #dddddd; - cursor: not-allowed; - color: #777777; - opacity: 1; - } - - .second-selected { - border: 1px solid #FF0000; - } +.timepicker-seconds { + + cursor: pointer; + + .second { + padding: 10px; + } + + .second-unavailable { + background-color: #dddddd; + cursor: not-allowed; + color: #777777; + opacity: 1; + } + + .second-selected { + border: 1px solid #FF0000; + } } \ No newline at end of file diff --git a/app/styles/controls/dropdown.less b/app/styles/controls/dropdown.less index 1ae8552..aa74e66 100644 --- a/app/styles/controls/dropdown.less +++ b/app/styles/controls/dropdown.less @@ -1,9 +1,9 @@ -.pl-dropdown-container { - z-index: 2000; - position: absolute; - - .pl-dropdown-content { - z-index: 2001; - } -} - +.pl-dropdown-container { + z-index: 2000; + position: absolute; + + .pl-dropdown-content { + z-index: 2001; + } +} + diff --git a/app/styles/controls/fileBox.less b/app/styles/controls/fileBox.less index 88058a0..4fc8594 100644 --- a/app/styles/controls/fileBox.less +++ b/app/styles/controls/fileBox.less @@ -1,37 +1,37 @@ -.pl-file-box { - - .input-group { - display: block; - - .form-control { - display: block; - width: calc(~"100% - 40px"); - } - } - - .input-group-btn { - width: 100%; - - .btn { - width: 40px; - } - } - - .pl-filebox-file-upload, .pl-filebox-file-empty, .pl-filebox-file-download-url { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } - - .pl-filebox-file-upload { - color: @btn-link-disabled-color; - } - .pl-filebox-file-empty { - color: @btn-link-disabled-color; - } - - .pl-filebox-file-download-url{ - width: 100%; - display: block; - } -} +.pl-file-box { + + .input-group { + display: block; + + .form-control { + display: block; + width: calc(~"100% - 40px"); + } + } + + .input-group-btn { + width: 100%; + + .btn { + width: 40px; + } + } + + .pl-filebox-file-upload, .pl-filebox-file-empty, .pl-filebox-file-download-url { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + .pl-filebox-file-upload { + color: @btn-link-disabled-color; + } + .pl-filebox-file-empty { + color: @btn-link-disabled-color; + } + + .pl-filebox-file-download-url{ + width: 100%; + display: block; + } +} diff --git a/app/styles/controls/imageBox.less b/app/styles/controls/imageBox.less index 32c153d..153380b 100644 --- a/app/styles/controls/imageBox.less +++ b/app/styles/controls/imageBox.less @@ -1,67 +1,73 @@ -.pl-imagebox { - - .pl-image { - position: relative; - width: 150px; - height: 150px; - overflow: hidden; - - img { - left: 50%; - top: 50%; - position: relative; - transform: translateX(-50%) translateY(-50%); - } - } - - .pl-image-file { - text-align: center; - - .pl-image-file-upload-button { - cursor: pointer; - } - } - - .pl-image-file-input { - width: 0.1px; - height: 0.1px; - opacity: 0; - overflow: hidden; - position: absolute; - z-index: -1; - } - - .pl-image-remove { - position: absolute; - top: 0; - right: 0; - cursor: pointer; - - &:after { - color: @pl-accent-danger; - content: "\2716"; - } - } - - &.pl-empty { - .pl-image-remove { - display: none; - } - - .pl-image { - display: none; - } - - } - - &.pl-disabled { - .pl-image-remove { - display: none; - } - - .pl-image-file { - display: none; - } - } -} - +.pl-imagebox { + + .pl-image { + position: relative; + width: 150px; + height: 150px; + + .pl-image-wrapper { + position: relative; + width: 100%; + height: 100%; + overflow: hidden; + + img { + left: 50%; + top: 50%; + position: relative; + transform: translateX(-50%) translateY(-50%); + } + } + } + + .pl-image-file { + text-align: center; + + .pl-image-file-upload-button { + cursor: pointer; + } + } + + .pl-image-file-input { + width: 0.1px; + height: 0.1px; + opacity: 0; + overflow: hidden; + position: absolute; + z-index: -1; + } + + .pl-image-remove { + position: absolute; + top: 0; + right: 0; + cursor: pointer; + + &:after { + color: @pl-accent-danger; + content: "\2716"; + } + } + + &.pl-empty { + .pl-image-remove { + display: none; + } + + .pl-image { + display: none; + } + + } + + &.pl-disabled { + .pl-image-remove { + display: none; + } + + .pl-image-file { + display: none; + } + } +} + diff --git a/app/styles/controls/messagebox.less b/app/styles/controls/messagebox.less index 7907178..cdef634 100644 --- a/app/styles/controls/messagebox.less +++ b/app/styles/controls/messagebox.less @@ -1,48 +1,48 @@ -.modal { - &.messagebox { - top: 25%; - - z-index: @zindex-modal + 10; - - + .modal-backdrop { - z-index: @zindex-modal + 5; - } - } -} - -.pl-messagebox { - - &_error {} - - &_warning {} - - &_default {} - -} - -.pl-messagebox-content { - - &__icon { - - &_error { - color: @brand-danger; - } - - &_warning { - color: @brand-warning - } - - &_default { - color: @brand-info; - } - - } -} - -.pl-messagebox-button { - - &_default {} - - &_action {} - +.modal { + &.messagebox { + top: 25%; + + z-index: @zindex-modal + 10; + + + .modal-backdrop { + z-index: @zindex-modal + 5; + } + } +} + +.pl-messagebox { + + &_error {} + + &_warning {} + + &_default {} + +} + +.pl-messagebox-content { + + &__icon { + + &_error { + color: @brand-danger; + } + + &_warning { + color: @brand-warning + } + + &_default { + color: @brand-info; + } + + } +} + +.pl-messagebox-button { + + &_default {} + + &_action {} + } \ No newline at end of file diff --git a/app/styles/controls/panel.less b/app/styles/controls/panel.less index 66f8ee3..9ad0a48 100644 --- a/app/styles/controls/panel.less +++ b/app/styles/controls/panel.less @@ -1,18 +1,18 @@ -.pl-panel { - - .pl-panel-header { - cursor: default; - } - - .pl-panel-header.pl-collapsed + .pl-panel-body { - display: none; - } - - .pl-panel-header.pl-collapsible { - cursor: pointer; - } - - .pl-panel-i { - .clearfix(); - } +.pl-panel { + + .pl-panel-header { + cursor: default; + } + + .pl-panel-header.pl-collapsed + .pl-panel-body { + display: none; + } + + .pl-panel-header.pl-collapsible { + cursor: pointer; + } + + .pl-panel-i { + .clearfix(); + } } \ No newline at end of file diff --git a/app/styles/controls/popupButton.less b/app/styles/controls/popupButton.less index 562ae2f..ab5175b 100644 --- a/app/styles/controls/popupButton.less +++ b/app/styles/controls/popupButton.less @@ -1,44 +1,44 @@ -/*.pl-popup-button__items { - background: #ffffff; - position: relative; - border: 1px solid @btn-default-border; - border-radius: @btn-border-radius-base; - - .btn { - width: 100%; - } - -} - -.backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; -} - -.pl-popup-button-dropdown { - position: absolute; - z-index: 1000; -}*/ - -.pl-popup-button__dropdown{ - position: absolute; - top: 0; - left: 0; - z-index: 1000; -} - -.pl-popup-button__item:after { - content: ""; - clear: both; - display: table; -} - -.pl-popup-button__items { - - > li > a { - width: 100%; - } -} +/*.pl-popup-button__items { + background: #ffffff; + position: relative; + border: 1px solid @btn-default-border; + border-radius: @btn-border-radius-base; + + .btn { + width: 100%; + } + +} + +.backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +.pl-popup-button-dropdown { + position: absolute; + z-index: 1000; +}*/ + +.pl-popup-button__dropdown{ + position: absolute; + top: 0; + left: 0; + z-index: 1000; +} + +.pl-popup-button__item:after { + content: ""; + clear: both; + display: table; +} + +.pl-popup-button__items { + + > li > a { + width: 100%; + } +} diff --git a/app/styles/controls/tabPanel.less b/app/styles/controls/tabPanel.less index ee40a39..be6b411 100644 --- a/app/styles/controls/tabPanel.less +++ b/app/styles/controls/tabPanel.less @@ -1,5 +1,14 @@ -.pl-tabpanel { - .pl-tabpage-i { - .clearfix(); - } -} +.pl-tabpanel { + .pl-tabpage-i { + .clearfix(); + } + + .pl-tabheader.pl-disabled { + background: @input-bg-disabled; + cursor: @cursor-disabled; + + a:hover { + color: @link-color; + } + } +} diff --git a/app/styles/controls/textbox.less b/app/styles/controls/textbox.less index c51898e..35cd491 100644 --- a/app/styles/controls/textbox.less +++ b/app/styles/controls/textbox.less @@ -1,12 +1,12 @@ -.pl-textbox { - textarea.pl-control { - resize: none; - } - - .pl-control-editor { - textarea.pl-control-editor { - resize: none; - } - } - -} +.pl-textbox { + textarea.pl-control { + resize: none; + } + + .pl-control-editor { + textarea.pl-control-editor { + resize: none; + } + } + +} diff --git a/app/styles/controls/treeView.less b/app/styles/controls/treeView.less index c9024bf..b7d63d4 100644 --- a/app/styles/controls/treeView.less +++ b/app/styles/controls/treeView.less @@ -1,88 +1,88 @@ -.pl-treeview { - - &_multi-select { - - } - - &_single-select { - - } - -} - -.pl-treeview-node { - &__button { - display:inline-block; - font: normal normal normal 14px/1 FontAwesome; - .user-select(none); - - &_expand { - &:before { - content: "\f196"; - } - } - - &_collapse { - &:before { - content: "\f147"; - } - } - } - - &__item { - display: inline-block; - } - - &__items { - margin-left: 20px; - - &_expanded { - display: block; - } - - &_collapsed { - display: none; - } - } - -} - -.pl-treeview-item { - &__checker { - display: inline-block; - font: normal normal normal 14px/1 FontAwesome; - .user-select(none); - - &_checkbox { - &:before { - content: "\f096"; - } - } - - &_checkbox&_checked { - &:before{ - content: "\f14a"; - } - } - - &_radio { - display: none;//nothing - } - - &_radio&_checked { - display: none;//nothing - } - - } - - &__content { - display: inline-block; - cursor: pointer; - - &_selected { - color: @list-group-active-color; - background-color: @list-group-active-bg; - border-color: @list-group-active-border; - } - } +.pl-treeview { + + &_multi-select { + + } + + &_single-select { + + } + +} + +.pl-treeview-node { + &__button { + display:inline-block; + font: normal normal normal 14px/1 FontAwesome; + .user-select(none); + + &_expand { + &:before { + content: "\f196"; + } + } + + &_collapse { + &:before { + content: "\f147"; + } + } + } + + &__item { + display: inline-block; + } + + &__items { + margin-left: 20px; + + &_expanded { + display: block; + } + + &_collapsed { + display: none; + } + } + +} + +.pl-treeview-item { + &__checker { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + .user-select(none); + + &_checkbox { + &:before { + content: "\f096"; + } + } + + &_checkbox&_checked { + &:before{ + content: "\f14a"; + } + } + + &_radio { + display: none;//nothing + } + + &_radio&_checked { + display: none;//nothing + } + + } + + &__content { + display: inline-block; + cursor: pointer; + + &_selected { + color: @list-group-active-color; + background-color: @list-group-active-bg; + border-color: @list-group-active-border; + } + } } \ No newline at end of file diff --git a/app/styles/controls/view.less b/app/styles/controls/view.less index 5be5a5c..2291780 100644 --- a/app/styles/controls/view.less +++ b/app/styles/controls/view.less @@ -1,3 +1,3 @@ -.pl-view { - .clearfix(); +.pl-view { + .clearfix(); } \ No newline at end of file diff --git a/app/styles/loaderIndicator.less b/app/styles/loaderIndicator.less index 1298df7..cf283df 100644 --- a/app/styles/loaderIndicator.less +++ b/app/styles/loaderIndicator.less @@ -1,136 +1,136 @@ - -.blockPage{ - border-width: 0!important; - background-color: rgba(0,0,0,0)!important; -} - -.blockOverlay{ - background-color: rgb(255, 255, 255)!important; -} - -.blockUI { - @width: 100px; - @halfWidth: @width / 2; - @height: 100px; - @halfHeight: @height / 2; - - position: fixed; - padding: 0px; - margin: -@halfHeight 0 0 -@halfWidth; - width: @width; - top: 50%; - left: 50%; - text-align: center; - color: rgb(0, 0, 0); - cursor: default; - opacity: 0.8; - - #loaderIndicator { - width: @width; - height: @height; - } -} - -.cssload-spin-box { - position: absolute; - margin: auto; - left: 0; - top: 0; - bottom: 0; - right: 0; - width: 15px; - height: 15px; - border-radius: 100%; - box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); - -o-box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); - -ms-box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); - -webkit-box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); - -moz-box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); - animation: cssload-spin ease infinite 4.6s; - -o-animation: cssload-spin ease infinite 4.6s; - -ms-animation: cssload-spin ease infinite 4.6s; - -webkit-animation: cssload-spin ease infinite 4.6s; - -moz-animation: cssload-spin ease infinite 4.6s; -} - - - -@keyframes cssload-spin { - 0%, - 100% { - box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); - } - 25% { - box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73); - } - 50% { - box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223); - } - 75% { - box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49; - } -} - -@-o-keyframes cssload-spin { - 0%, - 100% { - box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); - } - 25% { - box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73); - } - 50% { - box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223); - } - 75% { - box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49; - } -} - -@-ms-keyframes cssload-spin { - 0%, - 100% { - box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); - } - 25% { - box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73); - } - 50% { - box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223); - } - 75% { - box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49; - } -} - -@-webkit-keyframes cssload-spin { - 0%, - 100% { - box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); - } - 25% { - box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73); - } - 50% { - box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223); - } - 75% { - box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49; - } -} - -@-moz-keyframes cssload-spin { - 0%, - 100% { - box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); - } - 25% { - box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73); - } - 50% { - box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223); - } - 75% { - box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49; - } -} + +.blockPage{ + border-width: 0!important; + background-color: rgba(0,0,0,0)!important; +} + +.blockOverlay{ + background-color: rgb(255, 255, 255)!important; +} + +.blockUI { + @width: 100px; + @halfWidth: @width / 2; + @height: 100px; + @halfHeight: @height / 2; + + position: fixed; + padding: 0px; + margin: -@halfHeight 0 0 -@halfWidth; + width: @width; + top: 50%; + left: 50%; + text-align: center; + color: rgb(0, 0, 0); + cursor: default; + opacity: 0.8; + + #loaderIndicator { + width: @width; + height: @height; + } +} + +.cssload-spin-box { + position: absolute; + margin: auto; + left: 0; + top: 0; + bottom: 0; + right: 0; + width: 15px; + height: 15px; + border-radius: 100%; + box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); + -o-box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); + -ms-box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); + -webkit-box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); + -moz-box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); + animation: cssload-spin ease infinite 4.6s; + -o-animation: cssload-spin ease infinite 4.6s; + -ms-animation: cssload-spin ease infinite 4.6s; + -webkit-animation: cssload-spin ease infinite 4.6s; + -moz-animation: cssload-spin ease infinite 4.6s; +} + + + +@keyframes cssload-spin { + 0%, + 100% { + box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); + } + 25% { + box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73); + } + 50% { + box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223); + } + 75% { + box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49; + } +} + +@-o-keyframes cssload-spin { + 0%, + 100% { + box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); + } + 25% { + box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73); + } + 50% { + box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223); + } + 75% { + box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49; + } +} + +@-ms-keyframes cssload-spin { + 0%, + 100% { + box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); + } + 25% { + box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73); + } + 50% { + box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223); + } + 75% { + box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49; + } +} + +@-webkit-keyframes cssload-spin { + 0%, + 100% { + box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); + } + 25% { + box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73); + } + 50% { + box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223); + } + 75% { + box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49; + } +} + +@-moz-keyframes cssload-spin { + 0%, + 100% { + box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223); + } + 25% { + box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73); + } + 50% { + box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223); + } + 75% { + box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49; + } +} diff --git a/app/styles/main.less b/app/styles/main.less index f041f39..be2613a 100644 --- a/app/styles/main.less +++ b/app/styles/main.less @@ -1,4 +1,4 @@ -// переменные путей до некоторых файлов +// переменные путей до некоторых файлов @pl-override-platform-variables-path: "some.less"; @pl-override-bootstrap-variables-path: "some.less"; @pl-bootstrap-theme-path: "../../bootstrap-framework/less/theme.less"; diff --git a/app/styles/media/images/712.GIF b/app/styles/media/images/712.GIF deleted file mode 100644 index d8310f89cbc4b8bf2ba4f9b41e85b46600685c3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26569 zcmeF&c{r5+!~gyBoPEYN24gHS_MIUlNi)_V%1)@pu0ms}Y}GmTEg`a`8bY=-mLy3t zwvbA+s8mCWq*AFQ>Gt`2zTeOFz3$)jz3$(2-~Zglecbc+9OrRxFy~{QulH$dXJfM2 zFAxX>ssTW`ro3=$#J96;WPT=bps(%4dd#L!0xsO>u(tD>zbZiT3K~yZ)|+}AZDOz=JQg{-4VCWMzf}> z!bc;%-Rl=$NF45Ko1R=)S-*H=*g)6h=Y{e|4;o)g=8Ubsv(2of>i6&8!2kTE@LOPq zwVSIY&B@w8mjVaZub}V)ffWXH0qsAo_Q#J2pw_6xOuDx8$-%1aJ2CY1By4$`J&M>VB_{>bY`STK(&&G#B%tWQ*%N!0PEdwPX^#mCym?|NCW4Tu`=$gA z(vROhv1mh~4q7vxV}w8DGN{&#&uTpn`5%3Y(6-h+{9xkHL^0DY*{^QC+MDHsO-Jl^ zxm)SN>S;SHW#P+x!jc{QRJaPM}!H&5+GhPn3v`?*9eFUMd!{r@n-Qs zni@9y@vvZBP@-JXuS859L^z6Bw~cFOvP2~x-#{pw-kY9gDk(^ZE$y(sWbMY$D$xS7 zI&DXbRBWj7H`xSGM4zhgb~{nd(91fE&#FJG6fDQ;cQ_F!NpfL?&HD8r`evnLZ$O(M^f}? z|L5I|$o?xVm=_5G!16UR)lGB`L7v8m)Gn4u@E9RGcYuY|6c8ys3SkrtodE10JC90x zKw&r@w=&Fwu=3*jl91F+CmNtd(WuOjY;&;=5%ONd6A9$SGrrd-?no3oXVfBJIML}1 zTGGuKI<>?28Vm+cG_fklejN>>?FfDXFzk|vkbnp*85R>r+&72b;8xL-kz-JA;cic7 zOm31yc%>n5WIT)}u$0ciVa2`YN{Mdz)H6B8KLSA)#R>>Xj4cV#dE86|)94Jc1q@xT zp;@X^yQl)&*;%T2ifqW(Ckpo-yJfLe!;OXxke+WSO;gR|<7LHxr25(xDWKf3`bfsL zwWkO&bY-*>5~wHHejZ_@N@Gox^HP zsMwwLuo2ghOo!f?9fiO&W(0=AO4sKQ#KV{3_2@ zP6Jiw8S&$F@x~Xoj?1z~f6Sgs7haj|rZc#JW>wS5eB;&J1Fy79$UoN>+8*!uiB?)T zz(p1=HL*T&f9sm5%o?480fTCnS3i%y884n|k|FBSxTpNDuaCB0wy-HnUbO`rSMSHZZI-0FAQp_%BaS=G4k@u15~9- zg>?N1g_)B9b4)ym+vUVWW2@rt-rF{7ySsnQ__Po<<> z*OQamd-V0efncTMcVr&x_B=%HaDo9T+D?A?1y6 z8Yv!{44}?xMrvGjFk+xNmCol{EBzRaJJDQj_%KOBMaouGxvq$*d{I_pw#7&HK`vPI z+Mt;Q-gD#vs1g8IhOKe^kYCekP~)j#m)hdN03`To5@Un+O@hUZu8z!@7kcls7KVyR zeC}?o(GhPa;ed81*r3-qg)q}{E^XnheRUidBe&4}gu*r4Vs8?x;F3o$>OsJ^4?Ix3 zUr^vUqYIyQKN!_V^ggS!TjBf2eG3;v%tjr}PZNbaA-CFs16n&m=65N25lhRoA8S>_ zdks1k~n#IZ+$ zRrF)p-ruCy+Po)vO2gXD;Y;zW_Zdz2T{b(SB?pH$!X{4U85hJO~s2uT3S33?RdC02c zb%b4W%Tb^{2@Fco_VL|h)jF=;6;+&jn-UXcOW{JX zwz`LWtb%&7kBunK12GuhYan>zt-1}9r{_KWipA>k?gF3i!unwXRlT%C9 z&X~M)&o-u;O*Gax^Z+3|+UhWo*Zw;DT*S3UkDSIzcf@*?KzT{2a1>fbmNRh_fw+DH zoDi1!Ro#*&lzL=ODD(R;2p38m41AszsCqB|hf z)=a*LZ@llz6URz%xe(Cl&VwcCDUVj7^{jX=@ERPqQ8BdLEa;}JFP6Ml({B`j3kEs` zqEt+sQsFpNh@FjPLtvh@m$)0u!2T*%VA47zJCW`Hzz~w+Sj$Yo6h;hEyd;oD%j0J>8C3QSI^|ZdLG-MiNYZ z=}1bPS_(Tj-#U#Ej8fpR?x7qlo@nO48K!**m6;MWT0nJx2U9B9uUyYPCv5?`5hEcu z)A&bCwj3QhgV=Z)yu>Iel3uu+fy4JQJ(=7juxUW*Vv-ykuxMM$b@1fY-aMBTijt>f zGzGy)4VHo8$4$x=J z;s-ap>Rx72+keErzfK9IP@4lw(vvPYnPXk;(TPxSCa(uL(HP650Jx~`xVLU3hY?-4 z=~b?QtiNJo7*_U`K26|J51ETmy4VY18rw50Smu6ARz9V?Ek;2%A@8f3Yz~==>$SR+ z9w$^Y9{OB-XzO5G*Vp&oUqa{|gVCcB5zABQ?{*J@WWztGV!0zHPS|aoDkUKwG!7~S zGGGM=NH-o;aZ1<}uGl#H1x2V*VR~IK-M=jC@T?bdbUrHA__9X<}M*GSW*}1wR-srS> zd9MFu*XrliJ;zLELoRPyd7#Ciet#u)9@uruY!Zn;t_H~eOuH!X;r_v6_`q|Y1xtjV zzyBD&`i_clJ92I$ZZ!E!fa9!#XXj`UGp1UMcP%)zgV^pAnZod$2_{|piT#jfGEyP@ zWk9C;(}0h$b{_!4Tby6guso!=-CR45)y;MCmKempv!~K5OrZ5IVi3}T19CRc0<#L_ z)Pj-%Y$!E*7XrfVU^K+&kPqKcV#C*xGSUf7CaU)mhLy;uSYw>934|z145D12L!wObet%7sRo|;-*oBsYAU*^lpdriP zu`;O+H=YaA%w?cCfk5I8e1lrsfP^4|=W6I~TB7?0iJ*4lKh{d#}rvvd6Ll684N?J7LE8xcu4A zUch~Qvyj5ZGeM#*Yk5%ibaN4LnJPgpz3p2+8z#X%`x!-b@y?0@rnbwySa|?wM-WaL z1f?z`c8%?!J14!}cUK}<)NPh_31{v~rTW!tZb=o5D=eA+?I3kGHdX*3VZsG9xiEua z#-Xbz8&odyAw0(*`$Kv0RoxUY&t=N%VxU~S#oXvWX2V{)^?-AmhtzA8_y>|8T9s%269qFt9VYA%r~k@BE2ryjjA!|5c#qirv`Dk9^`5kf+XjvS*ZFJ0 z#d1UuPUe&6y>4RMaPnE7U9C@2R1FQ!cQzfoqG-N&`0>F!!H*j0T8Q-1SH0Lr`Juns zy;p{=L_qIfB=)+oJ`*U{YzqC4syIDgt|^AJTf<~aH&x%|@LA2*4-$+MCXs5qYt4=# zi5D#z!1kt$uIC@d)+U|_Egq3JhwBHr$vj&wy(;-xY_C@l=E0}UjDBORLE5EJzTH!k zD{ZS3#6fL^iMy8*+0|;FADtlxGuzrN2j-*3qi@Py&mDe?7elS!ni2Ot-dYBDWxqOm zNxdS4hu)+lPL+q4EECG#vZBtXQeE|XqDPP2#ecENne%DpT5Jt+#Q(EY=>Om4%YU*< z%fGeDI&1#7?9%lA)Gq7)<)}4o$zOa4bckZc5a5M>@g;15kK@9?$2NbI7PZT!_|4Z} zE>67pggm}$yyMu;YO@D>DIx)hsc9DI!&%xX>A6+}En#7;I1hPk*5PC?8DXq0{Pan; zbJ(35q|u(4j01`%?DG{>uc&TluCgUa?qsutuhG$p2afdEs$-F=BdSuu7dowFL~mYX z%X^5I4&=BK;8N{(v4i72(i6H^HfqdP{&*S4ahFlJa#v1Oq+!m+VRt|=AJ(OK$#=sA z#i}PP|*+MWn*`&ZXd(hY@p4iH4e@??1ejv!ELBt8!XWTbUO1VW?)Z&kglBh zOyL-24Y?QbOltIW-^pg+WnRhwriPl#F}Pc>9J4jP*@BJ*Fu z#SfqI3PT&dvQeBAf6faF1aoSx82An*y7r3oU)-@JSOLil<`0ay&s<*@VqPiJDNjEDY*aE~=T$d4UwrX0no-*PNKr zLG6Levl5aid=P>6VpCyrNAbLDoWUFydH?yT3Dfr-9B(2alrwpxTfYs$;Jotu^YQ8w zs)S@HJ|J1ZxC54=-#EGpt>(K}DnUrh8(>_~=HijM<+YXhAr^U53Aj3@I>$hm%8J># z<`13z_~M-9bV^ivF1XS_*C~K1N$R_W+9BuW3_FK=s&UaSjry7>N!_Jcc+tRws&aj1=oQVk zByYOqs$3lx{x$LkD`{s>+k*wju8qa6fp-VZvHX}Z`@w}X(Ki)c&BuIa)dsIMBv zO~b+~PdLU_N%mq#v}(f$@00k`Bx_sP+~HbT9NjI7^kR%0<{YRJ&_Tc z?<0rnNj=HV)&~1WpN^H$5HmJcc!iC-8PNRzZ1`aG%~YLl6M@A?F)=b#m%cp>yZru& z(i>+g4~!b$dgOWR%dJ`0Pc8kymo3n~U~CR037IC7yF8V($vg=la`-P$7f#PJlPSTu zKi<^myobR_&|PS*qIk#3T=khn+T|TRPgdS#TgZZIj{~fkoo_o%3Byp=14e1DFJIJJ z?LF;k(hl!ZyZQ6;u-b7`jQZZ&AD1qDxy`=QX~O*Zt@>tO*LPA0hx)0v`1gUFHd_ha zcT()fV?P%U-UD=tTo3+!=T!4@eD>P+o7cbp?uF2A`mS=N77r%3Zl5CD;-X9!nTqrY z!c!X>uKPVc@;3Ro;WGFoW)YC*o_k_L?;(^i{cnOk6HTf;7I|Fx#>g_%;YVVLcm~41 zgMUYzqKV3<96=A z_D+&AbSl<_-@nyD6i$K4q(;sB#3`W7yz|LDiLA{jk5nvbvb|5oc&T2h z0Wo-fCTD3z&6b^IRskLAZ#aDhMYfyaiemR=+X9G1JKHEWqJD~i4V0{Yv}=cZi#Jzc ziUX1m*v)VZO-+=-vWbs|;n;-A#D2Zon<0d|WrpVXt~8-M210_*&CR85_O!@96Q*1# zP@l)%4m$vhTirEqG^!S`hY%D#01)eew|o?gol+^eky~Y|i#u?1qC6>0rH7dUz$Lsw z={{^QEs+fP7OIP@t>Ke2J8J!c1J$hKYj20{rop5_c@`jkEY%yxh$2DQ_9u2bPZui4 z>?fHXH0`#)9XP19%$=NThe_+Q5oXW#(M8EgW}B%XVo@11SUlIT8`=uK&T#cf*VtJ; zW_K+X@;HJ6P$Od0+a_Kx$Q035mm^u@AZecg!QO4g<}HG6edC@20s4MO^k5}Xm|=Hd zGdDD%zdR>O0hF9;ySU4myL*TzeB8*@9h92!ON|6Xv=3L{^RzW;+;^$xLxvAH=U(Sc z0kBb{DhVpr{I<bJ=)jPTlpKp0YTe>zlA2*6e&ZUUz)2*jTn#7KvIh z`s+i1|3q)PzWTMguMdNZpd^@?WZSko4$2FXV2$%c-Mo7eyz{3Ifbr})r3`)|6mch~ zMVbV$G!L2&D6;q!U)Xxyy>>L^%OxVUdv_yH(=a5lh2OPFV>U%dFG(46$A+4HGr`4o`+X%dBN{imu~(HAY<8Z^>%^M zj|mpGf$j0pA2u3oH6An*=)^dF)=w1KkUl*y*qfu<_i!Tl{s;p6M}pD&H-`DEzpRIt z^;PNb{_@wPwBAbA6U@IFW<9>F7ny%umDUr?`mpr3UjE&xw4Pwrho!&D%bzpVe+*0i z`{iX_FMqw(4fBt+Xl8p<3&WmxBFcV!E%K^BB~!zUMfa^In2-%GB8~*ECm1~;0sYIZ z%8Om+;u+zc(HNwELTZ}c(U{%G*Aa8llCXhD+z{(=^mtB8uB$X$g+wgQbCV{Dl1QTP zvv!$TF(=#!Vi*wA0ZC2O)&vbv;fCG|?xoP4)*56-C#axQ)opXJzPC^8)}ejn?!>#- zt|dR9pKs`^hmX?-hi1-U?%e~m)n3~^>aAPdkT@A_ti4^4M>C1kv0u_u(|E{9CwV*C zE!p0uDsPY*5&O<1nJW=c>{nOq!Rv~Hu;vagpt|u>0GUd%6m02aj&ydpg9k_L8x~Ry+~!xq&SB z+`L=;S46=z>jjhcvS%NB&bq6Mo&|T=bMQ$`9rz{%yF4~%RPdyJwBi)el*m_=5{9vcA|58o_EtTZupZ?xT+Ohb#}A8O zANqa2B$)lUEcs-(jv2#K0@ug{v4VS;Xo(G0WQ9awtH`rNIJNI2Tw^WJIWP7rr+6<8 zL!rY!)q=by;yawYZQ93??)=0?M;oyS9J#67!Ov5h z9%94YsJmVnDcy)w^5J^5q`TW)DYgI^1x{5LYzh{ETr|6-04twIavEVYj-}Dp$du(%krgde9K<>@6 z+ykcFk1|fc(+pC0u-N!r^Dv~zk2Ga_Q!AH3*#-IH48$Jzv;rVB!>m z;qSm4I@@}r2f4bxhF4gY|HEtln|WgNe#6IMU+$O$@XnyjzAt>aXMWE&3xyUBU%F3M zdOxV)Y4m<++{yL8Mgdv2)7OU{At$~*lx0$h2cKv@mru=wB?qE+Fi;o)jdEPjeeMC?>j?{4Y@7gcups6w#;G#Tk>esxL*nAG$r ze=NCK`IOSJ<+;>e$4%aircIrt$6S#nuQ|7N$F3o9L6dQ_Z`;hpQTU7x*QZ(@-|^{n zmi*ne&B*on*UuxHKCV8_2Xt;MSy)E(fMT+v;J3+;k6XXn96$GEd8YW_S`WqZ_~7vL zJ3k((({-Z(is*XivVg35)!G@cjJ9FSr{ol*CKnP+gn)NEbg!4?&0jb6AyFe#(0Wu9 z?alH!Ug-o&_XkDAIgorF1BM^%Hm_#e1lw0!Ppkl85CyKA$3QVkAd1(bGMC`5d-@`7%pju3pd~_H>7@RnC5AOJSHgLoivr7v{l0Ze7A(UKlUg;6eBL)&gK5 zj3vAqpMecc8C9O*+%c-L;dE9=tuGYWGTl_O#}9i4sx<3pB9^9CP{>mDSVPYVlSyrB#&$pI6u-gYM6Aa0+HL) zSb!t|FjS-ZDIy;NY&0wljJgpM~1|B31H~O&N4xAMR82l=6gRJ;AE~ZoD2yN-zE_U z_XiPcbM>Rwdiwmx2QkD@00_2s#do=3F#Ouh_cZ{d?-T;*1)zz*w%Nt7;NSLBn!*Uz z(y^EtW9v-J$~9-a?}N=x-zg~zk6OQ9ypK_0&bwZCdXBJo>cW~KS10m~TJ?)TjQ-Jj z2N~vgdmg)9_B9o&P*Kt(9Do4B=UpqjJrzv&@KB?RU`~VLVLldY+{NO- zAi&i;1xbSTpeBrOuffs*O*}Lxtb+LmLH>P4Y5Xr&puZ2c{P!!+e>nmD1(ClepmnDF zHxtlbCtUtV5c!XcQpIeQ7W9y*j`@Qiw^_kjJga6thm?JvF6(p0e5xm>Y>Fk*)B4qOs&Eb38d&?c$wYl;26kF z3@yC@tGhv%T|pPq3TYs<+a(?=b&JHd^y}WZdNb&Fj6`qR^~{U5TDk++=B#15jCcAm zc(*M&>R84DYcbT5TP@OWhs%$r2g@hS7C*BWgHJr}-ygZa$VNI3S)9U?u3*c&# zQX4t` zIeQ{Z->B-*BiPWdC+$3ryW97`^BB9-2R-JW(iS z=ZZX(VY@F#a?<+j!(kLb&6h+s34&!NPF{aE9YsmZY0?swU3T*0sVS=OAm4aKdoNxF z!ny`8gK;?`1VqV6$+b8oi48fwY+wi9mp^!pR-3tc{@4#cinY`a<`f|Ay5=@oEW4gr zC28n&{}{JS_U_z_cbc0%ChedPDM+2ury@CDqw(TvQ&9k_b+AXuhuW=Pk)m(k+!H4F zBR@l9o4XBLrYV%4wBOEbx+h=kaH%}@`96K(RtHnEqU|+@O0?RkIygW7hg9i#0VUk0 z3qiN@6?tNz-!iNZM5-`mj-|}2SsZdVQdhbKkyB5&zYR-W%|` zjux&FPFBAJD)W&C&i2LF?3zp@CvookYh`GirBv|}Haqg6;x)xk=oPhdOrN`-c$5oE z)ot77tm{1?Q;$-l`-G@FtUkl+g}w9-t3n^CS?m$qw7?`ag_A$^iF-Ok_N0WdUku0| zS!mWNS62Kys9d}NWeFVMa)-6AF0|YxlNLjLGBBZEq&7XS0J{!sX7t>nqIH%=RjEw1 ztve#}V>YHOc0B~FY=1?As^Wa!y#$o?3(vh3&Wk!EC!NC&15Y}Bz2~`8h~}E(Ki%#V zXC!z9yYKOdZ_h)}LM+ca%(Kom$4qWKm~;_2`|ZhM;+JpJM=vPE?l7O-9sBf%%zN)E zsv+hE!?=d7D3sv(3N%;MDrkz?z>h!I-`JY_i7cI<{d4V>$m58g?>lCXo$G;gWtkxY zf*`gL{?HB+kQKkaRM^c+Oe3(io6+1s@gI)cY1|rA;x@}n=5w$yX zIe=;q7D9DFr(E*Hmo4zagcJZ}KV^&bbpmWq6d1N+=hnOWDjJDo#QL{DoeP-|usWYm zDXtG##{88-<1esskrVVb+ zgut3Th8N6axX8mR&LEwASODT#q7SennJJaxR4%-%-npH_zhD*)VVO@$g}SJxOM*hM z<;LSRiooS_po;gECoEF8A0SRzu=E*aDL*i3&hA%t%Vz+`;vW>NI6-uojUbY79~J7H~sbl{BVWZvOA1Kra_>ZNoZ{ctdp&VET$yk~XPa$a)g?FX)i*^!v}&ix zeglvAufIMV*-Lq8%wU6K$n`&iCGVVL#A{>8mWVPLd$GbpWO)+E1R-c_Pi>`tHFUVO zigm8$3PKR0ucUq5U7(hF>ujn{sO>N?8Q}{24jVx$=IsLcpD~w>BK$+jRRm+nXB60! zj|4UhsZ70PQBs$DVtbH^EEg#lOFMLE*1N_&uJLzJtBiEww_l#nWuN`& zmmt}{{nGuv`h`p)k&n1*{OK1l?R<&<tQ(Yy!(=2+Q$tnv z63o{$$HrhEX9#zwaT5hL05gj`~>pPhK=0x^*qm)&ZJ;$#y z`r+VCciK=hW0$6i2YzfOOe$~M`>DBKrq@&KRkcTraOlcAdqjQP#*4ZJMy~Ih3Uax+ zEbW3Ue_w_BW}2$Tez5e6w%j@wcYo5u{F5>*h1?@qLBhqCn40=jLa@@y{r0Wbt>k4`kqO2OT{;NA;4x%j{96FZLvlYglFufB9@G zP*bbTQNQAN$?WFAr`Hb7HaXczJ&R#GWaiL&AY_-QJ`E=@b7;~(-H&}1{aL^EIp8YD z5SDx+xR_~e_!Ue|Xj^0Q&nR%E6iSl6?30vFap7>DY#ldY;DVjb_SPQ>*XypD}TCVj&I;*~WzSCafw(Qhx6Xnq zqEXI@YDN-lIfRcO6X+(nX@7xpdcg6>RqpP)<~l!gO5Irmd9@6!=3Ph( z#plSXPk6lZT4t%`vs66dy_v*LXAKOka^I&MSpf81oQp;iP zC-~(J_Tp`|o8e#YyaNzAjK;_T*@KOdfDV08)%e$0g%?Ar7rVfuFT!}LAeaHPV)SmU z8r<24W=8{ZUT;OR2bUGvq_lgpX?IL}8x6;{Z@MGxbxe4GAU$s!6?2E8b|dCXESJ09j}a||Da-Yoz66zt+WpkL5`ZF~QN-1C^n^o?iRG;U^WFizEa_U`ke_?LIS z2`Ftb`!p@;DfqEpDMtI+Eh$?$gNv)n4cFcP8!ed8>~vkzImD6Nk8f))Hg&evyi(A+ zq20$kwRT;z;Qb1y6Ubm;E?woZKxssttgU(=!2Kk}&X5pLEa#gc-g}GPLTdsH-X|i0 zvE>TNWG@$sG=vU(bdwzgz*_;wSK$Z9NDKJg^NX}q#W2ndYYAnj`|E0hJnt8S4I9b+EvS^I>a7_gO>^6$PVS9qG4|M^kBnm{{wNq8w0;?MPS?W^}2Gpl~XMMCX}1S zzh3#dfC+BN9fc_`a&1i504@fC35N2njrAo-CX!*e4lZVo7#hQIN=78|#Kjk>XaX59 zcY)#5xelJ@)Z*5e83Dt*+X8$SuywmV(s;B>P?`hu6k5PKV{HWz$=TK>Tx7|Q;oveh z@>UsFAW91K-NQepPZ1C!0K;N|UsOax6=8IWeKrCD?gXkK>D(4LGejn|_JJamnS}9$ z&ONrG6`TGTT8@J(B`{p11sgiI%MXCXs=(ydMt9&yY>YM;gd0#?Nr6y>HI-)cKJFgM zL|0juP6cX~w1lbX=mb2?;>;5e8R`!z4^lBz_O9jMtl`8-x`g}$DsH=2!SIacPvMZNZK{IU;G>vH9ihe{FtHjFMLrq6)iY-Xg7aEp@W(&up1#HSOzLF3>7Gg;Pd%! zh?SzYcV2uDJsZbJqhn$J{X;nTWNASs(mzcQBvbci)9|@wCH*Y>kEXG^#Adx|Z2zNa z9Qzj&2nqesGzhX160%3!RsJ*qK|Nn=-2@VUHw|}^_i>4TH34DW1nTQ1Ag!A~>@O3D z{cQrtbrYc0YsNimLfV+5;$J3^{nG@vKTV+fUzx!8A128B+XUPG)dX4pYJ$C~|H%Z* zjK55vyl#S;e`A7*KTRO~hY6hiCniv(!P5RTfyzHjki)$ynReU5B$GtOw&ou+s(!Lt zQKYG+qTp(2(V*WUq~8sz!7ZlMkNz-$2Gx%Xq+|au!31C;0f)~oX_N=5JIC$u4dIDP zAc@si>N00T7;X+5vx^Gr9MQvtgBgl~PMk9tDFociA>Twj4JR=Rp-E-y!wrp51HgGN zD_41^Mq2?CO1kH)=*cyV$q8FY^;!h(%=3+o@EQinJvPGY^z(oLS0dxw^I$P$wi*T#I5jDmKPeoN7vrHvkvf@R9PQpvu1y6*dVe^`y4)wUP4 zdYsIB!vekc2N~LinE0)KN(fbH1S2!cAGn>4D{*r_bbNZ3@|o-pt^%>OyT%nZ!0{Qb zwt%&Ch}izBGTRGq!F?pLDq(+WL)wr16D=dg?-p7|g$*=tvQ7uWuT1PYaOu)*@54{8 z^3!B=)g{9hS@5;FnuZUZ?-YSc7|lMdbrX#FP_rb~?}_Usc=z!pAP$5hrO8f;=%D4)8b1${j^t1gE1%y1L%^9; z?P2o8#^?dfO_N-V;i<6JR$QWB)By6xWK=KGwud?@Ca~HF!$wcG+?M(x%L|eSV{*}q z^!1}50oQ*n0H60$lTiB_oPcKsZ{0S=YS>qCpT}x(dCwEx-P!b_-+1~`N6JZ=_fr{a zP0Q1Q8b2FeB{3JFj3bd;kE$X>qQ-2<159nJtZP=I#0e*y>PB38wZ2fEWgh${rt^Ld~Al|FJ&tX2gU zYBc@j&v%taevcusc_+Fi&}4SPexVHcV@pkvkTywDClCDg?#pi)N}3{1@&%KA+=xiL zv7L5NHl!3FeLU&zc7SB1118gWw^V%Vl`0#f)FCCeu#i^}szBM9imwIgjPu z$8}t74X5)H-b_f$YZN1ahtNbWsD_&o6(P~kVKYV8P&TAt#hzcwW#~%DH6yWPo(+YP zBuF8{#Yefn;&~uJn}NuP+3SJ%)@5_|Bg~b=!zj$L&>T^$RfQc zW?SJnov_`qPgU{Uq5Z+oDH(DeNOyt|LFs3*DO_B}E_=TnCvob7jOCQjiZ^E=m{P~I zfEfQ){8~P;Nfw4Prh=HI*7Hxad+ynASboG91X$v@1I1~FRVf)g9D67y8+#|Kg$!33 zO@S?!u4}~*1d9YT9Cz6hQicprCPMm}YizrO6@A3)1GR0x-tNSuJP?IrRPA)wPN9Af zAaO-i0LH`#EAubNrE(orDwAA@g(U-4WnA>TO@ z&MhksWTD0PrJVRCR<~z244Y=>WJO#`yWayCT`Iecz(+QS^Y{CvQoEwc3~KJw1IYQf z`vW%YEw-tEZ{}PQE9($)tI-II#B|;f5e3dO4>0zbdMOl=PauzKDpsHN>h>svW$5&H zsJwGN<8u12zr-7rW`9U1rv22hKpM^%=2iC8Sj$o34Nde1urdBJ0Ap&XHEX6`Qk1AF zlz`!S>RqjL*^O7dA*XjwIJf5`xE*WSmz3Vv-@Q2eMfYdSTlt+FxvPrqbx(G~judZ! zb-f5$|GkG;`*ogs(*3pL%wU}#7XR=%of_>CL_>dWc>d)Pku83hhQ(7Ky9|8uAkJyS z*XQXccbB;HUq#S1-lKr=f%*+|klZDX^V3}8{{FcN)agMJCGqbUOg?-feS3Q^w`NnX z1R7&w+2Xot*{w@;#eo^_qc&_GO4|V*% z;h~!KqWA9?6`5;)>LcO4)!&PX?LYPLzb+~Sc}dB?7Zrk5zWBO6B>zJnGTz4}|Ihl+ zTGxlnx<17J(uerp`jGy+NUZBaTKO-1$p1@`(EqRW@y{ahANu%DMWWze_3`pQ>m%`B z^zrYC#HBy<@krzkeL(*seXx3x;G$A;uGLw6lzJukO@UIZgO`P53}ht{`AUU~vLnm}!ye;=f2|J?4CP0COf9BuAptlL}@^TAbE zuy*_+vj8y+*6w}LlRUfi73WQ5?`&`sp9ozM^szIaKhzfE5 zrWGCPfyJGj0U&c7{syN_Yj%FT_;(T$Js91v2lx&0?7Y1$GNGXvaW-ZyQ-*T;Mk@#) zzQZ>IuE^je(5bKcvs~%?EC<0%Nr`<&l}ivvL8#*u^iE+E$XU5W$&}NHkWxB+Eak1t zAy+{*HHu6mDWX6|t$hC1x4nIO@AKY3lB3R}An58+rv&JDvBC1>1<$FyF)E+!j-pd2 zG=ZZvb$i%v`E4)l--k&Q!TGGI?I33PNl3hyGEgB?&Tw&aV@|zA;nZ^2szqBo@IXbl z6`GiQR1n%F_fv(+J%2QpIWJ=yH82mz%O>=Ls*82ONU_NdC)>=!_Hljvauox#KQM0<`g&(UGZ8qExzfH}lG5=!`kCJ=hp#;X!fA)cLbaJZOyboW z-=;UAZ!9_;vOPC&(7rUUWk@Yx$LBXBPS+yNAYFGQ`JsDQ=UYjw^2l3_2@8wwIJb1y z9|2yKHEVhwpO^<6MSgj#$3b_nAwZjdHw~d2!%S*_6t~vx*Dz z@epu7fD2%-B>6NwUFAILiY|AH08ZNrNLrrS$Y7n4Z9e&HO|3(7@R%A0SYm&Ntw?ad zn=;7=Lyq~^>dUO*06Cdy1`M@+lH-dKdwCB7_(DrZhzM4!w4`rEGk3BiFwN z1fev?H_w?$S_slRs@ylVvVJ;RNSSM-Cn%2+Dgl4*x*)F{#uhFL1+>HcBk&AAln?2K zWFS`~t^AvEe;XLR= zH^WA70ckpW=ZC73+qW`vh5OD4po~%x;*<V7V!)AMgc-PeLW1P8)IhuK-ZtaKp6a&7 zvr-U2;;qbP2jw+V0ZVd3B&{eVcTpR-lVm}L15W{G*%($A*F|??@{O4_wMHY63SW5# z5PMHS>xmwrX7Ui`K)GFD{^g)0n~HK+?2NDk=)k?KZ)09FY0({ z7Q_*{0Qfv#KMXu)*%V`4zgvm`#(#KtPVf|$+HAjFEXT5%ZXM=-wB`1|=copZ4}`AN za6_sC)v49*Jo~d!z>(-03LS{RtHLT!9*B9awwF=Dvlfm_B48rv57#t74?#* z&#+ILHiS$tI^ZptGzB}n$Eb{X)WvgG=d%-G-?3$5!YIFK{=B%|?=FyO&DhneLxY6or0RPYi9W{Z!FV><# zE*5&py^;(;vW75{7xFqnYv^WXh%DrkF#`xDcKL>qN_w2QS++T)<*n6L+j1>r=blxc z>`5!$uG(F>X-a;reS0rMv6QJ-X1>?XURu!9ZM&JLXsTi)l{=*?saH^SfqwECZ#!Jw zZflQ%jd`BbvHabocgo5c=|sNlb#jWktNxy~>{~`E0-hOo;lh>LsVBP;sK%}8i*&oQ zA;!7xQB>esqGCTGv-ikF(SYqg1xvPUuE{R#!cS`V+#=g6NW|=sUJbTD64CTlbI|2H zaA)(|S|wxNTbFB|s!Trn3_X=7FD@Pn`r3V}FLn%4X(|46;Ie7&{%J!1p8du^Rh&$% zfTs%LDnASzij_>pS*dCR&Qn|vPcFau#HR^M?*~>}H3@nAL!V3ZGR#TDDyi9R%fL^HboM4ki!Q z=2#(nQh0Uw2?%GvCWxVZp`utFO$~L>t-Fth!S~e-9n;gWou24BhPAe#3bH{^q-0l<(~8D3G-@F!nu~(k z)u<)#n;ZA_%YH3{fRwwM8Ty2|{h!I&RBp2qt!ac_TmA5lGpMtT8y#f-k8aMhsmX8Wl z9uXDA0t!e`eDl2P+0X3RGyB{7VbA^%*UUNBc^-#4i+OnS3U+S9Zl!#W?vTlaxrZJW zH-_{9sL=)IZqd3TX3J>EIaqn8wx9v~(c|jks`p;aT*h<5!_Jf0B>F632oD zUM9W1!<32Y8?k!MZ4a`$r~D&oQ7dz0R$B%m`m*ksb{KwXGT(3OK9t!urRQhL&E6pq z7zf+{evOa5d@UDwv5a^jy;Cn6+2|Ahf>y%uV%HL~<|rbL^`4Ifxd`*_%0XtA!f zVYMJ~xP{Cg^^Gw(I2SlzvM@h>uIuLE-#k{*h{H;{_(85^-0ISrZ}qFopWEf+?|x16 z=7F@w!w$;>HO)O}%+B>nk$N1Z`wA%_d?y1suXe|Am<|Y^_L59k445gNhfxI%$BxLc zyNV!KUmg@~$bey8dSw&~Xs$)Hw=Hg-3u4}D0SIXqZ=N^~7+F;b*{iqyI=M`sj4dU(=RwGbc6uBAvtA&g}I7TuP)(J2$Nv-p7CJ?~DVy)+@367xc zF+0s4!*vF~J3q;c+dPca&#u9<>O7(NjHY-5d_Mh?%!ZL6Inxh$p8i|}Zpa6tQV9vs zyR<8irJ>R+Ic44-ZgnBL?S^CGdAqe-D;)Q6%PsE3DGuNuPk&nUX;|a)hR^6w&bIMM zpC*vY2;NQKJcL+)n=Kl?LAi}Jo&j=RxYorwb8zZgts00D-C7pIFGYzAdqEJN@%HDjA#(~G5l$#fsV6WuEy2SRtEWI4+MT;Q!FK zZZEK5qz09ZOa%zK`;R|@Z2b&Igyyt=*~mjqP+on^_ctc8VysG^qwp9-Nae4D+=$qU zVkb+`X!SMF92G{%Z125A-Q6asV-UttduFfAL|l~lU|pcs6dFV=`{E%eKT%Y#Cb7__ z3W28(uMyEQGP=~ijr_lcAN2n_J0k^W{xP!shn8E>i!Ivi*mh zk^W)+S*=R_CjS|(N>{5=cIF>1+y4kYBh{DuoBySFRB=KWV9`JPFKzfc1_Uaz-K6~Q zmHeAyD<&1MXRPbrE;WLh$EBvV03~*cwy}oPv}S*pAFO#K^Q0pYp{HlE-w(=-4Hozl zsY*)nQq!8ey5>bqw35`cmYQ+G#}KNbf>UXz_9oKc7mY9KA$_yU(%RgJS33!v8jaVT zG|-y8b#Rr3F3mik!bkpIJE7~vBYUc1U2m`MDYxd>Rv+TM&L!yVM+ao>_%m&W-_1ag z(+!0Z-H3R z#90)CN{>PnB<$fqc3vc2yQm6K@NH4rSk=SaavFF3rel>3b6cSfs^+e$E8H)FgVf5C z;(d;>5Sse!T0$k^q-Bw9Ew%KU>&4!kmh-pt)d{jn`FwT!*Tw!r z%zl?%9?mdY`N2%3M!yfuMn2gjY}%p`Q|SCq#9R?VQ6$cy5H!=rCm*TM+lw_$CQ(J^zag^vPg#3q?B)f-FucRaa=`4CusideLeyJaCX6$C>BL~m4x{)>bhcXc}VnAYC;;eb`nOm)_-P)x53Dr`U* zB1aEE$UpEXK4+1LiFkDU5PgO(Jb+ON!>F;W9a8%VH){$vJXx%SSKX3gxM()@Qq5|S znCkDmQ8mhs^w5%VF{TyhxfHT%|AY({g~>|LNV#$@_C8i}QDt=voNgy9S^XJYuUjsu zQ1{?k8eHxGjGcq^K9^o-(c5dgN8NJo5%=Q+e~wseeTLO@4g9&ouKB1xs-&YM^Cm|L z**rrRlQY35pr6z7gUU?td%MFeq2zO39=S3)jUVTB8)X^AepI-viEE}0BQFcN0E+bs zb^K9$>>#Y7_-JouwMk{tV{gB>`B8tVIu6{K`elABSgm4f)r+FIg{KkMbeKpQN0Ne3 z7n`KMNV+eZitufpfAA{(=a=?wX&u9aC^A^qZ;ts17boyo;m>0PnqFscf%BO=n^1=F z))Tq9n>yYLo~z6^uhrXad$K)kF&CppnOTyYO~rMszPCMfRH3`_9j@V+QlV(yo9sKL z2fpNQAwQq>*FStG5Y@4D@yAg=@zPw6J$ZlB`L~T5*_MtYOr$cfXL0)B$#2VV&aU5; zoIce4hh(~v-U|Wa$M*dByLTvsj2+ZqQ7q#w2Hn!d8FC-pivfAN{qy~B_s`mT`xjde`6J!e zs&0Wc0AbfpyrbDs{2pTWcBj#qT-TBb*_VuWRz;GIM=(6aeLB@`))v(dN2O1y0B)?2dL( z#0v)^S|9p4H#64jQM6&XM?;8ds_4DzPE(t2n^g|OXLBV$V)qP0jjSI${*lk?V!(PX zAG34lybhQ`t(I=W6|Ss$Zgq>@i=9v4IwMuNRX6k%s3i;};|)b7D_pxUHm~grsPhdg z1FrRnP_&%^Vp6>AG;Zt~vEl-Co})y^DMn;rl{Ym~1pQe$DbBSYY6<7oXnZmB&EoQv zSc;$tcRFCtC^kPFhz|R_)u2HHiK$u($Z;=jo=_dD>%C%x6yEnlJe8BZENLQU1GY8M z{+(8EtIM&2yJYiBYxggJ#wM;I=mX=r*3sEZs4r8RD~~T{b5CX*yyWviwcxMQjoP`t zi#;L&SV~tE8&RnEs3pkuC0G%~BhF+?lX9Tss-*Mr^?Us;!a#>|aod@V;5ok1i*_9` zko(=p`mXtl?afK-nr#Oe`;Lq}X(tw6%_EoAodH=FtgRZxi|UCTYJNYn-Si)>t#B<} z%S9TtS2$HcQeUpTWIqsUQ;V>~mX*gsRbK0FjmGWj7B>^q@gOpVw?%QMzr<=>bFk1i z`7IX${pACjjx&vVlOssLCWv)jeDQ*cf{bVUIz}2!7IM3GSXe)4GZA?b4G;Lp9+)pf z8?ULNvAOa|$$y{wVtTw_W|S3~l<_(thV%MbC|&o>!0OsWE%oV_9jc6>=%YMnd7#gH z|2{b+cckP_V#Fqrv$L3Qq4Gam2>rijDrpTpPRsgtQi+Y-{U*&O`=pfejnUKJ^GU`+ zYAPYYf4r+VFY7oI98~x@nWT^|IAX7y#EpR=kDhQMs%mQ+?DNZvN!B~=hooUNO}$R~ zB4wq^Rjj6`uM8|&Dqtf*Ns0iVs9ApAm54UOlKRZFi@h_GQ`&sAlsdZr6WY0MX9fK} z@M7;`q(ygA>C8FZD&YPsu%)O+Tr)}r%@;MM=Bnpl*( zvm()r5;oY68*AK!IOakpi=OAiV=&ZN`DxsB3J&EEn8gjbrGxZ%takOd<0jpqVy44h z5qH%xr^|_*ZX*!X#XFl=qx>d|bj;RktGKkR3CIB*@+@6kI znB(4_-T{HxE{Bm1GwzRdsaIU!&2WYHwfTPJy~=bN|vR;;A+ChjYNCCiH6d+f(f z))8G!Xg~SN(pFnD6%@ssoYWz1O-j$n=JC6o%8N6WZJY$R7zx@_9M#(hxstp!cu?t) zGE81U#zs;ZZ7IV(Ak)dYY@9)Wmb@Rn`KA%3JU!ye0LlslPz9^l1r4%wjQqNRQFF9> zMq-fclNH~l*MlGw6yUkg2QAfN57PB&rq^N4*h`k2H9{fSpPtYIP|`=vI_az$0z5cA z4bPAA1`u|fenTz+E=OT=5vm+^;0oF??$ws1S^lB%l zfaAX2gyug1VPvBzxvDglBcN3i1?J~a0VvNcmMp)HHNN8(0xA|WEirQjJxC}@Wm074 zglFz^Ef?vZBVYZ*1UxjEe1L2z(pE3Qj6jgJRqxN$G7s5AmV{b96_@6$*?;~trh{{d zpw=O=Qg|=3GE(; zT-wN<&fKH5;H~&v4{EQ*u}+}dpRL+kw@Qrx?u6&YQU^j2(_#QQ^Xm>sC?T77;?;i; zYl1Nv;V@aXI5?ZoZW|9$RFk++^+(g(>i0o2TnO=7xuU%1dJc&3J;{qgWQUI=I|b*s zCcW70!sR2}u3f%*)#t1e4@}*>C1nqB#^j~c32VAEnRhl-EETOa?t5<;L1A8#PE?nt zo+!LvLZuT`sS|cRu!Ld%cOi87TEzeoED^1Iz5es-H8h2>3f|bP9QuQwbJcTiF8582kiIG2Tz4bg?B1(se|?(EgO&RO5~PJ z@c2T)yF{o97gao=jNZwP#N8Q0C`q%Rzd0DzE44>E^~pstU?7)Cg1@(3vq+2lE2GTJ zN_tzlv&U(qD&18p@r`*|c0xKMRIy>v$-I{l=ScyVL!H)Q3iI5QIXuPR)=uW%^I*r$ z_d^^;#h<0_5XTJr9!rUnlkLL-8fkp3RH@V4AQx+D3Dvl?=(@>vZ!Us9>2A5uD#*)@ zc5)a%n2LuSm-F*L4%0Nsg?HS@BT@$X91J%U^zjHKBUlDxQ<^}F*n8S>T#S)8-rl|? z&iiNAGtJg_k&F%OA_$4xP#^L{Luy#i~UY2&G}Y4nEtcVbdj{ ztskAzRfcIPNq}*Kp`*Nrmrj2JRp?NM`{LKwA{q|hNbi}su4X5wARI?$K(^xVZ7nBX zqM1aGO<8X%#4$5$;PU8_eUIdJPC=p@-Xn@T8w0#8n;hR!y}A+g^d%qE6;$y$U9NLb z-3L{qDAHGI-qW7(@t%Xoz#(g!=!AtR`@7S=K_lKe;^f1{@Em!<{yLZMA>cmQuRCM< z#yp)2_Wa1@ZpmupjbF8F)!@XOoP4*XxzjkLw@QDK!hk#_j=~X!cnx0Be86kgx(gw0 zwC$@uUJS0vA5L%hx?4HXcYSxU0&X!rY@1udYi4Xb8lF zUBTyy56V1v@!QU?5Xs!L@9^x+k|d|pE|w{G83_0_2Fydt8Z zWXx7EWdQal_lDJD()}Xm;J3xe543C3qShJ5TGkzKFB8m$H;H_?^x+hBxv%?`MHU<4 zk|X?c;%i3R_a=&C*W$g5#cL0o3)O%83=?iqM=$b|SI|SpR7&l3nU+stPtST}TC}AM zroYN4D0mva>A=VPFx*^q(oTmC;SiDDsc>6^?({_Tp*oev2k zReCx8OSV>prTw^j`QA*&&J^-K`%lA1EWWK=qCwJj?NUY_&djps?Mu_99Lvskl*i$9 z)zbZFDRH}m{z$ZefuUD{)CEgW#$aTnF@~a&7DE^L$m=O9bStRl)w;@?H7eI*Oip{} z3W7Vmky?Lu>!UA75gYTthCvMUscYNuD-Uj(!88;;e}VTtb0o`RUJ(`yhF#0=pPhBV ziEE#n;6w1=ufl=Uo-&A+_s~nvjIVCKgUiWaz)@2iVE?{GBw zvuzlie(#(Rs^i}Rxj^n&-K6_F8ok?9U=IyeJ=g$5dZ7>pSZcc#xt02aEaOsKDR<&s zQwfZ2>9}TMm$5H+Xjk>S-FI~x)+vV7KVj4I;cz$on0MT>-1Tu-Jy%9EI}@IAl0&z8 z7&4$+F1V^kJqO7sfv>Y`KHaf*>(Sf0IA`W#Ww+zZF~*KhOCKKn>$Q%9HIGyaBw{md z*<4Fqo@_%NXYu-2(Kb=V8MNtMN#y%rt;dMe{T>m0aueBwZOJ&YpSvJR_p4Dx>>yB=)G@T|j)-l+4i4{?909_D`g%%c zazBVS1TrA_Rk7o3Ljwg4A7RqWaWo$oFYtiQW=`}VaMsN{q~_-~F7Rf_4zTjGmRi&S z*vDSvAK5p6kxPCRQ^E0-LwR-s<9sk6r|_f)sfp|9k%EbM3a~4H%>#XMbwWWciV+{S z1M`NvQTIkDAhX4j&jcuQP9TUS_VG~)=^x*n0?Ju6nXYGq`bPM$Q#Uz!2f2`na1YJ} zKR+cS3^oIY2^T7*v-%O|MWu%MsuYG1k(4fC0IRoqdc5T5?8;CaiVIYV7NVID9}b>T zm3ihO1=B+60Wqb&dO+A(s+AaRidr^m0#HJ}B8}@ZRFy+@a|4Jj>v+6XPWb@`xOo^} zzv){57f3OPH|o8(7!5FevJ%)_U^HO*<0%UbmI2{I700YYyEwb94!P39gHm9>8pWn~ zq3=yCo`eZqJo8MNI|j6A!m)rAJ^HWHxgboZrnKf_%^AjCJEu;`$9{GfhuLU)rB<62FtVIkoaljQj>5 z(ldz+>;RH%_g#nl_w^qGn}eSxkzLp~pkonc;KK8mZwwxhVz%k~pux88#R2{b5Jb`6zidX*}WoyJS)i?qE{*_iAf_Hxo{px<==Y)Fhd5H;8nMQ=G#BX1U441?HwzClQ8=3T1ezXZXi&;6+ZU!xEqs9ZD@k*x zg#k&GYVBo~AaazwB#r|c_;^YT0&9YhhD?))Eax5i?5&}Xd&g-VJwe?~c_HU|O&L3e z?QVS+nsFHQTU9)Q>eduN)B%Gg=`5E-F1%GAZrElsuuhW=%)QkEcc|Rep35u#v|-YA z9b-cd#cN}^Q3TrBzb|dU!XNaEFgIG_Tdfj9XptAxZ|QH>{u}|SZFmEJ>u-Q%5i7if_4VBYh^{+6 zO01(U9IbGIeo%NP$K+%{Rk4W2YHX9(3E)egHy8WgxT3!oc2(*<=BpZo= zJW1>qq9BGBdL$b)NIRX(CpW0>MM1kS5)k|B-o?i&4?8rnJ~GB8>iRv`CB06%=={RR z&7gpq)aWW#yXtdSuefxB?9}cLsew6jUrXs!{QFx@uQ;laZHQR2#_a5!qx!d6o#I{x z<#@7wH(t8-wV>%8UDDlz;9Og`6z&_i{IIKWWN+V=3~OzfcyAh&h3u#=3r0k{Z9cieK*C?0l#zFi1Z(~yn$~U zoUiGH=a+7%>1Q|=H2)WlE_)nyMOP*>`?gCh9bEw_w35@9~_zy$>w3Ac6?0X TavCo`YpnYKb2QdL0qg$@LUVG- diff --git a/app/styles/media/images/sort_asc.png b/app/styles/media/images/sort_asc.png deleted file mode 100644 index a88d7975fe9017e4e5f2289a94bd1ed66a5f59dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1118 zcmbVLO=#0l98awuV{uMt6P_}u4rcI3idKFP2SpU%ZJIE?RL`X zK?Oyo=*5GG2SxDYK=7akJqV&hrl{aWJa`y*5xh+1%i2y4V}gO?edPc9{r;a9vjc}) zn|Cxb4AYwFmvVG%_ui)U^y_4!ujsO!qzYuv8YUIR!Aw%KiWp=JrG#@>(I!s4#N7H->?w+cxsH2#GA};A>g8lyFDGPKh!5)vuP_{)}*83+N zJUBU!S0_i+E{*Lu1iGsNB``2iK-CyCU7?y_mv{xb_pUh>ESZqe1Y2{eAZLMSIT%EO zFrdOH1W^=3p>Qk~I{J+k#s5zQ@j{%aIA!l^GQjJ zqA1Uc2%!{8qBKfMNh#9DCnKS_*uZ8?mnf!+8@f8xtz#prVg=E`3bCBLWsNmDAX~PG z<(4fQh=UOzE2?gKXRkc9XeI3Er?HlHECVd%SI}3`hy1_du3@$R$r(qT;k@Sft63UX zv;)2Ea_iH>^6+4jPK-lGM{Zw37Tz>~~zlHzO61x51(V4jcaKrcIVDG$-d>)z}S|7f!xxYhfUE}Kj zug_h&HZN}go22$5Ym1}P8~vYNx7-~$TWFJ;_nh!wFYSAQJF{CCo=xpK8^7?iY1^!H haOA^1D_`VC7fU=jcT diff --git a/app/styles/media/images/sort_both.png b/app/styles/media/images/sort_both.png deleted file mode 100644 index 18670406bc01ab2721781822dd6478917745ff54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1136 zcmaJ>O=#0l98WD1Hz^GK+C=e@fhgE~b#2$Ux^~T`1v5)mw1NlIe}zC z+ge9alrMQeN|SYi`>tC{zIG}!O_oO7k;UC8kBf>8sknx65F`zy2d1H-4fel=trX>@ z^-LCL<%6P%3`TJ=Ov$hao1$9VN|vJbLJV@SM>nJN{L>dS(6uOiBq(#Tm4F5Pz>p2Q zhq^NAP_G)%=(c^JwImV&17Zb~j6Ty5OHq1RS0sD)n5Dro1ouYi-$7;N6i6T&f*`~B zRW8JV5YO;|=5RQ?2M8R`v7Es2f}anI0YT(Au=3Evo2})=wA8uci&#;*fUzaAY_V8m ziU9`MJuDxIL|hF)@DqgJ88op{@|#XmML~j&YU>u(kqKNyC5HxZlqQk>PQkENWld+L zOr&6JNwHX-;oOueKw17j)G$`j4o<^A@%~fT$qZVMO+yC_*eYpUzR7iEi3uAj7}*(w z`YKgS6%a;F0a+l?9R#wX>ZWTi<7HV)nhsV>6(*%9O%xbi*F?TK!383rh#(|*p6}q} zd?z25;!?0(hzA2Li3(Rj>VN@FT;Xbexbdo7cN7eZc$T28pMYAYjSR4yvZz;&C0tc+ zg{xJMrKKvDCBd+6WB+P&<%mp=yImbyVyq56G|9BvWUP^I>ms=lb4e+lDSgg;Us`JO zKB6{wH+j~F#-A4FY3K3qm~Z6m@V6}oQ%8?p-E$dw`#0C$PJfmCV8)v}3>Ydha%`fZ zJk~G*M^A3LGk$Td;R`icF67R~`sBOHv)Hlqlc%$jy~9_oZJcNyWxkbb_O9u#|7hLF z-<-NMLzh3S0YA@8gd1Pt(Df|3@16Y-n=aSvsF@AkI`ioeFg>&H3bXU&vBnE6gIChkL+(Ey+0iB4Z$Eze7t_CX>Hq)$ diff --git a/app/styles/media/images/sort_desc.png b/app/styles/media/images/sort_desc.png deleted file mode 100644 index def071ed5afd264a036f6d9e75856366fd6ad153..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1127 zcmbVMOK8+U7*1U&zKRu5sR)h{1;yRWWV^4}ShvZpU2*HWU2!iy(qy)cZ89;Lb+`3m zMbruv!GjkO!3qksP*5)lD)k}=Dp*ht-n@8G5m8XoN!zU+ih_Y;=AZe$?|)|~*Ri8v z(dtDU$2DZy)jV65`|pB!_H}d7Cv0h=sUqzpC0fy3%q0!dg+a#Bx^W(BM*oq=xP{{a zC9_bZ#q2IgCss)FbwX9kVQ7wPX{|b%-is;d!ri7V^Y8E8=YeU+{JuyQW*r6hnC$~D z?i}bS=mWia!r)uCftISo2rNuBP__DOPpZoN6tBeg{;|M=DHYl)^V3chvpJv;7lTL$ z26Y&PAc{gL+#HL=wg3?#C_qs_Vi3iouqZ(YW*(kdbB&UeSJN}Lm?ZN(lsb|iR4SEF zB^)Adw}29fgwG+0L8cM(`faLJgSNN6#-L(PcTI+l@K3y+Xf(g*^61+0|J+O6zN2mb?UNGh6GU@A{1+eF%d@N2(^XdVmhis(y25|iAr;gV=io5OsYy0 zB}Gv|2&GUGrBPB%s*yG^841Ug8a88lRI_zlvuiTDGuXsmv6A9qjS{y&NMEf3ay^6+ zuZK85>5PD^rkl1e`{kLAR>iJ)6dP%mSYRr@k~xQcDE=$%X{_--ITM&Og5Ml}G)wJ> zb)dhUZG9%p4iC23#JFrUCcmwHz{cugMoku~ue-kg{Mj0~%`FeCcz9jAdg}QET-kSG za`+2B_+lRTaeAVz>E`F1pN7h>B=BbGqcz13d%ywZR&4OjkNNrF_U}#EcXDGa@V52B z>JnIW7#s%CHi diff --git a/app/styles/mixins/clearfix.less b/app/styles/mixins/clearfix.less index 6d2b75f..a027a7c 100644 --- a/app/styles/mixins/clearfix.less +++ b/app/styles/mixins/clearfix.less @@ -1,7 +1,7 @@ -.clearfix() { - &:after { - content: ""; - display: table; - clear: both; - } +.clearfix() { + &:after { + content: ""; + display: table; + clear: both; + } } \ No newline at end of file diff --git a/app/styles/mixins/userselect.less b/app/styles/mixins/userselect.less index acc0d67..5c92770 100644 --- a/app/styles/mixins/userselect.less +++ b/app/styles/mixins/userselect.less @@ -1,7 +1,7 @@ -.user-select (@val) { - -webkit-touch-callout: @val; - -webkit-user-select: @val; - -moz-user-select: @val; - -ms-user-select: @val; - user-select: @val; +.user-select (@val) { + -webkit-touch-callout: @val; + -webkit-user-select: @val; + -moz-user-select: @val; + -ms-user-select: @val; + user-select: @val; } \ No newline at end of file diff --git a/app/styles/modal.less b/app/styles/modal.less index 2a8e0d9..c1511fc 100644 --- a/app/styles/modal.less +++ b/app/styles/modal.less @@ -1,6 +1,6 @@ -.modal { - &.modal-scrollable { - overflow-x: hidden; - overflow-y: hidden; - } +.modal { + &.modal-scrollable { + overflow-x: hidden; + overflow-y: hidden; + } } \ No newline at end of file diff --git a/bootstrap-framework/js/alert.js b/bootstrap-framework/js/alert.js deleted file mode 100644 index a7787cb..0000000 --- a/bootstrap-framework/js/alert.js +++ /dev/null @@ -1,94 +0,0 @@ -/* ======================================================================== - * Bootstrap: alert.js v3.3.5 - * http://getbootstrap.com/javascript/#alerts - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // ALERT CLASS DEFINITION - // ====================== - - var dismiss = '[data-dismiss="alert"]' - var Alert = function (el) { - $(el).on('click', dismiss, this.close) - } - - Alert.VERSION = '3.3.5' - - Alert.TRANSITION_DURATION = 150 - - Alert.prototype.close = function (e) { - var $this = $(this) - var selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - var $parent = $(selector) - - if (e) e.preventDefault() - - if (!$parent.length) { - $parent = $this.closest('.alert') - } - - $parent.trigger(e = $.Event('close.bs.alert')) - - if (e.isDefaultPrevented()) return - - $parent.removeClass('in') - - function removeElement() { - // detach from parent, fire event then clean up data - $parent.detach().trigger('closed.bs.alert').remove() - } - - $.support.transition && $parent.hasClass('fade') ? - $parent - .one('bsTransitionEnd', removeElement) - .emulateTransitionEnd(Alert.TRANSITION_DURATION) : - removeElement() - } - - - // ALERT PLUGIN DEFINITION - // ======================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.alert') - - if (!data) $this.data('bs.alert', (data = new Alert(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - var old = $.fn.alert - - $.fn.alert = Plugin - $.fn.alert.Constructor = Alert - - - // ALERT NO CONFLICT - // ================= - - $.fn.alert.noConflict = function () { - $.fn.alert = old - return this - } - - - // ALERT DATA-API - // ============== - - $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) - -}(jQuery); diff --git a/bootstrap-framework/js/button.js b/bootstrap-framework/js/button.js deleted file mode 100644 index 15d7dca..0000000 --- a/bootstrap-framework/js/button.js +++ /dev/null @@ -1,120 +0,0 @@ -/* ======================================================================== - * Bootstrap: button.js v3.3.5 - * http://getbootstrap.com/javascript/#buttons - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // BUTTON PUBLIC CLASS DEFINITION - // ============================== - - var Button = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Button.DEFAULTS, options) - this.isLoading = false - } - - Button.VERSION = '3.3.5' - - Button.DEFAULTS = { - loadingText: 'loading...' - } - - Button.prototype.setState = function (state) { - var d = 'disabled' - var $el = this.$element - var val = $el.is('input') ? 'val' : 'html' - var data = $el.data() - - state += 'Text' - - if (data.resetText == null) $el.data('resetText', $el[val]()) - - // push to event loop to allow forms to submit - setTimeout($.proxy(function () { - $el[val](data[state] == null ? this.options[state] : data[state]) - - if (state == 'loadingText') { - this.isLoading = true - $el.addClass(d).attr(d, d) - } else if (this.isLoading) { - this.isLoading = false - $el.removeClass(d).removeAttr(d) - } - }, this), 0) - } - - Button.prototype.toggle = function () { - var changed = true - var $parent = this.$element.closest('[data-toggle="buttons"]') - - if ($parent.length) { - var $input = this.$element.find('input') - if ($input.prop('type') == 'radio') { - if ($input.prop('checked')) changed = false - $parent.find('.active').removeClass('active') - this.$element.addClass('active') - } else if ($input.prop('type') == 'checkbox') { - if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false - this.$element.toggleClass('active') - } - $input.prop('checked', this.$element.hasClass('active')) - if (changed) $input.trigger('change') - } else { - this.$element.attr('aria-pressed', !this.$element.hasClass('active')) - this.$element.toggleClass('active') - } - } - - - // BUTTON PLUGIN DEFINITION - // ======================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.button') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.button', (data = new Button(this, options))) - - if (option == 'toggle') data.toggle() - else if (option) data.setState(option) - }) - } - - var old = $.fn.button - - $.fn.button = Plugin - $.fn.button.Constructor = Button - - - // BUTTON NO CONFLICT - // ================== - - $.fn.button.noConflict = function () { - $.fn.button = old - return this - } - - - // BUTTON DATA-API - // =============== - - $(document) - .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - Plugin.call($btn, 'toggle') - if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault() - }) - .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { - $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) - }) - -}(jQuery); diff --git a/bootstrap-framework/js/collapse.js b/bootstrap-framework/js/collapse.js deleted file mode 100644 index 329e535..0000000 --- a/bootstrap-framework/js/collapse.js +++ /dev/null @@ -1,211 +0,0 @@ -/* ======================================================================== - * Bootstrap: collapse.js v3.3.5 - * http://getbootstrap.com/javascript/#collapse - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // COLLAPSE PUBLIC CLASS DEFINITION - // ================================ - - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Collapse.DEFAULTS, options) - this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + - '[data-toggle="collapse"][data-target="#' + element.id + '"]') - this.transitioning = null - - if (this.options.parent) { - this.$parent = this.getParent() - } else { - this.addAriaAndCollapsedClass(this.$element, this.$trigger) - } - - if (this.options.toggle) this.toggle() - } - - Collapse.VERSION = '3.3.5' - - Collapse.TRANSITION_DURATION = 350 - - Collapse.DEFAULTS = { - toggle: true - } - - Collapse.prototype.dimension = function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - Collapse.prototype.show = function () { - if (this.transitioning || this.$element.hasClass('in')) return - - var activesData - var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') - - if (actives && actives.length) { - activesData = actives.data('bs.collapse') - if (activesData && activesData.transitioning) return - } - - var startEvent = $.Event('show.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - if (actives && actives.length) { - Plugin.call(actives, 'hide') - activesData || actives.data('bs.collapse', null) - } - - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - .addClass('collapsing')[dimension](0) - .attr('aria-expanded', true) - - this.$trigger - .removeClass('collapsed') - .attr('aria-expanded', true) - - this.transitioning = 1 - - var complete = function () { - this.$element - .removeClass('collapsing') - .addClass('collapse in')[dimension]('') - this.transitioning = 0 - this.$element - .trigger('shown.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - var scrollSize = $.camelCase(['scroll', dimension].join('-')) - - this.$element - .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) - } - - Collapse.prototype.hide = function () { - if (this.transitioning || !this.$element.hasClass('in')) return - - var startEvent = $.Event('hide.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - var dimension = this.dimension() - - this.$element[dimension](this.$element[dimension]())[0].offsetHeight - - this.$element - .addClass('collapsing') - .removeClass('collapse in') - .attr('aria-expanded', false) - - this.$trigger - .addClass('collapsed') - .attr('aria-expanded', false) - - this.transitioning = 1 - - var complete = function () { - this.transitioning = 0 - this.$element - .removeClass('collapsing') - .addClass('collapse') - .trigger('hidden.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - this.$element - [dimension](0) - .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(Collapse.TRANSITION_DURATION) - } - - Collapse.prototype.toggle = function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - Collapse.prototype.getParent = function () { - return $(this.options.parent) - .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') - .each($.proxy(function (i, element) { - var $element = $(element) - this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) - }, this)) - .end() - } - - Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { - var isOpen = $element.hasClass('in') - - $element.attr('aria-expanded', isOpen) - $trigger - .toggleClass('collapsed', !isOpen) - .attr('aria-expanded', isOpen) - } - - function getTargetFromTrigger($trigger) { - var href - var target = $trigger.attr('data-target') - || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 - - return $(target) - } - - - // COLLAPSE PLUGIN DEFINITION - // ========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.collapse') - var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) - - if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false - if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.collapse - - $.fn.collapse = Plugin - $.fn.collapse.Constructor = Collapse - - - // COLLAPSE NO CONFLICT - // ==================== - - $.fn.collapse.noConflict = function () { - $.fn.collapse = old - return this - } - - - // COLLAPSE DATA-API - // ================= - - $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { - var $this = $(this) - - if (!$this.attr('data-target')) e.preventDefault() - - var $target = getTargetFromTrigger($this) - var data = $target.data('bs.collapse') - var option = data ? 'toggle' : $this.data() - - Plugin.call($target, option) - }) - -}(jQuery); diff --git a/bootstrap-framework/js/dropdown.js b/bootstrap-framework/js/dropdown.js deleted file mode 100644 index bc4d373..0000000 --- a/bootstrap-framework/js/dropdown.js +++ /dev/null @@ -1,165 +0,0 @@ -/* ======================================================================== - * Bootstrap: dropdown.js v3.3.5 - * http://getbootstrap.com/javascript/#dropdowns - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // DROPDOWN CLASS DEFINITION - // ========================= - - var backdrop = '.dropdown-backdrop' - var toggle = '[data-toggle="dropdown"]' - var Dropdown = function (element) { - $(element).on('click.bs.dropdown', this.toggle) - } - - Dropdown.VERSION = '3.3.5' - - function getParent($this) { - var selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - var $parent = selector && $(selector) - - return $parent && $parent.length ? $parent : $this.parent() - } - - function clearMenus(e) { - if (e && e.which === 3) return - $(backdrop).remove() - $(toggle).each(function () { - var $this = $(this) - var $parent = getParent($this) - var relatedTarget = { relatedTarget: this } - - if (!$parent.hasClass('open')) return - - if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return - - $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) - - if (e.isDefaultPrevented()) return - - $this.attr('aria-expanded', 'false') - $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget) - }) - } - - Dropdown.prototype.toggle = function (e) { - var $this = $(this) - - if ($this.is('.disabled, :disabled')) return - - var $parent = getParent($this) - var isActive = $parent.hasClass('open') - - clearMenus() - - if (!isActive) { - if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { - // if mobile we use a backdrop because click events don't delegate - $(document.createElement('div')) - .addClass('dropdown-backdrop') - .insertAfter($(this)) - .on('click', clearMenus) - } - - var relatedTarget = { relatedTarget: this } - $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) - - if (e.isDefaultPrevented()) return - - $this - .trigger('focus') - .attr('aria-expanded', 'true') - - $parent - .toggleClass('open') - .trigger('shown.bs.dropdown', relatedTarget) - } - - return false - } - - Dropdown.prototype.keydown = function (e) { - if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return - - var $this = $(this) - - e.preventDefault() - e.stopPropagation() - - if ($this.is('.disabled, :disabled')) return - - var $parent = getParent($this) - var isActive = $parent.hasClass('open') - - if (!isActive && e.which != 27 || isActive && e.which == 27) { - if (e.which == 27) $parent.find(toggle).trigger('focus') - return $this.trigger('click') - } - - var desc = ' li:not(.disabled):visible a' - var $items = $parent.find('.dropdown-menu' + desc) - - if (!$items.length) return - - var index = $items.index(e.target) - - if (e.which == 38 && index > 0) index-- // up - if (e.which == 40 && index < $items.length - 1) index++ // down - if (!~index) index = 0 - - $items.eq(index).trigger('focus') - } - - - // DROPDOWN PLUGIN DEFINITION - // ========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.dropdown') - - if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - var old = $.fn.dropdown - - $.fn.dropdown = Plugin - $.fn.dropdown.Constructor = Dropdown - - - // DROPDOWN NO CONFLICT - // ==================== - - $.fn.dropdown.noConflict = function () { - $.fn.dropdown = old - return this - } - - - // APPLY TO STANDARD DROPDOWN ELEMENTS - // =================================== - - $(document) - .on('click.bs.dropdown.data-api', clearMenus) - .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) - .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) - .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) - .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) - -}(jQuery); diff --git a/bootstrap-framework/js/modal.js b/bootstrap-framework/js/modal.js deleted file mode 100644 index be6f3fc..0000000 --- a/bootstrap-framework/js/modal.js +++ /dev/null @@ -1,356 +0,0 @@ -/* ======================================================================== - * Bootstrap: modal.js v3.3.5 - * http://getbootstrap.com/javascript/#modals - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // MODAL CLASS DEFINITION - // ====================== - - var _scrollbarWidth = 0; - var _isMeasureScrollbar = false; - - var Modal = function (element, options) { - this.options = options - this.$body = $(document.body) - this.$element = $(element) - this.$dialog = this.$element.find('.modal-dialog') - this.$backdrop = null - this.isShown = null - this.originalBodyPad = null - //this.scrollbarWidth = 0 - this.ignoreBackdropClick = false - - if (this.options.remote) { - this.$element - .find('.modal-content') - .load(this.options.remote, $.proxy(function () { - this.$element.trigger('loaded.bs.modal') - }, this)) - } - } - - //Классы элементов находящиеся вне диалога и которые могут получать фокус - Modal.ALLOWED_CONTROL_CLASSES = ['pl-combobox-filter-text']; - Modal.VERSION = '3.3.5' - - Modal.TRANSITION_DURATION = 300 - Modal.BACKDROP_TRANSITION_DURATION = 150 - - Modal.DEFAULTS = { - backdrop: true, - keyboard: true, - show: true - } - - Modal.prototype.toggle = function (_relatedTarget) { - return this.isShown ? this.hide() : this.show(_relatedTarget) - } - - Modal.prototype.show = function (_relatedTarget) { - var that = this - var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) - - this.$element.trigger(e) - - if (this.isShown || e.isDefaultPrevented()) return - - this.isShown = true - - this.checkScrollbar() - this.setScrollbar() - this.$body.addClass('modal-open') - - this.escape() - this.resize() - - this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) - - this.$dialog.on('mousedown.dismiss.bs.modal', function () { - that.$element.one('mouseup.dismiss.bs.modal', function (e) { - if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true - }) - }) - - this.backdrop(function () { - var transition = $.support.transition && that.$element.hasClass('fade') - - if (!that.$element.parent().length) { - that.$element.appendTo(that.$body) // don't move modals dom position - } - - that.$element - .show() - .scrollTop(0) - - that.adjustDialog() - - if (transition) { - that.$element[0].offsetWidth // force reflow - } - - that.$element.addClass('in') - - that.enforceFocus() - - var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) - - transition ? - that.$dialog // wait for modal to slide in - .one('bsTransitionEnd', function () { - that.$element.trigger('focus').trigger(e) - }) - .emulateTransitionEnd(Modal.TRANSITION_DURATION) : - that.$element.trigger('focus').trigger(e) - }) - } - - Modal.prototype.hide = function (e) { - if (e) e.preventDefault() - - e = $.Event('hide.bs.modal') - - this.$element.trigger(e) - - if (!this.isShown || e.isDefaultPrevented()) return - - this.isShown = false - - this.escape() - this.resize() - - $(document).off('focusin.bs.modal') - - this.$element - .removeClass('in') - .off('click.dismiss.bs.modal') - .off('mouseup.dismiss.bs.modal') - - this.$dialog.off('mousedown.dismiss.bs.modal') - - $.support.transition && this.$element.hasClass('fade') ? - this.$element - .one('bsTransitionEnd', $.proxy(this.hideModal, this)) - .emulateTransitionEnd(Modal.TRANSITION_DURATION) : - this.hideModal() - } - - Modal.prototype.enforceFocus = function () { - $(document) - .off('focusin.bs.modal') // guard against infinite focus loop - .on('focusin.bs.modal', $.proxy(function (e) { - if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { - var $el = $(e.target); - var allowed = Modal.ALLOWED_CONTROL_CLASSES.some(function (className) { - return $el.hasClass(className); - }); - if (!allowed) { - this.$element.trigger('focus') - } - } - }, this)) - } - - Modal.prototype.escape = function () { - if (this.isShown && this.options.keyboard) { - this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { - e.which == 27 && this.hide() - }, this)) - } else if (!this.isShown) { - this.$element.off('keydown.dismiss.bs.modal') - } - } - - Modal.prototype.resize = function () { - if (this.isShown) { - $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) - } else { - $(window).off('resize.bs.modal') - } - } - - Modal.prototype.hideModal = function () { - var that = this - this.$element.hide() - this.backdrop(function () { - that.$body.removeClass('modal-open') - that.resetAdjustments() - that.resetScrollbar() - that.$element.trigger('hidden.bs.modal') - }) - } - - Modal.prototype.removeBackdrop = function () { - this.$backdrop && this.$backdrop.remove() - this.$backdrop = null - } - - Modal.prototype.backdrop = function (callback) { - var that = this - var animate = this.$element.hasClass('fade') ? 'fade' : '' - - if (this.isShown && this.options.backdrop) { - var doAnimate = $.support.transition && animate - - this.$backdrop = $(document.createElement('div')) - .addClass('modal-backdrop ' + animate) - .appendTo(this.$body) - - this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { - if (this.ignoreBackdropClick) { - this.ignoreBackdropClick = false - return - } - if (e.target !== e.currentTarget) return - this.options.backdrop == 'static' - ? this.$element[0].focus() - : this.hide() - }, this)) - - if (doAnimate) this.$backdrop[0].offsetWidth // force reflow - - this.$backdrop.addClass('in') - - if (!callback) return - - doAnimate ? - this.$backdrop - .one('bsTransitionEnd', callback) - .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : - callback() - - } else if (!this.isShown && this.$backdrop) { - this.$backdrop.removeClass('in') - - var callbackRemove = function () { - that.removeBackdrop() - callback && callback() - } - $.support.transition && this.$element.hasClass('fade') ? - this.$backdrop - .one('bsTransitionEnd', callbackRemove) - .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : - callbackRemove() - - } else if (callback) { - callback() - } - } - - // these following methods are used to handle overflowing modals - - Modal.prototype.handleUpdate = function () { - this.adjustDialog() - } - - Modal.prototype.adjustDialog = function () { - var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight - - this.$element.css({ - paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', - paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' - }) - } - - Modal.prototype.resetAdjustments = function () { - this.$element.css({ - paddingLeft: '', - paddingRight: '' - }) - } - - Modal.prototype.checkScrollbar = function () { - var fullWindowWidth = window.innerWidth - if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 - var documentElementRect = document.documentElement.getBoundingClientRect() - fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) - } - this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth - this.scrollbarWidth = this.measureScrollbar() - } - - Modal.prototype.setScrollbar = function () { - var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) - this.originalBodyPad = document.body.style.paddingRight || '' - if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) - } - - Modal.prototype.resetScrollbar = function () { - this.$body.css('padding-right', this.originalBodyPad) - } - - Modal.prototype.measureScrollbar = function () { - if (_isMeasureScrollbar === false) { - _isMeasureScrollbar = true; - _scrollbarWidth = this._measureScrollbar() - } - - return _scrollbarWidth; - } - - Modal.prototype._measureScrollbar = function () { // thx walsh - var scrollDiv = document.createElement('div') - scrollDiv.className = 'modal-scrollbar-measure' - this.$body.append(scrollDiv) - var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth - this.$body[0].removeChild(scrollDiv) - return scrollbarWidth - } - - // MODAL PLUGIN DEFINITION - // ======================= - - function Plugin(option, _relatedTarget) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.modal') - var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) - - if (!data) $this.data('bs.modal', (data = new Modal(this, options))) - if (typeof option == 'string') data[option](_relatedTarget) - else if (options.show) data.show(_relatedTarget) - }) - } - - var old = $.fn.modal - - $.fn.modal = Plugin - $.fn.modal.Constructor = Modal - - - // MODAL NO CONFLICT - // ================= - - $.fn.modal.noConflict = function () { - $.fn.modal = old - return this - } - - - // MODAL DATA-API - // ============== - - $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { - var $this = $(this) - var href = $this.attr('href') - var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 - var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) - - if ($this.is('a')) e.preventDefault() - - $target.one('show.bs.modal', function (showEvent) { - if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown - $target.one('hidden.bs.modal', function () { - $this.is(':visible') && $this.trigger('focus') - }) - }) - Plugin.call($target, option, this) - }) - -}(jQuery); diff --git a/bootstrap-framework/js/popover.js b/bootstrap-framework/js/popover.js deleted file mode 100644 index aef22d1..0000000 --- a/bootstrap-framework/js/popover.js +++ /dev/null @@ -1,108 +0,0 @@ -/* ======================================================================== - * Bootstrap: popover.js v3.3.5 - * http://getbootstrap.com/javascript/#popovers - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // POPOVER PUBLIC CLASS DEFINITION - // =============================== - - var Popover = function (element, options) { - this.init('popover', element, options) - } - - if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') - - Popover.VERSION = '3.3.5' - - Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { - placement: 'right', - trigger: 'click', - content: '', - template: '' - }) - - - // NOTE: POPOVER EXTENDS tooltip.js - // ================================ - - Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) - - Popover.prototype.constructor = Popover - - Popover.prototype.getDefaults = function () { - return Popover.DEFAULTS - } - - Popover.prototype.setContent = function () { - var $tip = this.tip() - var title = this.getTitle() - var content = this.getContent() - - $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) - $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events - this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' - ](content) - - $tip.removeClass('fade top bottom left right in') - - // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do - // this manually by checking the contents. - if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() - } - - Popover.prototype.hasContent = function () { - return this.getTitle() || this.getContent() - } - - Popover.prototype.getContent = function () { - var $e = this.$element - var o = this.options - - return $e.attr('data-content') - || (typeof o.content == 'function' ? - o.content.call($e[0]) : - o.content) - } - - Popover.prototype.arrow = function () { - return (this.$arrow = this.$arrow || this.tip().find('.arrow')) - } - - - // POPOVER PLUGIN DEFINITION - // ========================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.popover') - var options = typeof option == 'object' && option - - if (!data && /destroy|hide/.test(option)) return - if (!data) $this.data('bs.popover', (data = new Popover(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.popover - - $.fn.popover = Plugin - $.fn.popover.Constructor = Popover - - - // POPOVER NO CONFLICT - // =================== - - $.fn.popover.noConflict = function () { - $.fn.popover = old - return this - } - -}(jQuery); diff --git a/bootstrap-framework/js/scrollspy.js b/bootstrap-framework/js/scrollspy.js deleted file mode 100644 index 7208e25..0000000 --- a/bootstrap-framework/js/scrollspy.js +++ /dev/null @@ -1,172 +0,0 @@ -/* ======================================================================== - * Bootstrap: scrollspy.js v3.3.5 - * http://getbootstrap.com/javascript/#scrollspy - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // SCROLLSPY CLASS DEFINITION - // ========================== - - function ScrollSpy(element, options) { - this.$body = $(document.body) - this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) - this.options = $.extend({}, ScrollSpy.DEFAULTS, options) - this.selector = (this.options.target || '') + ' .nav li > a' - this.offsets = [] - this.targets = [] - this.activeTarget = null - this.scrollHeight = 0 - - this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) - this.refresh() - this.process() - } - - ScrollSpy.VERSION = '3.3.5' - - ScrollSpy.DEFAULTS = { - offset: 10 - } - - ScrollSpy.prototype.getScrollHeight = function () { - return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) - } - - ScrollSpy.prototype.refresh = function () { - var that = this - var offsetMethod = 'offset' - var offsetBase = 0 - - this.offsets = [] - this.targets = [] - this.scrollHeight = this.getScrollHeight() - - if (!$.isWindow(this.$scrollElement[0])) { - offsetMethod = 'position' - offsetBase = this.$scrollElement.scrollTop() - } - - this.$body - .find(this.selector) - .map(function () { - var $el = $(this) - var href = $el.data('target') || $el.attr('href') - var $href = /^#./.test(href) && $(href) - - return ($href - && $href.length - && $href.is(':visible') - && [[$href[offsetMethod]().top + offsetBase, href]]) || null - }) - .sort(function (a, b) { return a[0] - b[0] }) - .each(function () { - that.offsets.push(this[0]) - that.targets.push(this[1]) - }) - } - - ScrollSpy.prototype.process = function () { - var scrollTop = this.$scrollElement.scrollTop() + this.options.offset - var scrollHeight = this.getScrollHeight() - var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() - var offsets = this.offsets - var targets = this.targets - var activeTarget = this.activeTarget - var i - - if (this.scrollHeight != scrollHeight) { - this.refresh() - } - - if (scrollTop >= maxScroll) { - return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) - } - - if (activeTarget && scrollTop < offsets[0]) { - this.activeTarget = null - return this.clear() - } - - for (i = offsets.length; i--;) { - activeTarget != targets[i] - && scrollTop >= offsets[i] - && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) - && this.activate(targets[i]) - } - } - - ScrollSpy.prototype.activate = function (target) { - this.activeTarget = target - - this.clear() - - var selector = this.selector + - '[data-target="' + target + '"],' + - this.selector + '[href="' + target + '"]' - - var active = $(selector) - .parents('li') - .addClass('active') - - if (active.parent('.dropdown-menu').length) { - active = active - .closest('li.dropdown') - .addClass('active') - } - - active.trigger('activate.bs.scrollspy') - } - - ScrollSpy.prototype.clear = function () { - $(this.selector) - .parentsUntil(this.options.target, '.active') - .removeClass('active') - } - - - // SCROLLSPY PLUGIN DEFINITION - // =========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.scrollspy') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.scrollspy - - $.fn.scrollspy = Plugin - $.fn.scrollspy.Constructor = ScrollSpy - - - // SCROLLSPY NO CONFLICT - // ===================== - - $.fn.scrollspy.noConflict = function () { - $.fn.scrollspy = old - return this - } - - - // SCROLLSPY DATA-API - // ================== - - $(window).on('load.bs.scrollspy.data-api', function () { - $('[data-spy="scroll"]').each(function () { - var $spy = $(this) - Plugin.call($spy, $spy.data()) - }) - }) - -}(jQuery); diff --git a/bootstrap-framework/js/tab.js b/bootstrap-framework/js/tab.js deleted file mode 100644 index 8d5361f..0000000 --- a/bootstrap-framework/js/tab.js +++ /dev/null @@ -1,155 +0,0 @@ -/* ======================================================================== - * Bootstrap: tab.js v3.3.5 - * http://getbootstrap.com/javascript/#tabs - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // TAB CLASS DEFINITION - // ==================== - - var Tab = function (element) { - // jscs:disable requireDollarBeforejQueryAssignment - this.element = $(element) - // jscs:enable requireDollarBeforejQueryAssignment - } - - Tab.VERSION = '3.3.5' - - Tab.TRANSITION_DURATION = 150 - - Tab.prototype.show = function () { - var $this = this.element - var $ul = $this.closest('ul:not(.dropdown-menu)') - var selector = $this.data('target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - if ($this.parent('li').hasClass('active')) return - - var $previous = $ul.find('.active:last a') - var hideEvent = $.Event('hide.bs.tab', { - relatedTarget: $this[0] - }) - var showEvent = $.Event('show.bs.tab', { - relatedTarget: $previous[0] - }) - - $previous.trigger(hideEvent) - $this.trigger(showEvent) - - if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return - - var $target = $(selector) - - this.activate($this.closest('li'), $ul) - this.activate($target, $target.parent(), function () { - $previous.trigger({ - type: 'hidden.bs.tab', - relatedTarget: $this[0] - }) - $this.trigger({ - type: 'shown.bs.tab', - relatedTarget: $previous[0] - }) - }) - } - - Tab.prototype.activate = function (element, container, callback) { - var $active = container.find('> .active') - var transition = callback - && $.support.transition - && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) - - function next() { - $active - .removeClass('active') - .find('> .dropdown-menu > .active') - .removeClass('active') - .end() - .find('[data-toggle="tab"]') - .attr('aria-expanded', false) - - element - .addClass('active') - .find('[data-toggle="tab"]') - .attr('aria-expanded', true) - - if (transition) { - element[0].offsetWidth // reflow for transition - element.addClass('in') - } else { - element.removeClass('fade') - } - - if (element.parent('.dropdown-menu').length) { - element - .closest('li.dropdown') - .addClass('active') - .end() - .find('[data-toggle="tab"]') - .attr('aria-expanded', true) - } - - callback && callback() - } - - $active.length && transition ? - $active - .one('bsTransitionEnd', next) - .emulateTransitionEnd(Tab.TRANSITION_DURATION) : - next() - - $active.removeClass('in') - } - - - // TAB PLUGIN DEFINITION - // ===================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.tab') - - if (!data) $this.data('bs.tab', (data = new Tab(this))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.tab - - $.fn.tab = Plugin - $.fn.tab.Constructor = Tab - - - // TAB NO CONFLICT - // =============== - - $.fn.tab.noConflict = function () { - $.fn.tab = old - return this - } - - - // TAB DATA-API - // ============ - - var clickHandler = function (e) { - e.preventDefault() - Plugin.call($(this), 'show') - } - - $(document) - .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) - .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) - -}(jQuery); diff --git a/bootstrap-framework/js/tooltip.js b/bootstrap-framework/js/tooltip.js deleted file mode 100644 index c3fe4b0..0000000 --- a/bootstrap-framework/js/tooltip.js +++ /dev/null @@ -1,514 +0,0 @@ -/* ======================================================================== - * Bootstrap: tooltip.js v3.3.5 - * http://getbootstrap.com/javascript/#tooltip - * Inspired by the original jQuery.tipsy by Jason Frame - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // TOOLTIP PUBLIC CLASS DEFINITION - // =============================== - - var Tooltip = function (element, options) { - this.type = null - this.options = null - this.enabled = null - this.timeout = null - this.hoverState = null - this.$element = null - this.inState = null - - this.init('tooltip', element, options) - } - - Tooltip.VERSION = '3.3.5' - - Tooltip.TRANSITION_DURATION = 150 - - Tooltip.DEFAULTS = { - animation: true, - placement: 'top', - selector: false, - template: '', - trigger: 'hover focus', - title: '', - delay: 0, - html: false, - container: false, - viewport: { - selector: 'body', - padding: 0 - } - } - - Tooltip.prototype.init = function (type, element, options) { - this.enabled = true - this.type = type - this.$element = $(element) - this.options = this.getOptions(options) - this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) - this.inState = { click: false, hover: false, focus: false } - - if (this.$element[0] instanceof document.constructor && !this.options.selector) { - throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') - } - - var triggers = this.options.trigger.split(' ') - - for (var i = triggers.length; i--;) { - var trigger = triggers[i] - - if (trigger == 'click') { - this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) - } else if (trigger != 'manual') { - var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' - var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' - - this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) - this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) - } - } - - this.options.selector ? - (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : - this.fixTitle() - } - - Tooltip.prototype.getDefaults = function () { - return Tooltip.DEFAULTS - } - - Tooltip.prototype.getOptions = function (options) { - options = $.extend({}, this.getDefaults(), this.$element.data(), options) - - if (options.delay && typeof options.delay == 'number') { - options.delay = { - show: options.delay, - hide: options.delay - } - } - - return options - } - - Tooltip.prototype.getDelegateOptions = function () { - var options = {} - var defaults = this.getDefaults() - - this._options && $.each(this._options, function (key, value) { - if (defaults[key] != value) options[key] = value - }) - - return options - } - - Tooltip.prototype.enter = function (obj) { - var self = obj instanceof this.constructor ? - obj : $(obj.currentTarget).data('bs.' + this.type) - - if (!self) { - self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) - $(obj.currentTarget).data('bs.' + this.type, self) - } - - if (obj instanceof $.Event) { - self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true - } - - if (self.tip().hasClass('in') || self.hoverState == 'in') { - self.hoverState = 'in' - return - } - - clearTimeout(self.timeout) - - self.hoverState = 'in' - - if (!self.options.delay || !self.options.delay.show) return self.show() - - self.timeout = setTimeout(function () { - if (self.hoverState == 'in') self.show() - }, self.options.delay.show) - } - - Tooltip.prototype.isInStateTrue = function () { - for (var key in this.inState) { - if (this.inState[key]) return true - } - - return false - } - - Tooltip.prototype.leave = function (obj) { - var self = obj instanceof this.constructor ? - obj : $(obj.currentTarget).data('bs.' + this.type) - - if (!self) { - self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) - $(obj.currentTarget).data('bs.' + this.type, self) - } - - if (obj instanceof $.Event) { - self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false - } - - if (self.isInStateTrue()) return - - clearTimeout(self.timeout) - - self.hoverState = 'out' - - if (!self.options.delay || !self.options.delay.hide) return self.hide() - - self.timeout = setTimeout(function () { - if (self.hoverState == 'out') self.hide() - }, self.options.delay.hide) - } - - Tooltip.prototype.show = function () { - var e = $.Event('show.bs.' + this.type) - - if (this.hasContent() && this.enabled) { - this.$element.trigger(e) - - var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) - if (e.isDefaultPrevented() || !inDom) return - var that = this - - var $tip = this.tip() - - var tipId = this.getUID(this.type) - - this.setContent() - $tip.attr('id', tipId) - this.$element.attr('aria-describedby', tipId) - - if (this.options.animation) $tip.addClass('fade') - - var placement = typeof this.options.placement == 'function' ? - this.options.placement.call(this, $tip[0], this.$element[0]) : - this.options.placement - - var autoToken = /\s?auto?\s?/i - var autoPlace = autoToken.test(placement) - if (autoPlace) placement = placement.replace(autoToken, '') || 'top' - - $tip - .detach() - .css({ top: 0, left: 0, display: 'block' }) - .addClass(placement) - .data('bs.' + this.type, this) - - this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) - this.$element.trigger('inserted.bs.' + this.type) - - var pos = this.getPosition() - var actualWidth = $tip[0].offsetWidth - var actualHeight = $tip[0].offsetHeight - - if (autoPlace) { - var orgPlacement = placement - var viewportDim = this.getPosition(this.$viewport) - - placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : - placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : - placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : - placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : - placement - - $tip - .removeClass(orgPlacement) - .addClass(placement) - } - - var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) - - this.applyPlacement(calculatedOffset, placement) - - var complete = function () { - var prevHoverState = that.hoverState - that.$element.trigger('shown.bs.' + that.type) - that.hoverState = null - - if (prevHoverState == 'out') that.leave(that) - } - - $.support.transition && this.$tip.hasClass('fade') ? - $tip - .one('bsTransitionEnd', complete) - .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : - complete() - } - } - - Tooltip.prototype.applyPlacement = function (offset, placement) { - var $tip = this.tip() - var width = $tip[0].offsetWidth - var height = $tip[0].offsetHeight - - // manually read margins because getBoundingClientRect includes difference - var marginTop = parseInt($tip.css('margin-top'), 10) - var marginLeft = parseInt($tip.css('margin-left'), 10) - - // we must check for NaN for ie 8/9 - if (isNaN(marginTop)) marginTop = 0 - if (isNaN(marginLeft)) marginLeft = 0 - - offset.top += marginTop - offset.left += marginLeft - - // $.fn.offset doesn't round pixel values - // so we use setOffset directly with our own function B-0 - $.offset.setOffset($tip[0], $.extend({ - using: function (props) { - $tip.css({ - top: Math.round(props.top), - left: Math.round(props.left) - }) - } - }, offset), 0) - - $tip.addClass('in') - - // check to see if placing tip in new offset caused the tip to resize itself - var actualWidth = $tip[0].offsetWidth - var actualHeight = $tip[0].offsetHeight - - if (placement == 'top' && actualHeight != height) { - offset.top = offset.top + height - actualHeight - } - - var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) - - if (delta.left) offset.left += delta.left - else offset.top += delta.top - - var isVertical = /top|bottom/.test(placement) - var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight - var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' - - $tip.offset(offset) - this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) - } - - Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { - this.arrow() - .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') - .css(isVertical ? 'top' : 'left', '') - } - - Tooltip.prototype.setContent = function () { - var $tip = this.tip() - var title = this.getTitle() - - $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) - $tip.removeClass('fade in top bottom left right') - } - - Tooltip.prototype.hide = function (callback) { - var that = this - var $tip = $(this.$tip) - var e = $.Event('hide.bs.' + this.type) - - function complete() { - if (that.hoverState != 'in') $tip.detach() - that.$element - .removeAttr('aria-describedby') - .trigger('hidden.bs.' + that.type) - callback && callback() - } - - this.$element.trigger(e) - - if (e.isDefaultPrevented()) return - - $tip.removeClass('in') - - $.support.transition && $tip.hasClass('fade') ? - $tip - .one('bsTransitionEnd', complete) - .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : - complete() - - this.hoverState = null - - return this - } - - Tooltip.prototype.fixTitle = function () { - var $e = this.$element - if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { - $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') - } - } - - Tooltip.prototype.hasContent = function () { - return this.getTitle() - } - - Tooltip.prototype.getPosition = function ($element) { - $element = $element || this.$element - - var el = $element[0] - var isBody = el.tagName == 'BODY' - - var elRect = el.getBoundingClientRect() - if (elRect.width == null) { - // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 - elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) - } - var elOffset = isBody ? { top: 0, left: 0 } : $element.offset() - var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } - var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null - - return $.extend({}, elRect, scroll, outerDims, elOffset) - } - - Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { - return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : - placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : - placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : - /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } - - } - - Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { - var delta = { top: 0, left: 0 } - if (!this.$viewport) return delta - - var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 - var viewportDimensions = this.getPosition(this.$viewport) - - if (/right|left/.test(placement)) { - var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll - var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight - if (topEdgeOffset < viewportDimensions.top) { // top overflow - delta.top = viewportDimensions.top - topEdgeOffset - } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow - delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset - } - } else { - var leftEdgeOffset = pos.left - viewportPadding - var rightEdgeOffset = pos.left + viewportPadding + actualWidth - if (leftEdgeOffset < viewportDimensions.left) { // left overflow - delta.left = viewportDimensions.left - leftEdgeOffset - } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow - delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset - } - } - - return delta - } - - Tooltip.prototype.getTitle = function () { - var title - var $e = this.$element - var o = this.options - - title = $e.attr('data-original-title') - || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) - - return title - } - - Tooltip.prototype.getUID = function (prefix) { - do prefix += ~~(Math.random() * 1000000) - while (document.getElementById(prefix)) - return prefix - } - - Tooltip.prototype.tip = function () { - if (!this.$tip) { - this.$tip = $(this.options.template) - if (this.$tip.length != 1) { - throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') - } - } - return this.$tip - } - - Tooltip.prototype.arrow = function () { - return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) - } - - Tooltip.prototype.enable = function () { - this.enabled = true - } - - Tooltip.prototype.disable = function () { - this.enabled = false - } - - Tooltip.prototype.toggleEnabled = function () { - this.enabled = !this.enabled - } - - Tooltip.prototype.toggle = function (e) { - var self = this - if (e) { - self = $(e.currentTarget).data('bs.' + this.type) - if (!self) { - self = new this.constructor(e.currentTarget, this.getDelegateOptions()) - $(e.currentTarget).data('bs.' + this.type, self) - } - } - - if (e) { - self.inState.click = !self.inState.click - if (self.isInStateTrue()) self.enter(self) - else self.leave(self) - } else { - self.tip().hasClass('in') ? self.leave(self) : self.enter(self) - } - } - - Tooltip.prototype.destroy = function () { - var that = this - clearTimeout(this.timeout) - this.hide(function () { - that.$element.off('.' + that.type).removeData('bs.' + that.type) - if (that.$tip) { - that.$tip.detach() - } - that.$tip = null - that.$arrow = null - that.$viewport = null - }) - } - - - // TOOLTIP PLUGIN DEFINITION - // ========================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.tooltip') - var options = typeof option == 'object' && option - - if (!data && /destroy|hide/.test(option)) return - if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.tooltip - - $.fn.tooltip = Plugin - $.fn.tooltip.Constructor = Tooltip - - - // TOOLTIP NO CONFLICT - // =================== - - $.fn.tooltip.noConflict = function () { - $.fn.tooltip = old - return this - } - -}(jQuery); diff --git a/bootstrap-framework/js/transition.js b/bootstrap-framework/js/transition.js deleted file mode 100644 index cd89fc4..0000000 --- a/bootstrap-framework/js/transition.js +++ /dev/null @@ -1,59 +0,0 @@ -/* ======================================================================== - * Bootstrap: transition.js v3.3.5 - * http://getbootstrap.com/javascript/#transitions - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) - // ============================================================ - - function transitionEnd() { - var el = document.createElement('bootstrap') - - var transEndEventNames = { - WebkitTransition : 'webkitTransitionEnd', - MozTransition : 'transitionend', - OTransition : 'oTransitionEnd otransitionend', - transition : 'transitionend' - } - - for (var name in transEndEventNames) { - if (el.style[name] !== undefined) { - return { end: transEndEventNames[name] } - } - } - - return false // explicit for ie8 ( ._.) - } - - // http://blog.alexmaccaw.com/css-transitions - $.fn.emulateTransitionEnd = function (duration) { - var called = false - var $el = this - $(this).one('bsTransitionEnd', function () { called = true }) - var callback = function () { if (!called) $($el).trigger($.support.transition.end) } - setTimeout(callback, duration) - return this - } - - $(function () { - $.support.transition = transitionEnd() - - if (!$.support.transition) return - - $.event.special.bsTransitionEnd = { - bindType: $.support.transition.end, - delegateType: $.support.transition.end, - handle: function (e) { - if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) - } - } - }) - -}(jQuery); diff --git a/bootstrap-framework/less/.csscomb.json b/bootstrap-framework/less/.csscomb.json deleted file mode 100644 index 40695a4..0000000 --- a/bootstrap-framework/less/.csscomb.json +++ /dev/null @@ -1,304 +0,0 @@ -{ - "always-semicolon": true, - "block-indent": 2, - "color-case": "lower", - "color-shorthand": true, - "element-case": "lower", - "eof-newline": true, - "leading-zero": false, - "remove-empty-rulesets": true, - "space-after-colon": 1, - "space-after-combinator": 1, - "space-before-selector-delimiter": 0, - "space-between-declarations": "\n", - "space-after-opening-brace": "\n", - "space-before-closing-brace": "\n", - "space-before-colon": 0, - "space-before-combinator": 1, - "space-before-opening-brace": 1, - "strip-spaces": true, - "unitless-zero": true, - "vendor-prefix-align": true, - "sort-order": [ - [ - "position", - "top", - "right", - "bottom", - "left", - "z-index", - "display", - "float", - "width", - "min-width", - "max-width", - "height", - "min-height", - "max-height", - "-webkit-box-sizing", - "-moz-box-sizing", - "box-sizing", - "-webkit-appearance", - "padding", - "padding-top", - "padding-right", - "padding-bottom", - "padding-left", - "margin", - "margin-top", - "margin-right", - "margin-bottom", - "margin-left", - "overflow", - "overflow-x", - "overflow-y", - "-webkit-overflow-scrolling", - "-ms-overflow-x", - "-ms-overflow-y", - "-ms-overflow-style", - "clip", - "clear", - "font", - "font-family", - "font-size", - "font-style", - "font-weight", - "font-variant", - "font-size-adjust", - "font-stretch", - "font-effect", - "font-emphasize", - "font-emphasize-position", - "font-emphasize-style", - "font-smooth", - "-webkit-hyphens", - "-moz-hyphens", - "hyphens", - "line-height", - "color", - "text-align", - "-webkit-text-align-last", - "-moz-text-align-last", - "-ms-text-align-last", - "text-align-last", - "text-emphasis", - "text-emphasis-color", - "text-emphasis-style", - "text-emphasis-position", - "text-decoration", - "text-indent", - "text-justify", - "text-outline", - "-ms-text-overflow", - "text-overflow", - "text-overflow-ellipsis", - "text-overflow-mode", - "text-shadow", - "text-transform", - "text-wrap", - "-webkit-text-size-adjust", - "-ms-text-size-adjust", - "letter-spacing", - "-ms-word-break", - "word-break", - "word-spacing", - "-ms-word-wrap", - "word-wrap", - "-moz-tab-size", - "-o-tab-size", - "tab-size", - "white-space", - "vertical-align", - "list-style", - "list-style-position", - "list-style-type", - "list-style-image", - "pointer-events", - "-ms-touch-action", - "touch-action", - "cursor", - "visibility", - "zoom", - "flex-direction", - "flex-order", - "flex-pack", - "flex-align", - "table-layout", - "empty-cells", - "caption-side", - "border-spacing", - "border-collapse", - "content", - "quotes", - "counter-reset", - "counter-increment", - "resize", - "-webkit-user-select", - "-moz-user-select", - "-ms-user-select", - "-o-user-select", - "user-select", - "nav-index", - "nav-up", - "nav-right", - "nav-down", - "nav-left", - "background", - "background-color", - "background-image", - "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient", - "filter:progid:DXImageTransform.Microsoft.gradient", - "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader", - "filter", - "background-repeat", - "background-attachment", - "background-position", - "background-position-x", - "background-position-y", - "-webkit-background-clip", - "-moz-background-clip", - "background-clip", - "background-origin", - "-webkit-background-size", - "-moz-background-size", - "-o-background-size", - "background-size", - "border", - "border-color", - "border-style", - "border-width", - "border-top", - "border-top-color", - "border-top-style", - "border-top-width", - "border-right", - "border-right-color", - "border-right-style", - "border-right-width", - "border-bottom", - "border-bottom-color", - "border-bottom-style", - "border-bottom-width", - "border-left", - "border-left-color", - "border-left-style", - "border-left-width", - "border-radius", - "border-top-left-radius", - "border-top-right-radius", - "border-bottom-right-radius", - "border-bottom-left-radius", - "-webkit-border-image", - "-moz-border-image", - "-o-border-image", - "border-image", - "-webkit-border-image-source", - "-moz-border-image-source", - "-o-border-image-source", - "border-image-source", - "-webkit-border-image-slice", - "-moz-border-image-slice", - "-o-border-image-slice", - "border-image-slice", - "-webkit-border-image-width", - "-moz-border-image-width", - "-o-border-image-width", - "border-image-width", - "-webkit-border-image-outset", - "-moz-border-image-outset", - "-o-border-image-outset", - "border-image-outset", - "-webkit-border-image-repeat", - "-moz-border-image-repeat", - "-o-border-image-repeat", - "border-image-repeat", - "outline", - "outline-width", - "outline-style", - "outline-color", - "outline-offset", - "-webkit-box-shadow", - "-moz-box-shadow", - "box-shadow", - "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity", - "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha", - "opacity", - "-ms-interpolation-mode", - "-webkit-transition", - "-moz-transition", - "-ms-transition", - "-o-transition", - "transition", - "-webkit-transition-delay", - "-moz-transition-delay", - "-ms-transition-delay", - "-o-transition-delay", - "transition-delay", - "-webkit-transition-timing-function", - "-moz-transition-timing-function", - "-ms-transition-timing-function", - "-o-transition-timing-function", - "transition-timing-function", - "-webkit-transition-duration", - "-moz-transition-duration", - "-ms-transition-duration", - "-o-transition-duration", - "transition-duration", - "-webkit-transition-property", - "-moz-transition-property", - "-ms-transition-property", - "-o-transition-property", - "transition-property", - "-webkit-transform", - "-moz-transform", - "-ms-transform", - "-o-transform", - "transform", - "-webkit-transform-origin", - "-moz-transform-origin", - "-ms-transform-origin", - "-o-transform-origin", - "transform-origin", - "-webkit-animation", - "-moz-animation", - "-ms-animation", - "-o-animation", - "animation", - "-webkit-animation-name", - "-moz-animation-name", - "-ms-animation-name", - "-o-animation-name", - "animation-name", - "-webkit-animation-duration", - "-moz-animation-duration", - "-ms-animation-duration", - "-o-animation-duration", - "animation-duration", - "-webkit-animation-play-state", - "-moz-animation-play-state", - "-ms-animation-play-state", - "-o-animation-play-state", - "animation-play-state", - "-webkit-animation-timing-function", - "-moz-animation-timing-function", - "-ms-animation-timing-function", - "-o-animation-timing-function", - "animation-timing-function", - "-webkit-animation-delay", - "-moz-animation-delay", - "-ms-animation-delay", - "-o-animation-delay", - "animation-delay", - "-webkit-animation-iteration-count", - "-moz-animation-iteration-count", - "-ms-animation-iteration-count", - "-o-animation-iteration-count", - "animation-iteration-count", - "-webkit-animation-direction", - "-moz-animation-direction", - "-ms-animation-direction", - "-o-animation-direction", - "animation-direction" - ] - ] -} diff --git a/bootstrap-framework/less/.csslintrc b/bootstrap-framework/less/.csslintrc deleted file mode 100644 index 005b862..0000000 --- a/bootstrap-framework/less/.csslintrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "adjoining-classes": false, - "box-sizing": false, - "box-model": false, - "compatible-vendor-prefixes": false, - "floats": false, - "font-sizes": false, - "gradients": false, - "important": false, - "known-properties": false, - "outline-none": false, - "qualified-headings": false, - "regex-selectors": false, - "shorthand": false, - "text-indent": false, - "unique-headings": false, - "universal-selector": false, - "unqualified-attributes": false -} diff --git a/bower.json b/bower.json deleted file mode 100644 index f3529e2..0000000 --- a/bower.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "infinni-ui", - "homepage": "https://github.com/InfinniPlatform/InfinniUI", - "authors": [ - "InfinnitySolutions " - ], - "description": "", - "main": "", - "moduleType": [], - "keywords": [ - "infinnitysolutions", - "infinnity", - "infinni-ui", - "ui-framework" - ], - "license": "GPL", - "dependencies": { - "infinni-ui-metadata": "latest" - } -} diff --git a/example/gulpfile.js/index.js b/example/gulpfile.js/index.js index d3f25a8..79d267a 100644 --- a/example/gulpfile.js/index.js +++ b/example/gulpfile.js/index.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict'; var help = ''; var gulp = require('gulp'), watch = require('gulp-watch'), diff --git a/example/www/config.js b/example/www/config.js index 8d3c29f..c52f886 100644 --- a/example/www/config.js +++ b/example/www/config.js @@ -1,5 +1,6 @@ window.InfinniUI = window.InfinniUI || {}; window.InfinniUI.config = window.InfinniUI.config || {}; +window.InfinniUI.config.lang = 'en-US'; // перекрываем дефолтные конфиги, лежащие в InfinniUI/app/config.js diff --git a/example/www/js/main.js b/example/www/js/main.js deleted file mode 100644 index 4b2d60a..0000000 --- a/example/www/js/main.js +++ /dev/null @@ -1,135 +0,0 @@ -if(InfinniUI.config.configName != null) { - document.title = InfinniUI.config.configName; -} - -moment.locale('ru'); - -(function ($target/*, metadata*/, homePageMetadata) { - - var host = InfinniUI.config.serverUrl; - - InfinniUI.providerRegister.register('ObjectDataSource', InfinniUI.Providers.ObjectDataProvider); - - setTimeout(InfinniUI.LayoutManager.init.bind(InfinniUI.LayoutManager), 1000); - - - InfinniUI.providerRegister.register('MetadataDataSource', function (metadataValue) { - var $pageContent = $('body'); - for (var i = 3; i >= 0; i--) { - setTimeout(function () { - InfinniUI.LayoutManager.init(); - }, 500 + i * 300); - } - - return new InfinniUI.Providers.MetadataProviderREST(new InfinniUI.Providers.QueryConstructorMetadata(host, metadataValue)); - }); - - /** - * @description При изменении размеров окна пересчитывает высоту элементов представления - */ - InfinniUI.AutoHeightService = (function () { - var TIMEOUT = 40; - var WAIT = 50; - var resizeTimeout; - - $(window).resize(function () { - clearTimeout(resizeTimeout); - resizeTimeout = setTimeout(_.debounce(onWindowResize, WAIT), TIMEOUT); - }); - - function onWindowResize() { - InfinniUI.LayoutManager.init(); - } - - })(); - - InfinniUI.providerRegister.register('DocumentDataSource', InfinniUI.Providers.RestDataProvider); - InfinniUI.providerRegister.register('RestDataSource', InfinniUI.Providers.RestDataProvider); - - InfinniUI.providerRegister.register('ServerActionProvider', function () { - return new InfinniUI.Providers.ServerActionProvider(); - }); - - var builder = new InfinniUI.ApplicationBuilder(), - rootView = new SpecialApplicationView(), - mainView; - - InfinniUI.global.messageBus.subscribe('onViewCreated', function (context, args) { - if(args.value.openMode == 'Default') { - window.contextApp = args.value.view; - } - }); - - rootView.open($target); - openHomePage() - .done(function (viewMetadata) { - var action = builder.buildType('OpenAction', viewMetadata, {parentView: rootView}); - action.execute(function() { - if( window.InfinniUI.RouterService ) { - window.InfinniUI.RouterService.startRouter(); - } - }); - }); - - function openHomePage() { - var defer = $.Deferred(); - - if (typeof homePageMetadata === 'string') { - $.ajax({ - url: homePageMetadata, - dataType: "json" - }) - .then(function (data) { - defer.resolve({ - LinkView: { - InlineView: { - View: data - } - } - }) - }, function (jqXHR, textStatus, errorThrown) { - console.error(textStatus); - }); - } else { - defer.resolve({ - LinkView: { - AutoView: homePageMetadata - } - }); - } - return defer.promise(); - } - -})( - $('body'), - window.InfinniUI.config.homePage -); - - -function SpecialApplicationView() { - var $container; - - this.isView = true; - - this.getContainer = function () { - return this.$container; - }; - - this.open = function ($el) { - this.$container = $el; - }; - - this.getApplicationView = function () { - return this; - }; - - this.menuIsInitialized = function () { - this.isMenuInitialized = true; - - //this.initViewHandlers(); - }; - - this.getContext = function(){ - return null; - }; -} diff --git a/example/www/testConfigurations/stab.json b/example/www/testConfigurations/stab.json index 29cb3ea..07987f1 100644 --- a/example/www/testConfigurations/stab.json +++ b/example/www/testConfigurations/stab.json @@ -400,6 +400,7 @@ { "Button": { "Text": "submit", + "ToolTip": "HEllo!", "OnClick": "{debugger; console.log(context);}" } } diff --git a/example/www/testConfigurations/treeview.json b/example/www/testConfigurations/treeview.json index 1ba298f..6d81122 100644 --- a/example/www/testConfigurations/treeview.json +++ b/example/www/testConfigurations/treeview.json @@ -1,56 +1,56 @@ -{ - "DataSources": [ - { - "ObjectDataSource": { - "Name": "Geo", - "Items": [ - { - "Id": 1, - "ParentId": null, - "Name": "Челябинск" - }, - { - "Id": 2, - "ParentId": 1, - "Name": "Чичерина" - }, - { - "Id": 3, - "ParentId": 1, - "Name": "Комарова" - }, - { - "Id": 4, - "ParentId": null, - "Name": "Копейск" - }, - { - "Id": 5, - "ParentId": 4, - "Name": "Победы" - }, - { - "Id": 6, - "ParentId": 5, - "Name": "33/1" - } - ] - } - } - ], - "Items": [ - { - "TreeView": { - "KeyProperty": "Id", - "ParentProperty": "ParentId", - "ItemProperty": "Name", - "ValueProperty": "Name", - "MultiSelect": true, - "Items": { - "Source": "Geo" - } - } - } - ] -} - +{ + "DataSources": [ + { + "ObjectDataSource": { + "Name": "Geo", + "Items": [ + { + "Id": 1, + "ParentId": null, + "Name": "Челябинск" + }, + { + "Id": 2, + "ParentId": 1, + "Name": "Чичерина" + }, + { + "Id": 3, + "ParentId": 1, + "Name": "Комарова" + }, + { + "Id": 4, + "ParentId": null, + "Name": "Копейск" + }, + { + "Id": 5, + "ParentId": 4, + "Name": "Победы" + }, + { + "Id": 6, + "ParentId": 5, + "Name": "33/1" + } + ] + } + } + ], + "Items": [ + { + "TreeView": { + "KeyProperty": "Id", + "ParentProperty": "ParentId", + "ItemProperty": "Name", + "ValueProperty": "Name", + "MultiSelect": true, + "Items": { + "Source": "Geo" + } + } + } + ] +} + diff --git a/example/www/viewExample/tooltip.json b/example/www/viewExample/tooltip.json new file mode 100644 index 0000000..d7d29fb --- /dev/null +++ b/example/www/viewExample/tooltip.json @@ -0,0 +1,58 @@ +{ + "DataSources": [{ + "ObjectDataSource": { + "Name": "TestDS", + "Items": [{ + "Items": [{}] + }] + } + }], + "Items": [{ + "StackPanel": { + "Items": { + "Source": "TestDS", + "Property": "$.Items" + }, + "ItemTemplate": { + "StackPanel": { + "Orientation": "Horizontal", + "Items": [{ + "TextBox": { + "LabelText": "Label", + "Value": { + "Source": "TestDS", + "Property": "$.Items.#.Value" + } + } + }, + { + "Button": { + "Text": "Удалить", + "ToolTip": { + "Label": { + "Text": { + "Source": "TestDS", + "Property": "@.#.Value" + } + } + }, + "Tag": { + "Source": "TestDS", + "Property": "@.#" + }, + "OnClick": "{var items = context.dataSources.TestDS.getProperty('$.Items'); items = _.reject(items, function(i) {return i === args.source.getTag();}); context.dataSources.TestDS.setProperty('$.Items', items);}" + } + } + ] + } + } + } + }, + { + "Button": { + "Text": "Добавить ещё", + "OnClick": "{var items = context.dataSources.TestDS.getProperty('$.Items'); items.push({}); context.dataSources.TestDS.setProperty('$.Items', _.clone(items));}" + } + } + ] +} \ No newline at end of file diff --git a/out/css/main.css b/out/css/main.css index f499e67..457d36a 100644 --- a/out/css/main.css +++ b/out/css/main.css @@ -12,4 +12,4 @@ html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:1 * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ -.form-control{box-shadow:none}.btn:focus,.btn:hover{border-color:transparent}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{background-repeat:repeat-x}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary:focus,.btn-primary:hover{background-color:#1a5f5f;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#1a5f5f;border-color:#185757}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#1a5f5f;background-image:none}.btn-success:focus,.btn-success:hover{background-color:#39843c;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#39843c;border-color:#367d39}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#39843c;background-image:none}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger:focus,.btn-danger:hover{background-color:#b0141a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#b0141a;border-color:#a71318}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#b0141a;background-image:none}.img-thumbnail,.thumbnail{box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a{width:100%}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#227b7b}.navbar-default{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border-radius:3px;box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border-radius:3px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:linear-gradient(to bottom,#278f8f 0%,#227b7b 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,39,143,0.5607843137254902)', endColorstr='#ff227b7b', GradientType=0)}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:linear-gradient(to bottom,#dff0d8 0%,#c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,223,240,0.8470588235294118)', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:linear-gradient(to bottom,#d9edf7 0%,#b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,217,237,0.9686274509803922)', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:linear-gradient(to bottom,#fcf8e3 0%,#f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,252,248,0.8901960784313725)', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:linear-gradient(to bottom,#f2dede 0%,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,242,222,0.8705882352941177)', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.alert-danger,.progress,.progress-bar{background-repeat:repeat-x}.progress{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,235,235,0.9215686274509803)', endColorstr='#fff5f5f5', GradientType=0);background-image:linear-gradient(to bottom,#ebebeb 0%,#f5f5f5 100%)}.progress-bar{background-image:linear-gradient(to bottom,#278f8f 0%,#1c6767 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,39,143,0.5607843137254902)', endColorstr='#ff1c6767', GradientType=0)}.progress-bar-success{background-image:linear-gradient(to bottom,#4caf50 0%,#3d8b40 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,76,175,0.3137254901960784)', endColorstr='#ff3d8b40', GradientType=0)}.progress-bar-info{background-image:linear-gradient(to bottom,#5bc0de 0%,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,91,192,0.8705882352941177)', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:linear-gradient(to bottom,#f0ad4e 0%,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,240,173,0.3058823529411765)', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:linear-gradient(to bottom,#e51c23 0%,#b9151b 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,229,28,0.13725490196078433)', endColorstr='#ffb9151b', GradientType=0)}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:3px;box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #1c6767;background-image:linear-gradient(to bottom,#278f8f 0%,#1f7171 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,39,143,0.5607843137254902)', endColorstr='#ff1f7171', GradientType=0);border-color:#1f7171}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.input-group-addon{cursor:pointer}.indeterminateCheckBox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.indeterminateCheckBox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.indeterminateCheckBox.disabled label,fieldset[disabled] .indeterminateCheckBox label{cursor:not-allowed}.indeterminateCheckBox input[type=checkbox]{position:absolute;margin-left:-20px;margin-top:4px \9}.panel{box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:linear-gradient(to bottom,#f5f5f5 0%,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,245,245,0.9607843137254902)', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.panel-heading{background-image:linear-gradient(to bottom,#278f8f 0%,#227b7b 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,39,143,0.5607843137254902)', endColorstr='#ff227b7b', GradientType=0)}.panel-success>.panel-heading{background-image:linear-gradient(to bottom,#dff0d8 0%,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,223,240,0.8470588235294118)', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.panel-heading{background-image:linear-gradient(to bottom,#d9edf7 0%,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,217,237,0.9686274509803922)', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.panel-heading{background-image:linear-gradient(to bottom,#fcf8e3 0%,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,252,248,0.8901960784313725)', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.panel-heading{background-image:linear-gradient(to bottom,#f2dede 0%,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,242,222,0.8705882352941177)', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:linear-gradient(to bottom,#e8e8e8 0%,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,232,232,0.9098039215686274)', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}.pl-text-horizontal-Left{text-align:left}.pl-text-horizontal-Right{text-align:right}.pl-text-horizontal-Center{text-align:center}.pl-text-horizontal-Justify{text-align:justify}.pl-horizontal-Left{float:left}.pl-horizontal-Right{float:right}.pl-horizontal-Center{text-align:center}.pl-transparent-bg{background-color:transparent}.pl-white-bg{background-color:#fff}.pl-black-bg{background-color:#000}.pl-primary1-bg{background-color:#278f8f}.pl-primary2-bg{background-color:#77c7c7}.pl-primary3-bg{background-color:#0d5d5d}.pl-accent1-bg{background-color:#ef8f40}.pl-accent2-bg{background-color:#f7c194}.pl-accent3-bg{background-color:#9b5215}.pl-background1-bg{background-color:#fff}.pl-background2-bg{background-color:#fafafa}.pl-background3-bg{background-color:#f5f5f5}.pl-background4-bg{background-color:#e0e0e0}.pl-accent-success-bg{background-color:#4caf50}.pl-accent-danger-bg{background-color:#e51c23}.pl-white-fg{color:#fff}.pl-black-fg{color:#000}.pl-primary1-fg{color:#278f8f}.pl-primary2-fg{color:#77c7c7}.pl-primary3-fg{color:#0d5d5d}.pl-accent1-fg{color:#ef8f40}.pl-accent2-fg{color:#f7c194}.pl-accent3-fg{color:#9b5215}.pl-background1-fg{color:#fff}.pl-background2-fg{color:#fafafa}.pl-background3-fg{color:#f5f5f5}.pl-background4-fg{color:#e0e0e0}.pl-accent-success-fg{color:#4caf50}.pl-accent-danger-fg{color:#e51c23}.pl-primary1-fg .form-control{border-color:#278f8f}.pl-primary2-fg .form-control{border-color:#77c7c7}.pl-primary3-fg .form-control{border-color:#0d5d5d}.pl-accent1-fg .form-control{border-color:#ef8f40}.pl-accent2-fg .form-control{border-color:#f7c194}.pl-accent3-fg .form-control{border-color:#9b5215}.pl-accent-success-fg .form-control{border-color:#4caf50}.pl-accent-danger-fg .form-control{border-color:#e51c23}.pl-primary1-bg .form-control{background-color:#278f8f}.pl-combobox-items>span:hover,.pl-primary2-bg .form-control{background-color:#77c7c7}.pl-primary3-bg .form-control{background-color:#0d5d5d}.pl-accent1-bg .form-control{background-color:#ef8f40}.pl-accent2-bg .form-control{background-color:#f7c194}.pl-accent3-bg .form-control{background-color:#9b5215}.pl-accent-success-bg .form-control{background-color:#4caf50}.pl-accent-danger-bg .form-control{background-color:#e51c23}.pl-display4{font:lighter 112px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-display3{font:56px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-display2{font:45px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-display1{font:34px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-headline{font:24px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-title{font:20px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-subhead{font:16px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-body2{font:700 14px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-body1{font:14px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-caption{font:12px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-menu{font:13px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-button{font:14px "Helvetica Neue",Helvetica,Arial,sans-serif}body,html{height:100%}#page-content{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:start;justify-content:flex-start;-ms-flex-line-pack:stretch;align-content:stretch;-ms-flex-align:stretch;align-items:stretch}#menu-arena,#page-bottom,#page-content,#page-top{-ms-flex-order:0;order:0;-webkit-box-flex:0;-ms-flex-item-align:auto;align-self:auto}#menu-arena,#page-top{height:50px;-ms-flex:0 1 50px;flex:0 1 50px}#page-bottom,#page-content{-ms-flex:1 100 auto;flex:1 100 auto}.page-content-overflow-hidden{overflow:hidden}#page-bottom{-ms-flex:0 1 50px;flex:0 1 50px;height:50px}.pl-clearfix:before{content:" ";display:table}.pl-clearfix:after{content:"";display:table;clear:both}.modal.modal-scrollable{overflow-x:hidden;overflow-y:hidden}.blockPage{border-width:0!important;background-color:rgba(0,0,0,0)!important}.blockOverlay{background-color:#fff!important}.blockUI{position:fixed;padding:0;margin:-50px 0 0 -50px;width:100px;top:50%;left:50%;text-align:center;color:#000;cursor:default;opacity:.8}.blockUI #loaderIndicator{width:100px;height:100px}.cssload-spin-box{position:absolute;margin:auto;left:0;top:0;bottom:0;right:0;width:15px;height:15px;border-radius:100%;box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;-o-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;-ms-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;-webkit-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;-moz-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;animation:cssload-spin ease infinite 4.6s;-o-animation:cssload-spin ease infinite 4.6s;-ms-animation:cssload-spin ease infinite 4.6s;-webkit-animation:cssload-spin ease infinite 4.6s;-moz-animation:cssload-spin ease infinite 4.6s}@keyframes cssload-spin{0%,to{box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf}25%{box-shadow:-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf,15px 15px #4f4d49}50%{box-shadow:-15px -15px #4f4d49,15px -15px #dfdfdf,15px 15px #4f4d49,-15px 15px #dfdfdf}75%{box-shadow:15px -15px #dfdfdf,15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49}}.modal.messagebox{top:25%;z-index:1060}.modal.messagebox+.modal-backdrop{z-index:1055}.pl-messagebox-content__icon_error{color:#e51c23}.pl-messagebox-content__icon_warning{color:#f0ad4e}.pl-messagebox-content__icon_default{color:#5bc0de}.pl-dropdown-container{z-index:2000;position:absolute}.pl-dropdown-container .pl-dropdown-content{z-index:2001}.toggle-off .togglebutton-box{border:1px solid #e0e0e0}.toggle-off .togglebutton-container{margin-left:-50px}.togglebutton-box{display:inline-block;width:66px;border:1px solid #278f8f;transition:border .5s;border-radius:3px;overflow:hidden}.togglebutton-container{display:inline-block;white-space:nowrap;transition:margin-left .5s}.togglebutton-container .togglebutton-handle-label,.togglebutton-container .togglebutton-handle-off,.togglebutton-container .togglebutton-handle-on{cursor:pointer;display:inline-block;text-align:center}.togglebutton-container .togglebutton-handle-off,.togglebutton-container .togglebutton-handle-on{width:50px;padding:6px 10px}.togglebutton-container .togglebutton-handle-label{width:6px}.togglebutton-handle-on{color:#fff;background:#278f8f}.togglebutton-handle-off{background:#e0e0e0}.pl-datepicker-footer,.pl-datetimepicker-footer{width:100%;border-top:1px solid #e6e6e6}.pl-datepicker-footer .btn{width:50%}.pl-datepicker-footer .btn:last-child{position:relative;left:1px}.pl-datetimepicker-footer .btn{width:100%}.backdrop{position:fixed;top:0;right:0;bottom:0;left:0}.pl-datepicker-dropdown .btn{border-color:transparent}.pl-datepicker-dropdown,.pl-timepicker-dropdown{position:absolute}.datepicker-date,.datepicker-datetime,.datepicker-time{background:#fff;position:relative;border:1px solid #ccc;border-radius:3px}.datepicker-date a.time,.datepicker-time a.days{display:none}.toggle-date,.toggle-time{text-align:center;width:100%;display:inline-block}.datepicker-clear{position:relative}.navigation .year,.navigation .years,.weekdays-calendar{cursor:pointer}.weekdays{color:#000}.days{width:100%;text-align:center}.day-inactive{opacity:.5}.day-unavailable,.month-unavailable,.year-unavailable{background-color:#e0e0e0;cursor:not-allowed;color:#777;opacity:.3}.day{padding:5px;text-align:center;vertical-align:middle}.day-today{background:#f5f5f5}.day-weekend{color:red}.day-selected{background:#77c7c7;color:#fff}.navigation{cursor:default}.navigation-next{text-align:right}.navigation-prev{text-align:left}.month,.timepicker-seconds .second{padding:10px}.month-today{background:#d4e2ee}.month-list{cursor:pointer}.month-selected{border:1px solid red}.times td,.year,.years{text-align:center}.year{padding:5px;color:#000}.year-list{cursor:pointer}.year-begin,.year-end{opacity:.5}.year-selected{border:1px solid red}.year-today{background:#d4e2ee}.timepicker-seconds{cursor:pointer}.timepicker-seconds .second-unavailable{background-color:#ddd;cursor:not-allowed;color:#777;opacity:1}.timepicker-seconds .second-selected{border:1px solid red}.pl-file-box .input-group{display:block}.pl-file-box .input-group .form-control{display:block;width:calc(100% - 40px)}.pl-file-box .input-group-btn,.pl-popup-button__items>li>a{width:100%}.pl-file-box .input-group-btn .btn{width:40px}.pl-file-box .pl-filebox-file-download-url,.pl-file-box .pl-filebox-file-empty,.pl-file-box .pl-filebox-file-upload{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.pl-file-box .pl-filebox-file-empty,.pl-file-box .pl-filebox-file-upload{color:#777}.pl-file-box .pl-filebox-file-download-url{width:100%;display:block}.pl-stack-panel{list-style:none;margin:0;padding:0}.pl-stack-panel .pl-stack-panel-i{max-width:100%}.pl-stack-panel.pl-form-group>.pl-stack-panel-i{margin-bottom:5px}.pl-stack-panel.horizontal-orientation>.pl-stack-panel-i,.pl-stack-panel.pl-stack-panel_horizontal .pl-stack-panel__content{float:left}.pl-stack-panel.horizontal-orientation:after{content:'';clear:both;display:block}.pl-stack-panel.horizontal-orientation.pl-form-group>.pl-stack-panel-i{display:inline-block;float:none}.pl-scrollpanel{position:relative}.pl-scrollpanel-body{white-space:nowrap}.pl-scrollpanel-i{display:block}.pl-horizontal-scroll-visible{overflow-x:scroll}.pl-horizontal-scroll-hidden{overflow-x:hidden}.pl-horizontal-scroll-auto{overflow-x:auto}.pl-vertical-scroll-visible{overflow-y:scroll}.pl-vertical-scroll-hidden{overflow-y:hidden}.pl-vertical-scroll-auto{overflow-y:auto}.pl-listbox .pl-listbox-i:focus{z-index:1}.pl-listbox-i[tabindex]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.pl-listbox-common-mode>.pl-listbox-control>.pl-listbox-i>.pl-listbox-input{position:absolute;visibility:hidden}.pl-listbox-common-mode>.pl-listbox-control>.pl-listbox-i-chosen{box-shadow:inset 4px 0 #278f8f}.pl-listbox .checkbox label,.pl-listbox .radio label{padding-left:0}.pl-listbox.pl-disabled .radio{color:#ccc;cursor:not-allowed}.pl-treeview-node__button{display:inline-block;font:14px/1 FontAwesome;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pl-treeview-node__button_expand:before{content:"\f196"}.pl-treeview-node__button_collapse:before{content:"\f147"}.pl-treeview-node__item{display:inline-block}.pl-treeview-node__items{margin-left:20px}.pl-treeview-node__items_expanded{display:block}.pl-treeview-node__items_collapsed{display:none}.pl-treeview-item__checker{display:inline-block;font:14px/1 FontAwesome;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pl-treeview-item__checker_checkbox:before{content:"\f096"}.pl-treeview-item__checker_checkbox.pl-treeview-item__checker_checked:before{content:"\f14a"}.pl-treeview-item__checker_radio,.pl-treeview-item__checker_radio.pl-treeview-item__checker_checked{display:none}.pl-treeview-item__content{display:inline-block;cursor:pointer}.pl-treeview-item__content_selected{color:#fff;background-color:#278f8f;border-color:#278f8f}.pl-popup-button__dropdown{position:absolute;top:0;left:0;z-index:1000}.pl-popup-button__item:after{content:"";clear:both;display:table}.pl-text-trimming{white-space:nowrap!important;overflow:hidden;text-overflow:ellipsis;display:block;width:100%}.pl-text-wrapping{white-space:pre-wrap;word-wrap:break-word}.pl-button-edit-group__control[readonly]{background-color:#fff;background-image:none}.pl-button-edit-group__control[disabled]{background-color:#eee;opacity:1}.pl-button-edit-button_disabled{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);box-shadow:none}.pl-combobox-items .pl-disabled,.pl-datagrid-row.pl-disabled,.pl-disabled-list-item{opacity:.5}.pl-label-floating.pl-empty-text-editor:not(.pl-focused) label{color:#757575}.pl-label-floating label{font-weight:400}.pl-label-floating{position:relative;padding-top:16px}.pl-label-floating .pl-control-label{z-index:3;position:absolute}.pl-label-floating.pl-focused label,.pl-label-floating:not(.pl-empty-text-editor) label{font-size:13px}.pl-label-floating.pl-empty-text-editor .pl-control-label{transition:all .5s ease;will-change:left,top,contents;pointer-events:none}.pl-label-floating.pl-empty-text-editor:not(.pl-focused) .pl-control-label{top:26px;left:6px}.pl-label-floating.pl-empty-text-editor.pl-focused .pl-control-label,.pl-label-floating:not(.pl-empty-text-editor) .pl-control-label{top:0;left:0}.pl-numericbox.pl-label-floating.pl-empty-text-editor:not(.pl-focused) .pl-control-label{left:44px}.pl-control.has-error{color:#a94442;border-color:#a94442;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.pl-control.has-error:focus{border-color:#843534;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.pl-combobox .pl-active{border:1px solid #c94a4a}.pl-combobox.pl-focused>.input-group>.pl-control{border-color:#66afe9;outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.pl-combobox-filter-text:focus{border:1px solid #ddd;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.pl-combobox.pl-disabled .pl-control{background:#eee;cursor:not-allowed}.pl-combobox.pl-disabled .pl-combobox__clear,.pl-combobox.pl-disabled .pl-combobox__grip{cursor:not-allowed}.pl-combobox-items{overflow-y:auto;max-height:30vh;cursor:pointer;text-indent:5px}.pl-combobox-items>.pl-combobox-selected{background-color:#e0e0e0}.pl-combobox-items>.pl-combobox-checked{background:#f5f5f5}.pl-combobox-dropdown{position:relative;background:#fff;border-left:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc;padding:5px;margin-top:1px}.pl-combobox-dropdown.dropdown-direction-down{border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-bottom:1px solid #ccc}.pl-combobox-dropdown.dropdown-direction-up{border-top-left-radius:4px;border-top-right-radius:4px;border-top:1px solid #ccc}.pl-combobox__value{position:absolute;left:12px;right:0;overflow:hidden}.pl-combobox__value>.pl-label{max-width:100%}.pl-textbox .pl-control-editor textarea.pl-control-editor,.pl-textbox textarea.pl-control{resize:none}.pl-numeric-box-input{-moz-appearance:textfield}.pl-numeric-box-input::-webkit-inner-spin-button,.pl-numeric-box-input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.pl-tabpanel .pl-tabpage-i:before{content:" ";display:table}.pl-tabpanel .pl-tabpage-i:after{content:"";display:table;clear:both}.pl-panel .pl-panel-header{cursor:default}.pl-panel .pl-panel-header.pl-collapsed+.pl-panel-body{display:none}.pl-datagrid .sortable,.pl-panel .pl-panel-header.pl-collapsible{cursor:pointer}.pl-panel .pl-panel-i:before{content:" ";display:table}.pl-panel .pl-panel-i:after{content:"";display:table;clear:both}.pl-datagrid .sorted{position:relative;padding-right:18px}.pl-datagrid .headerTemplate-sorted-asc:after,.pl-datagrid .headerTemplate-sorted-desc:after{position:absolute;right:5px;top:calc(50% - 10px);display:inline-block;font-family:FontAwesome}.pl-datagrid .headerTemplate-sorted-asc:after{content:"\f0d8"}.pl-datagrid .headerTemplate-sorted-desc:after{content:"\f0d7"}.pl-datagrid .sorted-asc span:after,.pl-datagrid .sorted-desc span:after{display:inline-block;font-family:FontAwesome;margin-left:5px}.pl-datagrid .sorted-asc span:after{content:"\f0d8"}.pl-datagrid .sorted-desc span:after{content:"\f0d7"}.pl-datagrid.verticalAlignmentStretch .pl-datagrid-table,.pl-datagrid_layout_fixed .pl-datagrid-table{table-layout:fixed}.pl-datagrid_select_single .pl-datagrid-toggle_all{display:none}.pl-datagrid_selectors_show .pl-datagrid-row__cell_checker,.pl-datagrid_selectors_show .pl-datagrid-row__cell_toggle{width:40px;display:table-cell}.pl-datagrid_selectors_hide .pl-datagrid-row__cell_checker,.pl-datagrid_selectors_hide .pl-datagrid-row__cell_toggle{width:0;display:none}.pl-datagrid.verticalAlignmentTop table>tbody>tr>td{vertical-align:top}.pl-datagrid.verticalAlignmentCenter table>tbody>tr>td{vertical-align:middle}.pl-datagrid.verticalAlignmentBottom table>tbody>tr>td{vertical-align:bottom}.pl-datagrid.verticalAlignmentStretch table>tbody>tr>td{vertical-align:middle}.pl-datagrid.verticalAlignmentStretch{overflow-x:hidden}.pl-datagrid.verticalAlignmentStretch .pl-datagrid__body{overflow-y:scroll;overflow-x:auto}.pl-datagrid-table{margin-bottom:0}.pl-datagrid-table_body{border-top:0!important}.pl-datagrid-container_head{overflow-x:hidden}.pl-datagrid-row__cell{overflow:hidden}.pl-datagrid-row__cell_width{padding:0!important;border:0!important}.pl-imagebox .pl-image{position:relative;width:150px;height:150px;overflow:hidden}.pl-imagebox .pl-image img{left:50%;top:50%;position:relative;transform:translateX(-50%) translateY(-50%)}.pl-imagebox .pl-image-file{text-align:center}.pl-imagebox .pl-image-file .pl-image-file-upload-button{cursor:pointer}.pl-imagebox .pl-image-file-input{width:.1px;height:.1px;opacity:0;overflow:hidden;position:absolute;z-index:-1}.pl-imagebox .pl-image-remove{position:absolute;top:0;right:0;cursor:pointer}.pl-imagebox .pl-image-remove:after{color:#e51c23;content:"\2716"}.pl-imagebox.pl-disabled .pl-image-file,.pl-imagebox.pl-disabled .pl-image-remove,.pl-imagebox.pl-empty .pl-image,.pl-imagebox.pl-empty .pl-image-remove{display:none}.pl-view:before{content:" ";display:table}.pl-view:after{content:"";display:table;clear:both}.pl-data-navigation:before{content:" ";display:table}.pl-data-navigation:after{content:"";display:table;clear:both}.pl-data-navigation .pl-data-navigation-size{float:right;margin:20px 0}.pl-divider{margin-top:5px;margin-bottom:5px}.pl-divider.pl-primary1-bg{border-color:#278f8f}.pl-divider.pl-primary2-bg{border-color:#77c7c7}.pl-divider.pl-primary3-bg{border-color:#0d5d5d}.pl-divider.pl-accent1-bg{border-color:#ef8f40}.pl-divider.pl-accent2-bg{border-color:#f7c194}.pl-divider.pl-accent3-bg{border-color:#9b5215}.pl-divider.pl-background1-bg{border-color:#fff}.pl-divider.pl-background2-bg{border-color:#fafafa}.pl-divider.pl-background3-bg{border-color:#f5f5f5}.pl-divider.pl-background4-bg{border-color:#e0e0e0} \ No newline at end of file +.form-control{box-shadow:none}.btn:focus,.btn:hover{border-color:transparent}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{background-repeat:repeat-x}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary:focus,.btn-primary:hover{background-color:#1a5f5f;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#1a5f5f;border-color:#185757}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#1a5f5f;background-image:none}.btn-success:focus,.btn-success:hover{background-color:#39843c;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#39843c;border-color:#367d39}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#39843c;background-image:none}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger:focus,.btn-danger:hover{background-color:#b0141a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#b0141a;border-color:#a71318}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#b0141a;background-image:none}.img-thumbnail,.thumbnail{box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a{width:100%}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#227b7b}.navbar-default{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border-radius:3px;box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border-radius:3px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:linear-gradient(to bottom,#278f8f 0%,#227b7b 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,39,143,0.5607843137254902)', endColorstr='#ff227b7b', GradientType=0)}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:linear-gradient(to bottom,#dff0d8 0%,#c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,223,240,0.8470588235294118)', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:linear-gradient(to bottom,#d9edf7 0%,#b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,217,237,0.9686274509803922)', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:linear-gradient(to bottom,#fcf8e3 0%,#f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,252,248,0.8901960784313725)', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:linear-gradient(to bottom,#f2dede 0%,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,242,222,0.8705882352941177)', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.alert-danger,.progress,.progress-bar{background-repeat:repeat-x}.progress{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,235,235,0.9215686274509803)', endColorstr='#fff5f5f5', GradientType=0);background-image:linear-gradient(to bottom,#ebebeb 0%,#f5f5f5 100%)}.progress-bar{background-image:linear-gradient(to bottom,#278f8f 0%,#1c6767 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,39,143,0.5607843137254902)', endColorstr='#ff1c6767', GradientType=0)}.progress-bar-success{background-image:linear-gradient(to bottom,#4caf50 0%,#3d8b40 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,76,175,0.3137254901960784)', endColorstr='#ff3d8b40', GradientType=0)}.progress-bar-info{background-image:linear-gradient(to bottom,#5bc0de 0%,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,91,192,0.8705882352941177)', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:linear-gradient(to bottom,#f0ad4e 0%,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,240,173,0.3058823529411765)', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:linear-gradient(to bottom,#e51c23 0%,#b9151b 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,229,28,0.13725490196078433)', endColorstr='#ffb9151b', GradientType=0)}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:3px;box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #1c6767;background-image:linear-gradient(to bottom,#278f8f 0%,#1f7171 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,39,143,0.5607843137254902)', endColorstr='#ff1f7171', GradientType=0);border-color:#1f7171}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.input-group-addon{cursor:pointer}.indeterminateCheckBox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.indeterminateCheckBox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.indeterminateCheckBox.disabled label,fieldset[disabled] .indeterminateCheckBox label{cursor:not-allowed}.indeterminateCheckBox input[type=checkbox]{position:absolute;margin-left:-20px;margin-top:4px \9}.panel{box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:linear-gradient(to bottom,#f5f5f5 0%,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,245,245,0.9607843137254902)', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.panel-heading{background-image:linear-gradient(to bottom,#278f8f 0%,#227b7b 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,39,143,0.5607843137254902)', endColorstr='#ff227b7b', GradientType=0)}.panel-success>.panel-heading{background-image:linear-gradient(to bottom,#dff0d8 0%,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,223,240,0.8470588235294118)', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.panel-heading{background-image:linear-gradient(to bottom,#d9edf7 0%,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,217,237,0.9686274509803922)', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.panel-heading{background-image:linear-gradient(to bottom,#fcf8e3 0%,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,252,248,0.8901960784313725)', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.panel-heading{background-image:linear-gradient(to bottom,#f2dede 0%,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,242,222,0.8705882352941177)', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:linear-gradient(to bottom,#e8e8e8 0%,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255,232,232,0.9098039215686274)', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}.pl-text-horizontal-Left{text-align:left}.pl-text-horizontal-Right{text-align:right}.pl-text-horizontal-Center{text-align:center}.pl-text-horizontal-Justify{text-align:justify}.pl-horizontal-Left{float:left}.pl-horizontal-Right{float:right}.pl-horizontal-Center{text-align:center}.pl-transparent-bg{background-color:transparent}.pl-white-bg{background-color:#fff}.pl-black-bg{background-color:#000}.pl-primary1-bg{background-color:#278f8f}.pl-primary2-bg{background-color:#77c7c7}.pl-primary3-bg{background-color:#0d5d5d}.pl-accent1-bg{background-color:#ef8f40}.pl-accent2-bg{background-color:#f7c194}.pl-accent3-bg{background-color:#9b5215}.pl-background1-bg{background-color:#fff}.pl-background2-bg{background-color:#fafafa}.pl-background3-bg{background-color:#f5f5f5}.pl-background4-bg{background-color:#e0e0e0}.pl-accent-success-bg{background-color:#4caf50}.pl-accent-danger-bg{background-color:#e51c23}.pl-white-fg{color:#fff}.pl-black-fg{color:#000}.pl-primary1-fg,.pl-tabpanel .pl-tabheader.pl-disabled a:hover{color:#278f8f}.pl-primary2-fg{color:#77c7c7}.pl-primary3-fg{color:#0d5d5d}.pl-accent1-fg{color:#ef8f40}.pl-accent2-fg{color:#f7c194}.pl-accent3-fg{color:#9b5215}.pl-background1-fg{color:#fff}.pl-background2-fg{color:#fafafa}.pl-background3-fg{color:#f5f5f5}.pl-background4-fg{color:#e0e0e0}.pl-accent-success-fg{color:#4caf50}.pl-accent-danger-fg{color:#e51c23}.pl-primary1-fg .form-control{border-color:#278f8f}.pl-primary2-fg .form-control{border-color:#77c7c7}.pl-primary3-fg .form-control{border-color:#0d5d5d}.pl-accent1-fg .form-control{border-color:#ef8f40}.pl-accent2-fg .form-control{border-color:#f7c194}.pl-accent3-fg .form-control{border-color:#9b5215}.pl-accent-success-fg .form-control{border-color:#4caf50}.pl-accent-danger-fg .form-control{border-color:#e51c23}.pl-primary1-bg .form-control{background-color:#278f8f}.pl-combobox-items>span:hover,.pl-primary2-bg .form-control{background-color:#77c7c7}.pl-primary3-bg .form-control{background-color:#0d5d5d}.pl-accent1-bg .form-control{background-color:#ef8f40}.pl-accent2-bg .form-control{background-color:#f7c194}.pl-accent3-bg .form-control{background-color:#9b5215}.pl-accent-success-bg .form-control{background-color:#4caf50}.pl-accent-danger-bg .form-control{background-color:#e51c23}.pl-display4{font:lighter 112px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-display3{font:56px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-display2{font:45px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-display1{font:34px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-headline{font:24px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-title{font:20px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-subhead{font:16px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-body2{font:700 14px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-body1{font:14px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-caption{font:12px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-menu{font:13px "Helvetica Neue",Helvetica,Arial,sans-serif}.pl-button{font:14px "Helvetica Neue",Helvetica,Arial,sans-serif}body,html{height:100%}#page-content{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:start;justify-content:flex-start;-ms-flex-line-pack:stretch;align-content:stretch;-ms-flex-align:stretch;align-items:stretch}#menu-arena,#page-bottom,#page-content,#page-top{-ms-flex-order:0;order:0;-webkit-box-flex:0;-ms-flex-item-align:auto;-ms-grid-row-align:auto;align-self:auto}#menu-arena,#page-top{height:50px;-ms-flex:0 1 50px;flex:0 1 50px}#page-bottom,#page-content{-ms-flex:1 100 auto;flex:1 100 auto}.page-content-overflow-hidden{overflow:hidden}#page-bottom{-ms-flex:0 1 50px;flex:0 1 50px;height:50px}.pl-clearfix:before{content:" ";display:table}.pl-clearfix:after{content:"";display:table;clear:both}.modal.modal-scrollable{overflow-x:hidden;overflow-y:hidden}.blockPage{border-width:0!important;background-color:rgba(0,0,0,0)!important}.blockOverlay{background-color:#fff!important}.blockUI{position:fixed;padding:0;margin:-50px 0 0 -50px;width:100px;top:50%;left:50%;text-align:center;color:#000;cursor:default;opacity:.8}.blockUI #loaderIndicator{width:100px;height:100px}.cssload-spin-box{position:absolute;margin:auto;left:0;top:0;bottom:0;right:0;width:15px;height:15px;border-radius:100%;box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;-o-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;-ms-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;-webkit-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;-moz-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;animation:cssload-spin ease infinite 4.6s;-o-animation:cssload-spin ease infinite 4.6s;-ms-animation:cssload-spin ease infinite 4.6s;-webkit-animation:cssload-spin ease infinite 4.6s;-moz-animation:cssload-spin ease infinite 4.6s}@keyframes cssload-spin{0%,to{box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf}25%{box-shadow:-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf,15px 15px #4f4d49}50%{box-shadow:-15px -15px #4f4d49,15px -15px #dfdfdf,15px 15px #4f4d49,-15px 15px #dfdfdf}75%{box-shadow:15px -15px #dfdfdf,15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49}}.modal.messagebox{top:25%;z-index:1060}.modal.messagebox+.modal-backdrop{z-index:1055}.pl-messagebox-content__icon_error{color:#e51c23}.pl-messagebox-content__icon_warning{color:#f0ad4e}.pl-messagebox-content__icon_default{color:#5bc0de}.pl-dropdown-container{z-index:2000;position:absolute}.pl-dropdown-container .pl-dropdown-content{z-index:2001}.toggle-off .togglebutton-box{border:1px solid #e0e0e0}.toggle-off .togglebutton-container{margin-left:-50px}.togglebutton-box{display:inline-block;width:66px;border:1px solid #278f8f;transition:border .5s;border-radius:3px;overflow:hidden}.togglebutton-container{display:inline-block;white-space:nowrap;transition:margin-left .5s}.togglebutton-container .togglebutton-handle-label,.togglebutton-container .togglebutton-handle-off,.togglebutton-container .togglebutton-handle-on{cursor:pointer;display:inline-block;text-align:center}.togglebutton-container .togglebutton-handle-off,.togglebutton-container .togglebutton-handle-on{width:50px;padding:6px 10px}.togglebutton-container .togglebutton-handle-label{width:6px}.togglebutton-handle-on{color:#fff;background:#278f8f}.togglebutton-handle-off{background:#e0e0e0}.pl-datepicker-footer,.pl-datetimepicker-footer{width:100%;border-top:1px solid #e6e6e6}.pl-datepicker-footer .btn{width:50%}.pl-datepicker-footer .btn:last-child{position:relative;left:1px}.pl-datetimepicker-footer .btn{width:100%}.backdrop{position:fixed;top:0;right:0;bottom:0;left:0}.pl-datepicker-dropdown .btn{border-color:transparent}.pl-datepicker-dropdown,.pl-timepicker-dropdown{position:absolute}.datepicker-date,.datepicker-datetime,.datepicker-time{background:#fff;position:relative;border:1px solid #ccc;border-radius:3px}.datepicker-date a.time,.datepicker-time a.days{display:none}.toggle-date,.toggle-time{text-align:center;width:100%;display:inline-block}.datepicker-clear{position:relative}.navigation .year,.navigation .years,.weekdays-calendar{cursor:pointer}.weekdays{color:#000}.days{width:100%;text-align:center}.day-inactive{opacity:.5}.day-unavailable,.month-unavailable,.year-unavailable{background-color:#e0e0e0;cursor:not-allowed;color:#777;opacity:.3}.day{padding:5px;text-align:center;vertical-align:middle}.day-today{background:#f5f5f5}.day-weekend{color:red}.day-selected{background:#77c7c7;color:#fff}.navigation{cursor:default}.navigation-next{text-align:right}.navigation-prev{text-align:left}.month,.timepicker-seconds .second{padding:10px}.month-today{background:#d4e2ee}.month-list{cursor:pointer}.month-selected{border:1px solid red}.times td,.year,.years{text-align:center}.year{padding:5px;color:#000}.year-list{cursor:pointer}.year-begin,.year-end{opacity:.5}.year-selected{border:1px solid red}.year-today{background:#d4e2ee}.timepicker-seconds{cursor:pointer}.timepicker-seconds .second-unavailable{background-color:#ddd;cursor:not-allowed;color:#777;opacity:1}.timepicker-seconds .second-selected{border:1px solid red}.pl-file-box .input-group{display:block}.pl-file-box .input-group .form-control{display:block;width:calc(100% - 40px)}.pl-file-box .input-group-btn,.pl-popup-button__items>li>a{width:100%}.pl-file-box .input-group-btn .btn{width:40px}.pl-file-box .pl-filebox-file-download-url,.pl-file-box .pl-filebox-file-empty,.pl-file-box .pl-filebox-file-upload{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.pl-file-box .pl-filebox-file-empty,.pl-file-box .pl-filebox-file-upload{color:#777}.pl-file-box .pl-filebox-file-download-url{width:100%;display:block}.pl-stack-panel{list-style:none;margin:0;padding:0}.pl-stack-panel .pl-stack-panel-i{max-width:100%}.pl-stack-panel.pl-form-group>.pl-stack-panel-i{margin-bottom:5px}.pl-stack-panel.horizontal-orientation>.pl-stack-panel-i,.pl-stack-panel.pl-stack-panel_horizontal .pl-stack-panel__content{float:left}.pl-stack-panel.horizontal-orientation:after{content:'';clear:both;display:block}.pl-stack-panel.horizontal-orientation.pl-form-group>.pl-stack-panel-i{display:inline-block;float:none}.pl-scrollpanel{position:relative}.pl-scrollpanel-body{white-space:nowrap}.pl-scrollpanel-i{display:block}.pl-horizontal-scroll-visible{overflow-x:scroll}.pl-horizontal-scroll-hidden{overflow-x:hidden}.pl-horizontal-scroll-auto{overflow-x:auto}.pl-vertical-scroll-visible{overflow-y:scroll}.pl-vertical-scroll-hidden{overflow-y:hidden}.pl-vertical-scroll-auto{overflow-y:auto}.pl-listbox .pl-listbox-i:focus{z-index:1}.pl-listbox-i[tabindex]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.pl-listbox-common-mode>.pl-listbox-control>.pl-listbox-i>.pl-listbox-input{position:absolute;visibility:hidden}.pl-listbox-common-mode>.pl-listbox-control>.pl-listbox-i-chosen{box-shadow:inset 4px 0 #278f8f}.pl-listbox .checkbox label,.pl-listbox .radio label{padding-left:0}.pl-listbox.pl-disabled .radio{color:#ccc;cursor:not-allowed}.pl-treeview-node__button{display:inline-block;font:14px/1 FontAwesome;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pl-treeview-node__button_expand:before{content:"\f196"}.pl-treeview-node__button_collapse:before{content:"\f147"}.pl-treeview-node__item{display:inline-block}.pl-treeview-node__items{margin-left:20px}.pl-treeview-node__items_expanded{display:block}.pl-treeview-node__items_collapsed{display:none}.pl-treeview-item__checker{display:inline-block;font:14px/1 FontAwesome;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pl-treeview-item__checker_checkbox:before{content:"\f096"}.pl-treeview-item__checker_checkbox.pl-treeview-item__checker_checked:before{content:"\f14a"}.pl-treeview-item__checker_radio,.pl-treeview-item__checker_radio.pl-treeview-item__checker_checked{display:none}.pl-treeview-item__content{display:inline-block;cursor:pointer}.pl-treeview-item__content_selected{color:#fff;background-color:#278f8f;border-color:#278f8f}.pl-popup-button__dropdown{position:absolute;top:0;left:0;z-index:1000}.pl-popup-button__item:after{content:"";clear:both;display:table}.pl-text-trimming{white-space:nowrap!important;overflow:hidden;text-overflow:ellipsis;display:block;width:100%}.pl-text-wrapping{white-space:pre-wrap;word-wrap:break-word}.pl-button-edit-group__control[readonly]{background-color:#fff;background-image:none}.pl-button-edit-group__control[disabled]{background-color:#eee;opacity:1}.pl-button-edit-button_disabled{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);box-shadow:none}.pl-combobox-items .pl-disabled,.pl-datagrid-row.pl-disabled,.pl-disabled-list-item{opacity:.5}.pl-label-floating.pl-empty-text-editor:not(.pl-focused) label{color:#757575}.pl-label-floating label{font-weight:400}.pl-label-floating{position:relative;padding-top:16px}.pl-label-floating .pl-control-label{z-index:3;position:absolute}.pl-label-floating.pl-focused label,.pl-label-floating:not(.pl-empty-text-editor) label{font-size:13px}.pl-label-floating.pl-empty-text-editor .pl-control-label{transition:all .5s ease;will-change:left,top,contents;pointer-events:none}.pl-label-floating.pl-empty-text-editor:not(.pl-focused) .pl-control-label{top:26px;left:6px}.pl-label-floating.pl-empty-text-editor.pl-focused .pl-control-label,.pl-label-floating:not(.pl-empty-text-editor) .pl-control-label{top:0;left:0}.pl-numericbox.pl-label-floating.pl-empty-text-editor:not(.pl-focused) .pl-control-label{left:44px}.pl-control.has-error{color:#a94442;border-color:#a94442;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.pl-control.has-error:focus{border-color:#843534;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.pl-combobox .pl-active{border:1px solid #c94a4a}.pl-combobox.pl-focused>.input-group>.pl-control{border-color:#66afe9;outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.pl-combobox-filter-text:focus{border:1px solid #ddd;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.pl-combobox.pl-disabled .pl-control{background:#eee;cursor:not-allowed}.pl-combobox.pl-disabled .pl-combobox__clear,.pl-combobox.pl-disabled .pl-combobox__grip{cursor:not-allowed}.pl-combobox-items{overflow-y:auto;max-height:30vh;cursor:pointer;text-indent:5px}.pl-combobox-items>.pl-combobox-selected{background-color:#e0e0e0}.pl-combobox-items>.pl-combobox-checked{background:#f5f5f5}.pl-combobox-dropdown{position:relative;background:#fff;border-left:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc;padding:5px;margin-top:1px}.pl-combobox-dropdown.dropdown-direction-down{border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-bottom:1px solid #ccc}.pl-combobox-dropdown.dropdown-direction-up{border-top-left-radius:4px;border-top-right-radius:4px;border-top:1px solid #ccc}.pl-combobox__value{position:absolute;left:12px;right:0;overflow:hidden}.pl-combobox__value>.pl-label{max-width:100%}.pl-textbox .pl-control-editor textarea.pl-control-editor,.pl-textbox textarea.pl-control{resize:none}.pl-numeric-box-input{-moz-appearance:textfield}.pl-numeric-box-input::-webkit-inner-spin-button,.pl-numeric-box-input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.pl-tabpanel .pl-tabpage-i:before{content:" ";display:table}.pl-tabpanel .pl-tabpage-i:after{content:"";display:table;clear:both}.pl-tabpanel .pl-tabheader.pl-disabled{background:#eee;cursor:not-allowed}.pl-panel .pl-panel-header{cursor:default}.pl-panel .pl-panel-header.pl-collapsed+.pl-panel-body{display:none}.pl-datagrid .sortable,.pl-panel .pl-panel-header.pl-collapsible{cursor:pointer}.pl-panel .pl-panel-i:before{content:" ";display:table}.pl-panel .pl-panel-i:after{content:"";display:table;clear:both}.pl-datagrid .sorted{position:relative;padding-right:18px}.pl-datagrid .headerTemplate-sorted-asc:after,.pl-datagrid .headerTemplate-sorted-desc:after{position:absolute;right:5px;top:calc(50% - 10px);display:inline-block;font-family:FontAwesome}.pl-datagrid .headerTemplate-sorted-asc:after{content:"\f0d8"}.pl-datagrid .headerTemplate-sorted-desc:after{content:"\f0d7"}.pl-datagrid .sorted-asc span:after,.pl-datagrid .sorted-desc span:after{display:inline-block;font-family:FontAwesome;margin-left:5px}.pl-datagrid .sorted-asc span:after{content:"\f0d8"}.pl-datagrid .sorted-desc span:after{content:"\f0d7"}.pl-datagrid.verticalAlignmentStretch .pl-datagrid-table,.pl-datagrid_layout_fixed .pl-datagrid-table{table-layout:fixed}.pl-datagrid_select_single .pl-datagrid-toggle_all{display:none}.pl-datagrid_selectors_show .pl-datagrid-row__cell_checker,.pl-datagrid_selectors_show .pl-datagrid-row__cell_toggle{width:40px;display:table-cell}.pl-datagrid_selectors_hide .pl-datagrid-row__cell_checker,.pl-datagrid_selectors_hide .pl-datagrid-row__cell_toggle{width:0;display:none}.pl-datagrid.verticalAlignmentTop table>tbody>tr>td{vertical-align:top}.pl-datagrid.verticalAlignmentCenter table>tbody>tr>td{vertical-align:middle}.pl-datagrid.verticalAlignmentBottom table>tbody>tr>td{vertical-align:bottom}.pl-datagrid.verticalAlignmentStretch table>tbody>tr>td{vertical-align:middle}.pl-datagrid.verticalAlignmentStretch{overflow-x:hidden}.pl-datagrid.verticalAlignmentStretch .pl-datagrid__body{overflow-y:scroll;overflow-x:auto}.pl-datagrid-table{margin-bottom:0}.pl-datagrid-table_body{border-top:0!important}.pl-datagrid-container_head{overflow-x:hidden}.pl-datagrid-row__cell{overflow:hidden}.pl-datagrid-row__cell_width{padding:0!important;border:0!important}.pl-imagebox .pl-image{position:relative;width:150px;height:150px}.pl-imagebox .pl-image .pl-image-wrapper{position:relative;width:100%;height:100%;overflow:hidden}.pl-imagebox .pl-image .pl-image-wrapper img{left:50%;top:50%;position:relative;transform:translateX(-50%) translateY(-50%)}.pl-imagebox .pl-image-file{text-align:center}.pl-imagebox .pl-image-file .pl-image-file-upload-button{cursor:pointer}.pl-imagebox .pl-image-file-input{width:.1px;height:.1px;opacity:0;overflow:hidden;position:absolute;z-index:-1}.pl-imagebox .pl-image-remove{position:absolute;top:0;right:0;cursor:pointer}.pl-imagebox .pl-image-remove:after{color:#e51c23;content:"\2716"}.pl-imagebox.pl-disabled .pl-image-file,.pl-imagebox.pl-disabled .pl-image-remove,.pl-imagebox.pl-empty .pl-image,.pl-imagebox.pl-empty .pl-image-remove{display:none}.pl-view:before{content:" ";display:table}.pl-view:after{content:"";display:table;clear:both}.pl-data-navigation:before{content:" ";display:table}.pl-data-navigation:after{content:"";display:table;clear:both}.pl-data-navigation .pl-data-navigation-size{float:right;margin:20px 0}.pl-divider{margin-top:5px;margin-bottom:5px}.pl-divider.pl-primary1-bg{border-color:#278f8f}.pl-divider.pl-primary2-bg{border-color:#77c7c7}.pl-divider.pl-primary3-bg{border-color:#0d5d5d}.pl-divider.pl-accent1-bg{border-color:#ef8f40}.pl-divider.pl-accent2-bg{border-color:#f7c194}.pl-divider.pl-accent3-bg{border-color:#9b5215}.pl-divider.pl-background1-bg{border-color:#fff}.pl-divider.pl-background2-bg{border-color:#fafafa}.pl-divider.pl-background3-bg{border-color:#f5f5f5}.pl-divider.pl-background4-bg{border-color:#e0e0e0} \ No newline at end of file diff --git a/out/css/vendor.css b/out/css/vendor.css index 0af3181..72fe415 100644 --- a/out/css/vendor.css +++ b/out/css/vendor.css @@ -1,6 +1,6 @@ /*! - * Font Awesome 4.6.3 by @davegandy - http://fontawesome.io - @fontawesome + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.6.3');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.6.3') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.6.3') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.6.3') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.6.3') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.6.3#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} .toast-title{font-weight:700}.toast-message{-ms-word-wrap:break-word;word-wrap:break-word}.toast-message a,.toast-message label{color:#FFF}.toast-message a:hover{color:#CCC;text-decoration:none}.toast-close-button{position:relative;right:-.3em;top:-.3em;float:right;font-size:20px;font-weight:700;color:#FFF;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;opacity:.8;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80);line-height:1}.toast-close-button:focus,.toast-close-button:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=40);filter:alpha(opacity=40)}.rtl .toast-close-button{left:-.3em;float:left;right:.3em}button.toast-close-button{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.toast-top-center{top:0;right:0;width:100%}.toast-bottom-center{bottom:0;right:0;width:100%}.toast-top-full-width{top:0;right:0;width:100%}.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}#toast-container{position:fixed;z-index:999999;pointer-events:none}#toast-container *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#toast-container>div{position:relative;pointer-events:auto;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#FFF;opacity:.8;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80)}#toast-container>div.rtl{direction:rtl;padding:15px 50px 15px 15px;background-position:right 15px center}#toast-container>div:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100);cursor:pointer}#toast-container>.toast-info{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=)!important}#toast-container>.toast-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=)!important}#toast-container>.toast-success{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==)!important}#toast-container>.toast-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=)!important}#toast-container.toast-bottom-center>div,#toast-container.toast-top-center>div{width:300px;margin-left:auto;margin-right:auto}#toast-container.toast-bottom-full-width>div,#toast-container.toast-top-full-width>div{width:96%;margin-left:auto;margin-right:auto}.toast{background-color:#030303}.toast-success{background-color:#51A351}.toast-error{background-color:#BD362F}.toast-info{background-color:#2F96B4}.toast-warning{background-color:#F89406}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=40);filter:alpha(opacity=40)}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:11em}#toast-container>div.rtl{padding:8px 50px 8px 8px}#toast-container .toast-close-button{right:-.2em;top:-.2em}#toast-container .rtl .toast-close-button{left:-.2em;right:.2em}}@media all and (min-width:241px) and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:18em}#toast-container>div.rtl{padding:8px 50px 8px 8px}#toast-container .toast-close-button{right:-.2em;top:-.2em}#toast-container .rtl .toast-close-button{left:-.2em;right:.2em}}@media all and (min-width:481px) and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:25em}#toast-container>div.rtl{padding:15px 50px 15px 15px}} \ No newline at end of file diff --git a/out/fonts/FontAwesome.otf b/out/fonts/FontAwesome.otf index d4de13e832d567ff29c5b4e9561b8c370348cc9c..401ec0f36e4f73b8efa40bd6f604fe80d286db70 100644 GIT binary patch delta 52632 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 delta 42590 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 OwyI90UFxgj$o~QNhKXzd diff --git a/out/fonts/fontawesome-webfont.eot b/out/fonts/fontawesome-webfont.eot index c7b00d2ba8896fd29de846b19f89fcf0d56ad152..e9f60ca953f93e35eab4108bd414bc02ddcf3928 100644 GIT binary patch literal 165742 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 G*yFsbY~cLNXLP73aA74Mq6M9f^&YV`isWW zU@CY~qxP|&bnWBDi{LM9r0!uDR`&3$@xh)p^>voF;SAaZi_ozepkmLV+&hGKrp0jy9{6cAs)nGCitl6Cw2c%Z0GVz1C zH-$3>en`tRh)Z(8))4y=esC5oyjkopd;K_uLM(K16Uoowyo4@9gTv5u=A_uBd0McB zG~8g=+O1_GWtp;w*7oD;g7xT0>D9KH`rx%cs^JH~P_@+@N5^&vZtAIXZ@TH+Rb$iX zv8(8dKV^46(Z&yFGFn4hNolFPVozn;+&27G?m@2LsJe7YgGEHj?!M`nn`S-w=q$Y4 zB>(63Fnnw_J_&IJT0ztZtSecc!QccI&<3XK0KsV4VV(j@25^A-xlh_$hgq6}Ke~GZ zhiQV3X|Mlv6UKb8uXL$*D>r^GD8;;u+Pi;zrDxZzjvWE#@cNGO`q~o7B+DH$I?5#T zf_t7@)B41BzjIgI68Bcci{s-$P8pU>=kLG8SB$x;c&X=_mE3UN@*eF+YgP|eXQVn) z)pd&9U^7r1QaaX{+Wb-9S8_jQZC19~W) z*_+RuH*MPD=B_m7we#2A@YwQv$kH2gA%qk7H)?k!jWbzcHWK497Ke<$ggzW+IYI2A zFQ_A$Ae4bxFvl4XPu2-7cn1vW-EWQ6?|>Qm*6uI!JNaRLXZFc5@3r48t0~)bwpU*5 z-KNE}N45AiuXh{&18l_quuV$6w|?c-PtzqcPhY)q{d+Hc_@OkartG`dddteZXK&Je zGpYJ-+PmEUR`sOnx42*X$6KT~@9ze#J>YvvaN24jI}4QG3M;w<>~!2i@r)9lI!6N1 z0GN((xJjHUB^|#9vJgy=07qv}Kw>zE+6qQns-L}JIqLFtY3pDu_$~YrZOO$WEpF>3 zXTu#w7J9w+@)x-6oW(5`w;GI8gk@*+!5ew8iD$g=DR*n@|2*R`zxe7azdr7~Z;$%< zSH@*lQ9U(Hx^%Fb|1?Smv({(NaZW+DGsnNWwX(DFUG8)(b6Rn>MzUxlZhNbVe>`mS zl&aJjk3F~9{lT-}y>e~pI}kOf@0^%Vdj&m(iK4LTf6kmF!_0HQ$`f-eBnmdTsf$_3 zR`hz2EjKIKWL6z@jj1}us>ZmY)iQInPifzSiOFN92j9$pX*CuV8SPrD#b%Qa97~TI zS6)?BPUgFnkqG8{{HUwd)%ZsvurI~=Jr8YSkhUA!RANJ;o|D->9S9QB5DxTybH&PGFtc0Z>dLwr|Ah}aX`XwTtE&UssYSEILtNijh)8)WWjMm$uT;+p1|=L z><4lEg%APBLn+FRr&2tGd)7icqrVXFE;+3j`3p~mvsiDMU>yK$19$B@8$Dy4GClfzo4)s_o2NuM3t-WhCrXE>LQ z_CQtR*!a0mhnw#I2S=WxT_H@^Saif`)uhLNJC zq4{bSCwYBd!4>6KGH5y~WZc@7_X~RqtaSN(`jfT!KhgGR)3iN50ecR$!|?Vq8|xa+ zY#*+B=>j4;wypclu7?wd+y06`GlVf2vBXzuPA;JgpfkIa1gXG88sZ*aS`(w z_9`LL4@aT0p!4H7sWP`mwUZRKCu@UWdNi-yebkfmNN+*QU+N*lf6BAJ$FNs^SLmDz z^algGcLq`f>-uKOd_Ws4y^1_2ucQaL>xyaQjy!eVD6OQi>km;_zvHS=ZpZZrw4)}Z zPz(rC?a`hZiQV9o^s>b?f-~ljm1*4IE<3plqCV}_shIiuQl=uKB4vUx2T$RCFr0{u z1v660Y3?>kX@{19i6;*CA}pJsFpo{nculW61+66XAOBZD< z{H|h`mJS5C2;ymL##}U*MC%fL0R97OSQ@lUXQ-j?i{z{=l-!$64H{LlTLo{Ln<|OV zBWq*5LP`KJl74fC{GzzP_Z;;;6i--QpZUrtHC@+RBlt+=_3TyV4gk=4b{TBJAx!GehYbTby(&-R337 zQ%g2)Uc&K|x|eL0yR*VCXDBqZ89C(obOFYYht(k`^q0OaQ*Y{)@7xE~KQ7XN)hGlZ zl5$1<#s!tyf%>mbIG(9WR`R*{Qc_h(ZGT^8>7lXOw^g1iIE2EdRaR^3nx_UUDy#W6 zy!q(v^QLL*42nxBK!$WVOv)I9Z4InlKtv#qJOzoZTxx86<5tQ*v528nxJ^sm+_tRp zT7oVNE7-NgcoqA#NPr*AT|8xEa)x&K#QaWEb{M34!cH-0Ro63!ec@APIJoOuP&|13 z9CFAVMAe@*(L6g{3h&p2m!K zEG?(A$c(3trJ5LHQ@(h3@`CB*ep}GDYSOwpgT=cZU;F&F6(b=V*TLLD z*fq(p>yRHTG1ttB*(Q8xLAl4cZdp^?6=QjcG;_V(q>MY0FOru|-SE}@^WElQTpCQZ zAMJy_$l;GISf1ZmbTzkD(^S!#q?(lDIA?SIrj2H$hs*|^{b|Kp!zXPTcjcCcfA+KN zdlV!rFo2RY@10$^a_d*-?j7HJC;KhfoB%@;*{;(hx_iP`#qI(?qa{b zH|YEvx~cE^RQ4J}dS>z%gK-XYm&uvZcgoyLClEhS(`FJ^zV!Vl&2c{U4N9z_|1($J znob`V2~>KDKA&dTi9YwyS#e-5dYkH?3rN(#;$}@K&5Yu}2s&MGF*w{xhbAzS@z(qi z&k99O!34}xTQ`?X!RRgjc)80Qud0{3UN4(nS5uZ1#K=^l&$CdhVr%4<67S=#uNP z$hnqV471K$Gy&){4ElZt?A?0NLoW2o_3R)!o~sw#>7&;Vq954STsM(+32Z#w^MksO zsrqpE@Js9$)|uQzKbXiMwttapenf8iB|j(wIa2-@GqE@(2P#M09Rvvhdu!sE0Mx&cK&$EtK}}WywYEC~MF5r3cUj%d$|lLwY4>`) z_D++uNojUl@4Cz8YF3nvwp>JWtwGtSG`nnfeNp(_RYv`S2?qhgb_(1$KD6ymTRgnD zx^~3GBD2+4vB9{=V_iMG*kQTX;ycG^`f{n+VxR4Ah!t~JQ6Z?Q;ws}Jw|#YE0jR0S z+36oq6_8xno^4J?Y02d!iad3xPm+8~r^*Vvr4A<|$^#UEbKvJ9YHF=Ch2jF`4!QS# zl8We8%)x>ejzT^IH%ymE#EBe2~-$}ZXtz&vZ_NgVk4kc zOv-dk(6ie2e{lAqYwn9Q$weL#^Nh?MpPUK z#Cb)4d96*6`>t7Zwsz#_qbv6CnswLS9Jt|b`8Mqz?`?H1tT99K#4#d+VwAy}#eC74 z;%UFxaNB!Zw`R9){Pncrny4>k;D}TV2BU0ua-+Fsp>wmcX#SGkn`h0O`pN*`jUj8q zIlnc7x6NRbR)=wP1g`-}2unC>O6ow=s{=NV6pfEo3=tY8 z=*$TKFk8Wv0K8B_**m*Q>+VW*1&gD#{#GSc(h#YQL?*<(ZUx~>L^RyAG3}j0&Q|mJtT7ec|Y7cr~ z+A`Wz!Sqz9bk0u-kftk^q{FPl4N+T(>4(fl@jEEVfNE$b*XSE)(t-A>4>`O^cXfrj zd_nrA-@@u?czM(o3OVDok%p3(((12`76;LwysK$;diTl$BdV)!p5Gj=swpb=j2N>b zqJ1D5E#zO9e(vJ6+rGuy<(PS-B6=gHvFat&)qr%j7T`vT1ju zIvHwGCk5)id{uDi@-e?0J*(-W-RGZs)uhSeqv7TA&h|CUx(R0ysoiQC8XnxL&RXI3 zO`H`8Pe&^ePw*`{rIJhzUg@MuhUL`IONG^*V?R0h5@BRDFgEF45b0jSrg0r{<4X)nw^c)uQ_Ai_p>ic!=K$pmnyqYb=`6fUo40ru#Gh= zMRJxOD(1n?Mjz_|IWyJK5^fh3*n>eI0MmEKq%=-oIdGd4F-LT>RL)Bp5FWxb4aNLNXB^o?YBSXQ`SwN zI*N~(CQW~P$HpzwrMG4IZKI>TVI4nQ$a-#)zV}LE(xgQ5MG@L#e!e@ ziNtg{Ph&qpX9FLaMlqMh>3)Nu%sAO#1NEsbe=#4Vqx0Y;<~+mV!xwj%}Z=xZn= zSqjxSH4T~v>Xd*=2wmHPN?@+9!}aQz-9(UIITZ==EB9}pgY1H4xu^-WdOFSK!ocZc zd-qhN$eZcN#Q^0>8J%)XI$4W(IW6R810*ucIM7Q#`twI|?$LYR1kr>3#{B{Z4X(xm&Cb21d^F9MKiD=wk_r+a=nyK!s^$zdXglCdshbfKBqa5aMwN#LmSNj6+DPhH4K-GxRl;#@=IJc zm{h}JsmQFrHCioWCBGzjr5p9L4$t4`c5#Cz(NJ#+R7q-)Tx2)6>#WZDhLGJD964iJ zJXu`snOYJYy=`<+b*HDiI9XPo8XK$TF86)Ub5=NC@VN#f$~GDsjk01g$;wDY!KqOh zC$x={(PT7CH7c?ZPH{RNz}Tel$>M0p;je4|O2|%Yq8@sCb7gRhgR4a*qf+WGD>E8~ z`wb<@^QX)i-7&*Z>U6qXMt_B2M#tzmqZTA1PNgzcvs|(|-E z4t*ZT-`kgepLl0g1>H!{(h8b`Ko=fR+|!L_Iji>5-Qf34-}z%X8+*Qwe^XrIS4Re$ zWUblH=yEfj!IgeIQ>m}+`V(4u?6c;s&Ym_6+pt|V`IQ1!oAC@R1XC3tL4BQ7`!TnU zWaoqG=nhI@e7dV7)8VzO8ivuC!q{hcxO7fo#2I=<`rktP0OfAO-CQE!ZT@}e7lw;{c) z@2l7RV$@&S5H@{=Bj~^Kp5At=Jq=Y92rXP@{-D4j>U=-a^gM2s-nIZA;u=fbm2BP=Zca5W81_cA>Tr z)x+r@{pu_la2Q(wm`Zqyd@GhNDNT&4oNHb_>w4{jIU}m&iXykMxvi;WL8;y7t}cp& z9CEpR)WlI1qmOq!zg4QTmzv#eP3>NLd7V-+YKmuyLFP533rd>WnvL$F3b}g39PYk; z)^hXQ%5jO(B}-TMio7@t<(V?7M5!ycd)u4Z+~!hym9+KwPVO^Wkhi^Dc7$R@)o$oh z^mRbgQ@5EvalJa}V4Bi3cs^w5pYtbXXz5W|e%+z-K;8M%Lf~BlZRvNI7=)cG6lbjg z?)l8iOw!mU`uaKN@UL4>d#edM9^-ePb(VICy6Cg-H^Ew$n_s801w`A83W!_Z{D+1G z(<9A>WB@>)D%cxw7c?Xv7N}6gg?&TkLX|0@k&VL)YMI~SsE^dzj2^3BKL7SM$!0Lt zj;ytKWw|(58n6_NNH$JVRh!W*wewMr7)H2jOCruuJAIIfPMFpf6j=hL!D3nVT9Dpo zut}|VoG<%v&w;HrQtz<%%T&X##*z5{D!!egoRN}R_Xxuy+E3dhx6!7mlNyuqsKR-P zlP#8EKGt{Ij~8kXY?&*%q)PkPG;rziWPd>HefyPwV49!>f&Q_@Fn{8Cyz{HCXuo+( zJMu<#{Tl}^-dh%nM0IrDa@V zMHgAog4`tk;DNK-c{HwRhx%Fn%ir3mex!XeZQ4QY)vQ_iZ(j4-GcO?@6Z-Y*f?u7_ zmf!}WRoGkI#BO9;5CFvMobtV@Qm?#eNKbbX!O@xEVhnm z6LFnWu=E}6kB82ZEf!g}n5&IuivccTHk-_5cazDAe+O!_j+dQ~aUBy~PM34Eq0X-LOl zjunFnO<4Nq|BL`!xwvyj&g9Q0(A_*xLT~l{^nM&kGzB7+^hP^L&bD7iVdXe3wobJXVX~o*tX$ zI5xthE?gAl!4+v~+ASbN2nYIqNn_#3>!fi2k=g*Hg_%caA#plNQR+RtHTiW>(*OFG*-nzu~6DMCrX>xzP`3sj}D!||8 zf3dk-w(NCUMu^C%k|t?sa>9gU_Ms-R2Hhm~4jNfPPyH!3Zy zV0QFf=MWK%>|(eV$pB5qOkC)uou{oIJwb_i4epV{W95%N)`+uOrLx7fNtD^czsq4B znAWb+Zsk|YX}a?b+sS-!*t2w1JUqU6Ol`&Jrqa5=4eeLWzr1DX1fWW`6MYf+8SOW< z+EMJ|fp${RJ7q9G7J+`pLof$#kBJP^i@%wNnG3fnK?&k>3IUVo3dbs9Nt)x_q|wIB zlBAi#1Xv-<+nr<13SBfkdzI?dJ|3~?-e>MzG(yRsA}I_oEd{HEGZ&7H|Km9mEbL6r z{Ubhh;h6_QXN_?>r(eWJ@CM1-yn6Y#am!aXXW!EfCpu}=btdYT?EJ>j+jeuc%;P2g z5*J%*$9La$^cy>u0DqjO#J%*IdaaPnAX#A6rRQ+sAHhY@o32==Ct3IF&sM14!2`FD zA))>ZKsccTyp$U0)vjABEY_N5lh(@e+Gj>sYOTgf?=82K)zw-?JX2d$x}n2Y0v%SjDtBXDxV2TyyxQmN?2%8zkKkKF*!AA$P$1#qrF%fUu~URt`tp3C_(>^tkcbHhO0Hh0A zpTVQR{DjsD=y-Bsl#nuTVKRxYbjpSJg|K+SEP+^Y*z3S9p(_-s9^YP5Zc?Vz*o(Qx z?f03co`dGfW}0T>UdEZaW>s0XVEzlw@s&bc+B-9;^^AGsx$AE~!1-7?tn9z|p4}_? zRsM&sjg1>#Rb#6jFBRKMeZ>I_4<%=&rF3yqUD&Lik@7<@2*(0rC)UqPj`Gfe8L&{S zhGtB67KhF{GnLZCF}gN0IrIPU_9lQ)mFNEOyl0tx-!qeCCX<;7*??>lNC*Q7`xe43 z2$7wD3MhiII4W*v6;Y775v{FSYqhp+|6)6BZR@Rdz4}#KZR4%=+E%T%_gX8-9KPT4 zo|$Aa1ohtUet#uro3p&@^FHhEX`OcGjq==$UeAQ~<6AZzZ|l75nn<#}+mo0rqWv5$ z1N<|1yMgX+Qmz?53v|%P=^&74bwqfH?xIC`L()W{|G`j^>kbs7q<$hb6fL@S za#nHyi$$TJ7*i!6estChR}QriMs#yy!@Po#AYdeWL~* zUR%)FT#4Q~O-N!O&it}b8zFOmbe=egH*Ka<9jT?dFCMAcagAo<>tKrW%w?P_A_gd& zXwHTn>a>WEWRzimu7EJ*$3~Jfv|@bLg}6iH4mgJB!o60eP#_N!xYrQoMf4&rGLau~D9ila zYGD*3*MNN?v*n6op+dQM!Kkr@qH1|^ zh7skG&aC;+$C$OSR2!ke>7|B6JDpjV%$Jo5hI14PGyx1I=Diw7>h@vzL?PLTzC;`; z?}nkmP%J6$BG!9mxz?+Np zIHbVy&<#H&Ekz1(ksSJ_NDQ+XHyg-!YcW8YvE5v*jFQ->F;|Q-IB@Mw6YP~v=jY$~9n@~8MVO{1g z@g=-I$aXs1BH&>hK(~|d>Y9n*;xRm&07=pLuqVYV-bwyCUIKgMdLSrovEs2f3{b z<++d|UX&}*7)y8){Ntc{RL*udOS8r%JV4EZ64fUF85n7%NAWejYbLV}NB|lS>SnYN z?PFpysSR*OodDcNK;OVKsSbKS^g;|bSdogA=};1?3rYq|Nc_tR!b2ln>=bNTL59uS zZjF^Y1RoS7qF^>LEqt<#Mu0ZjpiUNLtsc5%t*8}5lW4OWwFXfqGn-q~H)5}2mSRZ^ zKpfQxOe+KC(M5V`tz1zQ)@pTTQ2?NgStmwpvPCi&U9wd)m<^I-w&{(`Vb?Q*4ApV5 z(G}DMfgox!S_C+OTa5UkEbB#G$SC<8vLrDPPT_Uq5N~7`%Js5Ut3!o!f@HJm?b;(N zbbv90V6J7=E&)E`b|}N4n`VOOuvo$IEMx`%EkX8mpug0yY80enF3?M57gI zQ((b(;dv_v7PDKFgL|6)q^sb%Gp_aU)wp^uX96>jGEsOmBhyuDZ8}+y{bG?UqGqyDfYMtJ{6@xXI>fVC9g+uG zbQzl4fY>P6VAkv8GEpapl2>quqSIoui)Mr95Nuw@voGBux%Mq zYqG!&A9RXvoI%gZRwI->g2SYPB1tbg0U9UkC70cRFPTKU0L{E!2e?|as;p-wNwA;> zm}yKfYURNzE545Jz^T+srPZUGX{3qx0H&3ol`)Eow3xXj!2lx+DkB=}EoF`(n^)2W z_26hljpwvSdw}akJQN9;WAQnnHTN=3Ko19hR`Qqt#60*^1acxN84Oi8W-4nXd^@w0 zVpMzKqWw_(cHwQ`*uQ>F4F;Ncc?}XU{q867ZF>zihsu1j_i%f38%41S53RkO-5Bq< z<^ffy6fQNDn;z=lDz2OXjU+MMr0ziZ)HseHI3+}-N8v$8UWEK_n5pL6VPUS@YH^ z-F?^bJ%5Vt}@l0B2B$XfpF!7J0KUW$rc!~hPD3+Ms%)ia=pl{0nuS0_) zMk9rt16uqE&;%{gtVGqhUs{u$%()O~zzC_11`vYVVXfdfEU}YwTDn~JYTSiTDRNih z4#ap?$m%48h4*c`rhEH7?VLTW9aCi~b>z~)W0xM$c|y(8H%u~4?Yic=Yr3WyCvBMC z9P;P}Ra`!CY1TVd3~%qgX48EO<*6O5d**2Osm_lAM&ZKw?7XUKU$o?gjCIcqH|%NJ zuxtIAj>_t$YW%D0ShIfD2DzU5%qnHsRN0vm^B3-wcim7D^;K7~Uj8EuKZ;X3tlbVD z(=eh%wxAVAWPvDL3Mmg=TPKpMGzTdG=aT&qTw(TFBIg<;`kFOrB)&>#;&>KE1kb>+ z2B2dhdAN+pj}^ZH_t#P}WOC_RDs4ppbD0<}eknMnviR2G%#`AniYwzKw-y(_5*$-_ zmw5S-TNmxQbkR$TmM>p=*`CF(EG{@lszbazB$k;2MYhTooy&w{`02hJ3>+yIKEOe7 z@JMkSHwDW^-jsRwlSM}sEqQs-p1n(#FUOllp3=O)Tup&?1<^)a@`nk7JGz35N>n$} zBOy~(>fI9qX^_jCE*5|=cn@Q((|dZ4jk)4MmOAk+0xA#wuDRF-%lTtBwIA!9Gr9Ct z$c`7mj%LBTedqC%Rm_T=dk5?Lu6Ta&XaF9q!a$AUtk$ z*e$72Su7q{Rad`o)%w|Sbyv5rzAip{{VH|GtUY1tf`Dk1!6*HuN9YH|>@$Gpvq}N6 zCzbi<_XLxmE|LLdr@JCzPlDyUYO2J>kDK?krp5CY@11*7)8aCVVb&~zrEGE2O>>tojkD`+_dDb1*Ao``HQpP(giSRL)4OKuTMcNVOb@(m7M?noGc?geUJ;8t6u0>WYa5RLDJ>(^Zu~>-DTzEbb z=Pw6=C#Q(ao#It|Sa^jEBWtV8YNL5Ce+KO1 zHqBg6?QNQUAP0QbaOG=Lqb?5ZLlZP3JdqXFBbSG?_!QPegco`UzEDBCfy7n?l|5O(2uWh*{9fh*}OFkZGv)4J9g^Su_Z-y zktO~$6KAdO?4HIhm;a)+gVRbF%BNDw_qH-YUp3>pUiriPU-DaPao4J;%WF%Dllm58 z#~3FQnvO5O$UIv}o~Up(EN-l>@f8Ipwl+*yG^2h|U81N>`H9+~R;Nq6WZk+k_l_|; zqH`}-wki9Eekf?yVOxp~wx$i7mS&wyRfA;|YZ$pD0iFQM7=^Of;Mb5{*g%Q+MV}ZZ z4uCY|_@8q>JQ{}h=B5NG!svf6mRKr5#bVli@?ZR%doi+~75m0rb2XFdcTK&}XtK)Y z#n$?!<(KX3?3gc;rSMQ3)+>e{<=;f)h)dXgJA+DdJ5q_(=fbyjlD zyxOq~%LPEFsh*KmXEIW|_M9hDm%Gdrv97&s&LCvUqb)02CoZ4W(b4X%EB2q(#G5YM z&@wJkH_qwtRocyZt7Y4`(pa=cD4!kEPl#4{yum=*q|U{&O2DV&=)yXRws%3})r>`7 zty6tM=kuW2FpR*(!{^GYty*Jp1woSmG%(Qs4H^#!;!Q>OdkH@{*K(vzM1v#qO$_R{ z7+Jto9d&*4xTs#V1lt-9mM`tTxU{8|32n(X!6M-UNsS#R?m__F|Gn3X9 z&{djT%C$c`e{S8Bi4#KMy0LTS?(Vvq%{y6Caq7xk-@t{Re0DV4heM^6gkrEpL-{{% z)|>$4EU3Gq;JmPH{E@zsRX+#@>gc;qk2i2FwVHuCI??#%xdiMweM zWaT78*EG!|+OV634wd0UaR@TenRhksaP%AUUdHC0VcZ2nT> z|Lq#TX5O&2h!GYviFiX{IRHYEViDCLf^Wf)se&K4oOU>MQK$_!7!L(|E5Bx`dn|^Z z8D!P9pUu^~tYLFpB<~24WRqgt9Jadj5ce6JRV}}8O%6hRA!!0JH5LHs91WhgWWLJ- z!KL(|#^$p^amdJ5g8rZ$Ggy6?%`B;J_Kppf<0XMKcmmW9@>-TJn~gIShXI5aI(xEx zlSd-_6cOeEGR2J$MBqWpK*2%7D7_wEFG0(EP;?Sr1EpZsk|pld3%9nq47KjwNtga; z^X`AUY0HzBudMExSE>hYgVxdT>O;3bbp6&zv#t6lVjtU=7OitgFDbdK>r_jozEYb*t7qdj?MRk%pu)4==CR^bNgHOU-j*emraW7T2WR%b?1^<K?p<`lIUQwM$W=cui|bx}?bTOb6E1v3`QcM^BdcQe z=PpkFc*njs2H)6MH*NX+$l&D3bkD1=@_CF6^b#6m7%YZwDoKJobt%*>6l7EZ=V>@G zzzY{zEr!q?#B%Vk9VD%4E~MxbJ)hcn+q^0Z=@qNy9XNJiUX{8Ns(OzNq-fqrsbhbE ziWT!T7SLhKQavnveOJ`2^uK@O;eGSx?>nsSlq%#_#sdo9iphZ#Jwo|{FhMbfSrS>R zQiwFss8KQy?9j`|&<*8j64q^OVgV#e63^ksE_l^9($wb9f`EyHv4&?kqn<@TAOMm< ze1YGL4dcENbcWZd&n7h~Atmwe(#RoslRpeyDguGF}j}$MRo9?SM8!=4Q2wU($EzceOopeaHDv$UhoQfY3;W=e^g5xM87H z;I{8*GeL)G;HH8ITBt8$#)NOPnG>ql&Qh*h zWt>ty34rm;*F33uigBg#?eg{u7R{5>Q`U$R2j3@_Lkx_M{bOC#*zx1XR_*c*B-IGq(GV|B@o{8hJ3p1*lD@AJn%&$i*n1|9(=hKoMs|KsjeFu0HwhG-gj z6NR02xQ2KllvU2l&Q+ddYuKj6LihSj-&!x-tUR@F>EtCIlkybUel`o1t{IyqKm3Y# z^I%x~1FN64cI~X$=bbnBPUd;Rxn=jXhSG-2Z`jT3lX2q?hsL#({W072*)OlJJQjT){R0dcw$MIV@Im_3E)riYBiU=q`Y_6ca&e9uVeb_jW)Y(*6X`BKYM85 z!b8t)Ui*XT*XL>UuiVO9x8B8yUlNM}WBcAqm)&yESfoE>5R7X!w(jnYSbl8TpaivJ~v3;LD^f$vOykiS%0kDp1GRq zVCg_iC;5ATIf&(~gt_DK_8Vo2`%JbUh z9jfe_*S6Eje-d8cyItyiX=UK|B_;1L?UVG9n?6x~K;xR|0vZ5x!At8OJYq-&B}jT5 z#x}{P70vb-p^szS5EvI&o&q#3;_jrm%4X&6S8u*@Sv#ZVm@V<@Hf3s4l;7vm>@w-r|)yZS%w?(I1*QeIrsG=I+5nepzsGxrc~ z!pSc|SCA)uB~*o*q}1leH+COyX<6)cl^Ly@AOH2^A6)<8mq0BH{PW9E7WVFW74(6f z)`kEd2^SPxr15s^#3*QkxXWqEyk{wqj1GtNbEQ|(J1tK6 zUnIYs&2$CihuMv=&x^lu`v>+G339PrtlYp%HorK*>MU~Tjmr477+hGhviLYl@>d-K zU!uTPY~kv}%w^h&xW}uU?TFq&;?(Rl#6glkWN>Gw4B#URl`pWSWHsaPj-^{T?+Rl%;){@`StD{A2dwJ|V96v& z$16bph~Zles|b2KXKVo$Gy2J6qqP8xDY~bRh4}rn$()b-mt@e#Fwd)MdNQq8Y*-I^ zKqOSY68uyOQhX&e!epDI){mhNNM=IwXQLY2+&brLfPWf!2x1u(hS5ey?BxMlyyvL* z=no!g*pcWU2>q^rYg;4Lqki3-zG)X;d+6E=r*#^~7*m$_EGg_eQ=4jA+oZ8YMYWd6 zb?&a!UGBQcmfE7Cu~J)W?WPsCJoTfeZdoCs5nPtKdb}+(w{hma1+}#c_RZX|z*J-U z`YpG79lHe^?%Xkc?nU**&Cy^m+F0WA*VWfFHrCYF`F$mgbgj9#{-U|#cig$|;T=<^ z?0A^d|2~dA8{jc0T&>LodGPkA2Ce<%xn1wIlX?a%!@Eq4Md6Y$Pjh8C)#tL9&B{-Z zDl*AaMfM==qY6ZMs*j2-_o&#DtOvEgKO^o#a!G8V!FLJa99SgR=R+3-1WD>6kPt4T zQEnn&KOhDe*4&&kDJBfJWl@4anq%Se(e27Iv}pbO#r>3wvWJpUt}zNZYx9klkhS?P zCbrI418eh@4+uTT5z<4YR!}Wu!0bb{)|g-CHs~wgPLx_;gZ}Pe*r4aOmyr#+pp0lb zHFY6iYKHu9A$fn1?OWE+XV41w8uJSK1!e3*OLwh>v1U`ou!Z{BA27G z@n6d|J;N3qwe4uQiV3KTDcpf57p!m?0p3so1Ax@X#2IiaA}2>9&SUXL^1&>Xh8#Oo zQ?C?L-8M|oiJLpU6Q{%GGh;&0K{owhQSY%3!h1qcSn>U|R_L;f`cCNUO-efJ#sSbh zkg5Hb9y)Ys=YeAvt+X|EzTjRz37BGClh(UmXfNBmxvV{Ttan9870vRhk`;uSF?`m! zyWBXXtg*^vTY1s31F*aP^xb!Xf`+yrz9*G!3+V51{2PK^bPhMbp(nxq$mtS*2*~V% z(N&JbY2FYBI?V#24?IeNyZFFOpZ~&zB|@M?sbh`bnlV9zkG}tHdLK zx+5aQXm)byO7#8XHFtDn$5~LO*5aqH%?m z$2wT6nTmGDI)?$JimeWHNO7Kra|S#r4ugug1UgoGf)+&L03keV@p1OHE$p^lBA zt*GJGLDNniq=XZ4I+Mb*82pqbfoQ@+p_JGdB0aQaeTB!Lr#Z$97FjWL@MMe@Z^D+s z&IK)jih;Wbb%1MocDc@#$)|IKVWN*g2&aNVGFMmdoaL`cE`T^;1?Tcf@^i>q-czu= zA7p!sX62V=__ATa&S(g9I0rd{)J6Sdr^qB}JA4(U(1Y-`7)a4D)MA`g7I!Mwm6+KC z^C_nUK7sX}(ukntS*u>(uyyY=UeDi#4Mlus`)o8@(xaLmYhKp;LGw3oP&Rni)G|cQ z7Ur#P!U!VO1g(pNoJAP;`R9fA(}??`-wW?AJpaG_{Fi;Nu)eT^;QuU%IRlFc*+_>_ zx`&U5+e^|ih7FuRhmOU(m+aK71UlNUGH`jW!KA(Xf;sb)=69M;|L@O||H&xL zl74Wt!{fDxvzf&5M8E`Lo>IUfK@P&dqXA1j9Ysfw#32a=jPn2f=>Dps?=)zh0y=nF zlN*J67GXr@2Az6He%|WXWJyrTG^F6<|JoS+k`Xm{tCR{6!43_i__z|&s!LT*4`;a3 zwB^UO!_$ZGtWdT77?_S^7Dqv~y|xiDP)-YnK8%pxr7p+Lxp?4~wPvULd zUmZLLn47GQg>WUt!yAzB$G%F{zYS~B=am%aex&q3x^I|U4B;Xp?}AZk z^YIrlk>Jo6{xrIjl;V~Ot%d0#DhpmMHo+{Xi^Rz)*c5L{kRh`PE-|>;1QQ0h^lDfo zd@>|=U5Y91Dt-M)<#*Gl`Fr}3$-Z}Nfx!+IeZ!v7G% ztcDQl>kp+vdVk8V$G)HSg>V(Daj1A4`JRB+&HA5cq3-~n7Y2oBATKb2YG`uA6X8S{ zY?6>Vt(nsVyAxRF6YnNNtUn~CLrIFaIITfuxMVt=e)j}2Or%oj&|p93A5+|pOZ*pd z#pmb`Sv&G65piAWD5e2SoNSIcgY-cWl#06J$28$_X(YT)8umd{pHg7Zo=kQW0->a_ z7yr))>upwE8ZMWr(itk!ke5-mNGO~-u?owjq}8&~H}EaBRQUYJk_kzaMJ-j~1H#0S z1rxw$&lCSsY5*5Eh9p`{{~@y^&(mjM(r6cji;VSvEmZ0dZ}u7v>WxNaH@lu48ujuc z{04p_HtH?AmEG!dXI$pv!-8`CYpz_XJ(2siAQuczyy!!@pi$wT{)yp>!Xhe@`nl`z z1^zAe8p<`=WnrFL1*!@PPZ=huBJ={PS>a{s$9bBsNe$AX5$!cHKZH|luaOs}hA*pi zw$Rj=>@_5!LqS+x4X9Y`l2I@7_L`@81m(I&E!VL96$Z9khIpPCg?Db=MU?BT)g7f3 z1oR}eOn#rEov2`=TqatC@g-cu`;n}|1~nUG-Vnn;qJfhg6hp5T(E`dSLj-kY;GX6Q zi-z9$l?TDudYiv<9p*t?+4_WO=CNA5llp|}o}F1=q4CAqvoxnl z-+26xjr)Osgn&kH{tC8-tSujYAX&ByDk<0rhH0A)eE8>_MbIX>Z9mf=3Xu{d5DSGe z{bXd;!bUBGMEs02AatuZk6h5A3ny8K=vdpjVylr_0=J@48tARLevxvQQ6xQRF2uMT zDdlo6=qryT!$n?JVgWh91v4nu1G=%?-N5?j)BLSd2l{{#%0EAV&&xf1Dr{4qxZQ5= zL(D1c=mH9)qTh-=!wPQK;G!Plb9%5!QL&)AKmk+G}epRD9NQD(&9O0C6ZElh(DA_jLN=MkxobFd(kGnzu)+M~#d1*vxjpI7N&Q;y&0Q(nt9Ov@ z0UAx~93%#q(<@Bk9CzjhzLPRMRY32Y!M4>0SFb)OeWL#Q0u->@`-CeGuA;1us}BAQ zc@mIQK>2shoeQcVJ#!PiaLyd@Kj_ibnQy2+9_9fE%1-skgH%88v00xH6V6~l&y7;< z3z*+Y;rwAP`&tJ>jA`DJcZ`7&@iupQ%b%(G56`bmS<#9BG;0CU_T(luy zt=;C3Nlc<}xz{ z@bcSeLnyAw`PUGAL>*F~12pf(YnG!XZdkkO7$`Hc?ByN%$Z$rECfLDLP%2`Mw2Lkn z%iuczcuO)T(Vwa}C$&16nxS+qnzVRQ5p9I84;?;p=#nva%=pfXYl&x;$;i_ zP|dt~6wqbsm-{)G2ROAL$rK4<&wrWS4F}$7>VLjZ~K@NB#Cl zO&Qzj{Xrj9Q?1IwthH&{H`*sEN1LX>TEL$T9bDBnzAi-V%H>rqOSs{8i9DPnOQEm? zKnSNAa;HMY+M##OP3;`0pT=G%gsg(SQ~>24N?A+(Cl^G2rTi+Y_Xmo`>Wi*@@Y*8% zxO%^0U>2&c=s7QU*VIcq8^q`sm^J3$P#9i9SGJWj|-YQ|Bbro{q^IrwHjL#@aw6r zO5(p)w}zsz_FT2}`msf*s$lq^*3AS90U;2;%8zQ$AmjS~uU@58ERcbWhv?f>K#BeL zYN8qi*%SY*!e{wB?9^3;*7vWVA<6l3`r<8_4JXqkECB$U^#wWOuf$1XFNlXZ{n58dU(CAELUC!&Oi-&kb(YyL&bkw zFG94K{HSTIT!grnt(x7Mt9azgH#FZz%{*?b|DaQ#z(AfKI!4Z}p<~>Ge#1Se1*{80 z*9-3X((C!(%0GrhVCY#e9J%8rDwB&WM#Ib#hh$(WdygIeQucm3{$#|=Kl+eJTk1Z-(L@12&%MZxw-kLv=48+WES(PWIT1Ks z0C<=YX2Yy?Fc%$1$a>sE6N@S(ydbyNTznjed+MRp# zqQd(Tx2JkitUck{ZkFv%h>+T$y361us*p`!x@ITML#@u!?BZJ-!@DqEXFzk1cNoI{ zJl=+S{D?*ZKK1{XW)YK5yzt`pzw`QU#6SP_sM{sCSn6GMftpB-*B5YYd}6E1T{V8s zBM)6)8@_GeJO87$68vfVhG%-%V?Wnl^6Z65%hMOv_5&oUSnJohv?fUse?PIwpgrjj zbkDBTKUc**{+~4@My+3;_M*cli^%=z;`psm^74d} zCj*Zab%E6QT+owC_c5m2HMR6aD{F5vvrm4M^bRUw2oc1;q9jPZaA_vxsFaP~U?%O27@cleW3dOF$d>Vq0Zl}ZBVHjH ztf_?4md<5`q8EHId=*llqXPIzIAX%~1B?b5_S~HV>kar}&i$g+Smv7ZlTat1QzXxJ z$_Fac3X5RMSd@80O63eVgMA|`7viFSV3ZmRpY_8pOoLm0i@%=q@I7J=7Vq5YX9ffA z{>R`WG+DU(#C;6O|HMaLg9l zl)V7Zh_060KjCS9biA=f=azMILnJ&h}h zly@(WRadr83lyzrB*7h*#Kz%c#TEcwRZLH44Gb)Vv~oEAv$QE>6AfHr(F(C#@+ zLJlGHE;Y1|WL2(ysP_V;dWc_?Nl(dVTAaYOpjag5{{*~1y#T?AsgabJdOGqoA-oeB zE0oxN_!V3X&c0eE1?A93*;A)ACcg=udm8GzJ~h))e_kxCET|AT%Htl--e2VXnV<@TsN3YA17M0e6&-Kk=YQOE2LMDBtsJQIke# z@?QDP5g#LZ(1S@bh&gBDacz8F` zRpD-jIg8-ap`Ym@6rNlM3=JFCvr)2b9N_9ODp{J#8`v;h=Es?IOxlxNiKM<#Q9_2M;_jSYUH}t zqe$Y&x^->4;JRt+*3Xu{ylQW~6s%=u)@ z9}!qmL7OlT#T4rTQru(OPi>~6!BlKwMiZNC$FYcG5yvTlmyw#v=M)cWYQ~gfFJVt> zq~`S7oR)6J2?icV&xW6Z&I8CNu=}8Y!-3V5*oU(pJV!{pyvacr8HA5P0nDoEQ%(JY zi_HlS4K2djpeQwr8f|LDf-$pdJEIqbnAcQ(`R2Mwiz8zq+ZHaqq%>Mu7wuYe%n&tL zfGjDLMa5%lx}tTse#w%qZMbXkq~r%<8NgEgk(yfXgz;U~-7DFX3+bnQ@#AqBY=^OF zLbS7X)|dq=R(4l+ji2DHt%>*r30Rp-(iA+JEy;u?keU%+qc(@`QA$BS9Orf!N}fVd zAL_Iua?ljh5MAJ^c}*yLOiMzDF9{(p(30MIi+m$<`Ua+XOL>c2D0t=$9GupiRQ`FA z{BOl%>K)}7|3O^Dzk_}@em{Rc@>6mR)GzU+fJP3!_lP56}Ebt+|2<0=uUVxPy z3)N6@44izF$8~7*yh5H)fjBg#!VE4emB7mt}4}d2r)5g#{ZnU8q)|NhnorPaQnz>S+LontCn2s+La0 zh$jQ|3fkihRKrX7xJMtz8qh?orW`edrfqDgrtxfxOwvIr^UxInxzk2wXb_tKnHl(z^v|lS3R^;C5-qU z@k^Q^e256y0(|hy8uo+8d0&n6hRC-))pyDz3Z=lgVFfaOs{79aG081CD(x1Z!z{a6rfg{`f{nt;>Z~S~76JTgmet|iqonNy9qSRCrj5SG zE*k8okuHXMA1b|YZ0qc>KB6<%`;DPFQ>HnqYN&4EGLuv20mv@Zt>Scu^WHjG$A{{M zn0_!1B4y#@2tE)shK{KGiRKDSUb&Ams?2};;|q5pJXA^P3}#c(A}>+?UHMSdS`A5u zx!-7KdwaT0vc*icx+RrkWvS1Vqu=l9QLeTd`z1pXyttbcEn$YF%gs^<``o$khc~%U z9?(+A$FHjL21BG2Kpc=@FYF5APed6YZ)jh=UwQm-OL4H}p<%olMV739mlk7y|VeJq6h({N-N`F)AkKU*9A zZncuEumPCb0)>TTg$*!DALN=JPBdym6qG@%J)>S~Clne0KH`mlb{f%P!tPP}AjxA# z93;`Q1V$D?)kIu!LsQfhjw9EQ9F=y_B1`piC?(juo)nIC0- zDn9&Z<}dFxHQlKEWj$Lbgq~n;oLYO|eW)MPm|++FFVI|Qe8Ff4uCPwVdtGoTV=nn! z9Mg!5}_H(v@l9y2_n5lmXZ?=E&S(lJU6Imo&ZWZIn@mAKqMS=Au89C=0ru@=+;YS z)498q9ZI9JWB0j$+}686F?+mvy={HRr$^I7WzrL;!!dIDMD^t8ryc8UdcBwRSe?@Q zeCZwRQ~JDm!Eo-)4?J-5xd4^sKe}D^^(*(gg=;zY{*Cfo)5#lh`mXYC@C%ts-TPOr zx4Ya5jAH>O zc|Naas2cQjC5qX ztN*_ zp0iX-C5(oALou489mBshd<ac}LWi(CgsaDL(eO*GXYH2uLp{vr@SV&-2TX_wJ$c zu;DVWH;0OocbL`LWcxFSsKaT)I-4jmq{X-c2t|aJQkL}QXiTVMz=F`J*S(Tc{UO0! zi%CAn@koN|GR(ehQJ(p;)$Op{@wSOMEh&o|_Qx>8!DwP- z`FJ}oaQjgCpV#o@Nx!OH&py^S(Mo<6#&dsVsr*A}PIAih}WFPR&w zCRp$^BQjucQVv0ZvdTb~5Y%*mLkorYIJsDrg^}#t?y#MKoS(VfIorvSE~hJ+Nkv_H z1NyT0bd&Z4`Byk{k++vY9$qbIp;T4E&6tF`tlp*!>j)C5KxYI&p)K>A@*LYD^nxH$ z?vczftYFCQBHl2#E4np$pk;es%l>Foya6Zs>Eu9EYEz!e5Y{R^h4l>CRPYp*(qm5H z=D~}jc&KkX?%Ns_4@L11PWDH)q8*0URaN#UIU9C%a`k~+cScW=kFDx3OHQ<-c(1A| zhLPT?d~EY|Lya>!Q^W8jeqE%Xq@>T#)`R;Q;n0=BC`ofPQDBM+{rFksZ55a(iGAa) zU*eU+_dJAYMzc*kC0`CJJP^FOO9?7Xpo<{uSO7rZNrA__;wfikngXyqdcC>NU}wp6 zrPBc|2Xff6WKjHOlr*OB8%+b_HySNtDX$lf;WU+r55_k%G}>I?y}14c>;mc66GV=~ zB>p6tL*)LIuB-?uX}lCp$PRoG3NBNh#Q-2Qmv!*o*&zk*WvQ}QR7jc9RyUZv;eI1q z1myA@D>js9##>)#Y7`z3u*P$CtoC0yo8w|Q6F271w2yF)%8KD0_2xTV;x+lRX_)S7 zLESy7mmECL$tj(~EAaM1nhN5QP)RT+`Em;B3)pSP8(VtVYgUKyj>BSg0P|KE5JF0S zre930DlR@=+*Q0v=*uq{`_A#ko)-3hEcA%gLXTvULWp5*D*ZywDm-z#xOi1heo6D& zsfhffDTW$dtI)HAE!7yiAVDOsdl1 z^kJ2l>S9UXuCtekeIpWyAb)r;s3gmj-+uKnaX)3%EDkWLFD+A&-j7eww|&#xTfkW^^2cYa9_rm4Q zin3x4(yLf3=0BYT{IwK{%rJaGAcrfB}x_x6~ z?NgR#`|L{eSv%T*Hvmwtyp-4g+;<#Yu-bvpE@#a&$atCK%V}j(r9`g}0;71P)B2$A z^>07GDy&Am=Vx|<@=_YGAKMS!>s6Le->|zU{Oc`LG~#QV)<2JRJPc{DYNOS8_y_LC zl{@TCrW62$lakMd)^-st?P%lI2t z)Hp`>W4-6c4x>S@{PH(^%>AB~t9w+1&30NhSzJq;*3A}|Fx76iJC$XzW&Y(3cE8JR zb!47(SvFgpOI(&s!0&j{;v!y#gh|u^kVZJ9B^rTLKq!cWhf6jz7>B3{VIyUy6St8` zt}7v#!kob_%sj7rhkZ`%r086h2XZFre!9|+So+}e;-=^KDM@y(a^Sx%DRgARg`+6@ zF2u-VGLQ-ZWzz#K(++!YiRJ=~3|GVj`!3)x5$zUkh)3uGfML}Os*EV|5hF(UJ{A{; zN;^ys#azEYS4VvUT}QTW$g@cuN;(_~!om}CfZ=y>M0q>J?!6&0ot>C}-$GouFs%Hh zTmXOk#{D|~3BT@JuRegi$szQ;LUnyKd=u@?UxB<`_Ui-kIc(E;I{yK`ZY?|iTsd&P z-Ds3oUP!mxQvQ9=j3s~$dYyr~$?Q9b+{-|eMivJd_6zn%Diy*g%^dgph0WMnjlyQm zYvbd%&X(IOX1{WrZT72MGXRGk%-(<@szG$F^a0wjK{JzM4tXi@39NXYNK<*-69LR< zHA_JJax@?fIF6fq^$B30HaB2{+{uk~5)kSg_1^k+EuCO#z)8DSy4iVj*ToiH!~Bac z@4lm}>JH~j*Yjl;)*~sL(K7eK*OTEpx-0KkaM|Wbua?%#Xj@*tK(C(|>l{C&ZhWb0 zMo~pu{jBOKI=QucYE5gb!YQVnoLhYCh8f$YkM&BY2iPFc51wjZM;I&Xyq~eb&xB70 zb!DyRW$vzMsVFjQ1?9U8snP5KICcCp+z|F5YaW9djR7^>S60XQbPOU4qinn+8ToxO zNmqH=nTD{Wfv@awt2Of=f=NR|5D_7WgKt``%4VxKRM|4nPih20e86-edqM8Km6$g( zF)F>V8F&FIKjPI0*Fu5JJohBIjc8gc^_8vam+bbN) z^b&a)S?@-wcXYVkV5Z!+PTi!3PaWYx6x{?3=UUM zy8MhLFoOTujq!`V*3tMSxoiS#=D?7Pp0%n(Q89qC3)`8F5QUBrh37*5=v^&^@-+(> z0htu_oq#P)lq8+7G(S15;V0Pkj8^Mm@ObujJiy12bM!;%^Wpm2hU;Hg%d@u!H?ron zhpV7{3eP3fX1D@MX!O<)`U>hiqBVv!FrlFe?i{Tt*v_Hf&)NWd%*!uj=XwWu1V=%m zC=E2Y%d?O9C>(f5K@*3!6y2GKU?CtUfo5X3XhJ~Qjcg?3QbPGiIU@?a)bx-J>E7bj!{QCXu3mQVoR({~yqt$+}u$pqisO>>~0Lk}B@ByTU1@@rY z>u~r$XBHw_V;CUK2l9wfE-|f+u$d`;80<3WWT;92N!SjR2{H~6qAwgjz)%Q~BE5t{ z5sXHIfmk23I8e_Z=spyPNqq^MSm$uq;)aRIt1IR@rrxz|-rh(cR#D{NJiasR3>XYL zQ?c6>sGBu5Y=Z}>%ZU`B67$U8nWmTEokDOZfCCqnPOb^fozyaELUjAIxk6bm033#B zK)9kPDhNB1%fimKXjQzX&F%7()mOHa`eSoz%C&yCm5&2z3k}+W{3v)^aQ~O=ST2;{ zqh1e}hLNfmPB0wKxK4n)$lD{=B-9?QB4!5iAyd1#&(;uI5^TqO<*$<7Dnfn947Tvt zS#<%IyV#^N7y{04=lIS3qKa4`vUlFHyQVtkR$QH&Xo%Y!jyh4ywM6DmD$Evdk4Gmh zpTE=U_G_b+^J4zew#xc4kIUUw6R(Q4Im646I|U(HBwPXSFjgH1mI-sGZI4bs!_5s5 z3VlxJW8l7`)tX5d8S9bLfPC=@;-9uH}`2fVh;~5}+A$u3Um=pMOMiBA#5(f+jB~MSC zn)!Lx?D_0_9r0+`pq+|DG;S}OtTT^^ggZJy6=Tf00YNken;J_z?vjl`&(-CAEmN*Y zCIyenIJNpZr0o0Xx|%6Qw;Ryo*9)=h0Xy!_Sk9T#&@^8c(nn0QS=duDz9H!G1RKVe zc%JC!;BeL*S`*&RKFe1V{`u~DM2I|G-q7&DbY%s5VEO^&mde^;UG{pRiU8kB^nWzuB+3UUR4BQ7)%rO`tFm8O&c}Ju*E2W7p9T9;I7yo!5lX z(M02^IocHA0|sI3XLKxj9>WcSSUt~xtJ8+~5J5C2jfxN-A*?|}r&Io+23KzE5u-v> z$p^6hGe@ZSLfq%|`r@qnoO1>zZdIP&vYv%jtSCiNV75YUt{d0P9x(tvw|d2j+HuYB z@9tg+vR3!~V7#LD=YyVw>~Aj&yNQK8!ugN z9UCp~oxz?gj&*j#ii=|%ov~uJU}aN%okhQriOygttN7OrFRS%-*41?$TfI8-OZKsH zO_fIsv2DtwH7}(~ORJa!MK2%;=)9#Q0e- z_BW5)m|^T*v&rE5TV+7}mC2O(gmsyWM(^LM{K_LvffdF7!z*rZDzod#Dcu7mwar$` z*4sUU=djGz-40u=a6w4CiClcL>lMlWR2F#kgGfL)E^!$C{h|!XpPfWluYi?|c7qNc3!frpzTKbdDdEx|9tNx80$qoyY*K46?85f0sW& z!7aa2ZZbRGWXiX!R!fDr&>YFc1tlDTfX&`!!oS+D8#!ILKE()Z+kfC_7D`;pT=h~J zBhY)eOM-}%pyjLp^|L}=3dbtO3hGJ%;x`FW2IZS?*ETc@zhv(z#m_v*Cd`@z?SI%G zDz$1|ag-7Xu5}ewtF<)b4}(GsDA&ELygY7vMMZRq|I9nAAvVB{pUSXJ24sg9wMM(o zrY%~PNZvB0^154YNvyzv?6VoQqUfS5)sk!s6`k=rvd$y_Iq}U&@DFME5PHT1kJKP} zEE^;b^Tc&c&>7%g!ecN)VEqyZlqJhD3)xb|seD(iW8I2Rd5A4z ze^$P$IK@fI%gP_wWaYhW%I|O^7V&L8tQdZqg7Tj9rt(MS6=qfbuKb7c6ILP~P=2EP zosEO=Vggafln`{`kuTQ?GZ?HQo+QOOT z9l{$Ong7}-Y~1)3dncttGLMU)9@dYzj8x6t-@Ho*98n&*MR;;==JZ~1Z|3qI;fhoD zo;ZPVIc$SdeJ>VhHsNXxx8JS}#q7!uNUUwQid_t{L=-8{Fsd9E_Udc(|1mz31cb(?I^6JaRZ zOzye$B}*=ydBfR%5-yO9@4d2IXr z(+>fwmj~Z*h2;hVYeof&)GC0`+b19}sRuI!+(055HHC{*^C?{$8X}1Po$Hc}qp<{*!Dk8*^uyoeAHZJU8U%?shoMt&Xib zYl<(OwlbyH9~UkQMhyC~<8{XJKyk#ND=F6NBZJPshK^b8abrb?-d)}l>3Pm>xa~G= zd5ie;1B$=2vDk4S7Tj(w853+Y)IY!XJ2L~drKL7goinzKq9^I6`gfQW4iB zl2x2%Fos>-71gXdzIe8N`N3XMNYqZh`AK(2yynh_YGNH8OI>;CFJ22*)VG*q+r7%> z`^<8{Humn%zh7QzyVl^S-u|WnM2=W>gQWLXXqjH?v~2l46QA&xl}Y1RW&YR{?x?Qw zy0NsUFij`?*r{2|!NL28 zsjd^jAOi;(BavJnJkV5@q6Njrx_pnV*!;-$`QZm=?(7`rmYGiaFE&qk+!E>-H~;02 zBJE6QS+!@+L?QH>z_N2MTvjXVl;wk&Q>BefNa&bv=T|ex#<8>^A^`R?a_9izLs%{U zRyz#ZBUff=dwWf5MPreXAx*?dJ(G)?HgsNDz3k3))2?Or<+tCQr@YKpImX9s`YD@k ztXaBwY0)>8)e|o6og%Pt(%Ag!lmACj$e`|sn$To(P86!}giq}j+a3JN9kL(9`Y z{Ef9%UIYG44HLEL>^n)PM^>{TZ54Di;NP@qDndc2gsadLfSJs%0vZVKL>I%adq*nDoUyd%E&iq!a(OQ%d)xUk{) z(OY-yczEWP&E>UgH_q6-y0LLVWXd7s-ICJD&CSscan9_=7?KCFDf{<77Yc>TaU%cy zy(5Q9OUuirR3tkZR`1yN3+b{+bLLELcAB(Dw{0CG+Tm`l`qF8*ueg}y4qyR}!j*y$ z0Mxzk?aWg8)20S@k!zRW%qtMWj59&|43(l zRJX}G;SP2*@$+4~exA6>qSKlWR#hD|Yju{)(cDwjt*ux`iSPOxO`=Czlrud(#EbK_y0L1SShwjawriLP+%D;20XRBpcdlLLkoHhta{ z^Z{xF;tp98FCrCAgdqm6q(YM3jowOiLFwCZj(R6>PGxJRo2b$0UM!pZ&2S<>8&R`n zUrgV^M@nVkc9Q|AcjZ-*&4_qD$p(`w8qDrlhMGW8GnNH=QI#WB9u9gff}qu! zbQZCAL9^FW=p|LAIrKz`K!ZhG)m9I;zuz}q$8H2&*a%a$KunOLo)9!W|Th6I$ zoiwXyoGBg(hea#1+5+~Vw1K&p){Ik|XtHRPZl(uZm)?Z-H6oK4I$TihaQbaUL3@d@ zTvsiRyTI+9eBZ^Df>e81UA(Ofz7Xx*r4?S!lybd@%#`(wOq^QeLacmJF0J$!MEwC9 z1W4TksMIEu*=ouJ(PUsHE^jHTs*r3}vyWK=vfgKd1B`>24GzQqOWS*Z$5EYa!+WM| z@4c_KuXm)KB}*=Hmz!{J;EH=$7dkdzzy@rv=rM+bVv4~K1p*-uz`UjeUW!S8 z03o3UjIAAi_nDP!;gG<4{nzg@J9DO=Iprz$b3a-so`jY9I1>j66mTJ=@l)$fIt8a- zfa8&};F79ws#SG91uJvZ7d3mNzp6COmD?@8dbisIw|K)Gbrxs4M4>B)vAXKw0(-Mu zFK2j#tW2*P9+68698FNSO)Il33nn{_;Vc!KV{kIS-w>VoX*u#mvr4!&8GV8y#^Wl3 zoNyfBTrAIg#z^Iij%YMePQ$|jqGkzq@_DtxX0-zLY~)PsF1^gC@L183@s-?J4nk@) zXxVCm$~IA@FA9egYEEek1ls&&p4I4bq;|DcrEAt26jFy=nx$o>d1Vbz!&7DL0fk*} z_0V+QbIY5}SCuV&u6up1g?L;!`r&}3Di6xhT1ghHCIw(Tse_keCZxa!8>CMEC@gPmB+B{eEN#oA z1IAc_fg+2Kz<3QQEg&oBsg)HQoGB8eXNjW;IHZ6pDjz~C$4PQ#GK{|bx=oh`b&q|v zz1ET?{889VCXFt+_VV?SFlU^%X2a!uS)_n{=YRe%F?-2%{a;~HXGR@9(J^Ypfr8_`djf#7FG;gj{on>7Lh|!^&$cLg14JiQ18@Y;(tRcsrUG z3+;eso*#O7N`aS=bwnIyon$&@w6X#g2swm6!^;6&2#s}x&kI=yAv+`PiDpH|v|Rwd z7_Chj>zYZtg~AX`Lo5c=K`Me|#9587gAgM8 zsU=O3_6aq+x~*BG8%oC%=ahI#O20kOcJY!%vgm{TTjzJST_v1)a*2NQzy{&z26?Mw zYz=Djv%|PD17Ve!3((nH1d+{kg36>_HLwOjNdpL5V*u z=6|HfKUmY*pv6QRmWYl&qh+8mnc_e+Q7Mrs2td3+mLH7y0U=4O)brQ;?-hu4YAon2 zXoRmw@qPYZJ*BY<5Wu$0BdK|9;HDCKwmrUW+v5bdkX$l;yD&#*1abG51&xgbAU1Ux zb!6{$;b3k>%ws31MT>-#o$a9~Y|A_=ctwsQ&Yq%!2ZUWXT|}Yx++VnbQD=kChukQm zE0T><5$KBlSO>8v$U24N;?uB6nt}y+0ebqEicfM>D5AgY)k3dW-V1sV^3vJoNQr&a zBJpEfLz9H)gYk>jT>&+=S#6;qV-(Ai>2UrO#wOI-Lp9YQd+mhm0yu=YN#_hOpOLq$ z?L9sxnRNOI zjpoF3Dd1?Nq=(lT)F)18^w>*EGJDnP%wFMT?A2>doKTD3JjFkScnu?3s3c6sH9D+G z#SsvhI>TaCS~25#c}SF$Da8i`4r2pcKmRPRctm*N(ELB1MmX8lt1(|jrVAGx-$zr- zu6ULhZ_G0o{S&6_I(gly3$lG$*{67$@<;matPy_w=2j3Nu7BpmZ`Qp`-1}}Mwm)r@ zGTGU_k*}<{?&PjgqfZ+{pU&8%Gd}HH`ZdI%3S+VV-*Eir`nb8|5H<~F?$92LJtrl! zJ4>--?h<1JiKIVCi$pIhx$7(s2YNCi$vWLD?SXxuk)pxS>T{t0Bc@1f1{fD%mj=B; z;XosWnIF(9N?{074C0VzbMT{43=jkn=!aQWX%Cn@nvTK|UT%DjHzyls7Ntt(v{h?$ zkDA?f&?g&Ss5(v`==gmmFs|OmcH9TPRnvXPokB}G^#oBq!5}5`!PT!K7QtkCme*%z zAwPG2$`y@jw66f98#n)Tc`w2!NhEV(<}$+DjO3yxop;e=xQ%bQsx2+kN)znAayW6$Ci4qlA^oC@uqVxC@94?~JFB#t zbTC$N#^8$9-OHxg9m?S1`8#T)ET_vMMzxja^>TBWPVXttjkz_9)TmJM3<5VCH5#Md z8h^YiZgy#93B@mf%WUiBbrG+F z4;Z|sM-ba&`ZK+bYeOii|R4-PiVHNXH+FB6*2!InG{fP0yA<503J#ROk-<} z*re(pQVIiHP7%pk8i5N!42ldDFHjEc5*Nj#@f}fyYvLvaXu%m3ow*%!j)9RDtFd{^ zN;wiMdSnK#*86b&UzRKyQ&{-w!X-1HBlZfXcfBwCuU64Z$gcNcD~PmT{W~Eod@OwX z`qnE_2gv01hI~${)k&pSyit&!&+uBMx^ims%5e^pJlBQ?Gf%3w=Wx8!UPH!DER8Bk z%AIm|sIKnbiS8n`&%OTZ{y>XP>+}bPWx4ihTs+9vd|F;LeQr-EaCpYFsV>jMH9gn0 zXl?)4mHFA(eATx3bxo@uUA%&DsRI|cC$G_}(F&OA+WHk5ElBf>RSTFI)7Mwv?s$g! z9u4kp&*n9wdeSRgPGgCy>rnHsxKZk>D3m%u!f{r%SPlz`iRO!^Gz3wo@Q~UKASs|p znM26XjDgaCXie_?gU|l{;N{N*g3kzh(|>vxFm*2e@SoBTkC-2kxccf7e68T> z7tWjYCb2(3hP{!_5k7fy7TMoVKJvaHpnJl8NM(n0kkb%NNVF^!RizS`MlkbYEY>ox zo`BJov6a(xp04vSIK>Ni=>41)8V-i1I?O*>+L5Jnm0y=NY5M$G(?`|l4ai} zb05i_8yY@+(##2C{mY-fWO=68P?#bXkXFdHkh)j>+6ek`gLtm^RV`%%XTz7+D3Oz z8rxE?({WRsGFyGT%E#D7Ztkk}8qs~&YcG}AstY1av4oRYfPwxyTz3>nZWiOKLHqq)>>1s5FqT!cnZjT$io>v){#=BbB;qt1GGS*1GmWAB z&%t19AH`Ow2g1hGk^bj?K|B~zMNog{pv-Ih4;cdn{JA;*EpNa;bUhgw+xPG312QtX zbQ)xGi=-T*fK3#~AfXu(mi224wJiu1$y#_nBhY* z?N1NAx0fjPJxp@yww1qs5r~VnzUy3`LjI(8{dQJmaFo_hZya`>On5()3JPHE%*d3Y z{4VAjBJkF+(2p_2V93OblQHR1l^OFE#d9IPn|^6L{ve`*S1S+xZA@Ndyo$Rrm>bn( zdAC+Ca4mL~b*L&!bTzu>o}2&j&dH(vBX;YbrE=jLQ%~hP2g?8Wq*^x3-eYendnob0 ziHBgAc9G5fXZ*ve+;EJJ~ zrU!<`Y~@l<3P*n1t2Mp}7=}V)`*iTvs6`=Jt#jIt(Fbxm8m|M=kARQ|rmvt0%^yj> zxl-OAVHRI-ODd@`$*MX#s}Qb~Ox*V~NX`Y*J_Dt(3m;`Vur!6dL3z6sh6)Q<^GFj-iI~arAz&Pyw!emlrWp$-_ zp}bNZYnAnfmWI4V*A)qGL~@D{tON0#93{ueQ3{piG=7I=baJ47K*L2e0PUk^v(nN_Hq_^KsVXqabL;TRA*y^fdwtP8U||3%%{Y4=vh##I+~ z>Jq{W3Hi91!VX>HMvtX-Od@aJf_+YFO;;lC=6GfYfL`VD@$}&MZ5C_I_?o<%7u;d* z?jGlQl| zhSFC)I0?YGN!x?8q>fL7>&Q?L2@6Vzz_an0jg2!4pDI-6C@W%YGFFku?(d6L)P@Tm zj>Nq(RG+Q@?h7HSFnTd&t>j9uqcNq`_YX%#E1Fe(MvxfwdXto>Yv)%Qey0j zk+MS&10M;|?h;B^q@2af*$l)Kh9@n~*|<94%MXPs-}ob$_SRd%rzHLvdtW&H&9$p< zC6+(Y6s0Ni9qCCj|PMBy5(bAJooxH476d1n0HDI&v_AL9~=?{dP|bgwBak5^Q=lfjY7T})HDR;6N|8AhHZu`6`CCI7&a z)qZ;IOB1!)=&Y)X4JU9L+Ftk%#5q(#{Ir)LzB<#hLZw+Y8Jtv@0N+XrnmT|LI?BDrrNiJgMIV>QbpV^ul?g6 zS8sh^IPw10qTy4!!kD(tj1x5OH6R%&dL!^bvZ(b0`Z~3*m53liw3!k(9jMw@VogwD zn@H3IxCMnJpo$<*fgcZRqPqtR4puvWt?OVfJUdEYbg*)*dVQVn&pJKgw53IB*Az>Q z!m+aUc)XqbHr`%_wNov#Lt7uNf1VbG%bo9c9%e)~n_b2)z zS*F+3)#>z7X>qaiHCzmBsXI)sS=LqD66%%`SAMuG-X1S0<}JeWvhHw8aj;6~^6Y%! zg`HUrUF8#JMwUzm#~4G$Q(8|MTd)rG6coo((N;y9Ev+Y7O<~bMO{+(&Ct6{&qEI=J zXabW2{5n5fRj6f34-Jpl(5VMf5_?diiGLo~Xm~xJ^KuTa7leYkg8XDY>B{`R2?&O7 z*-hmKNxqNzU5YGE8n~L9mU#1WYqFgDmj~|oQtI%L(xD3xn0z=?h&`(>c`^FbpfQ6l zKqMbK14|KK5aJ(X0}tWj13;BpA_Lbv8qkkmk~6zk_O5hCTzgh@jalI`n_T3w-Snrs zX60=w$e43%>C9nQ-KeEYMhPF8T`u#QbzRGsjV72(-KO&Q*KIPp+@|$T_xjNYUb^pG z13Mj~ZTR31CYuv-sfG-`;y^)vdyJ51#tr zexk0e628upRT7j{d<|gw%BhSYB(<#F5K+H9`;|;8(G;YFn9Dfnt zV8AqTc76Dt(w~#z>&cBTz4THSV@dy=3>O}w1vfEf>}eIiD!HEfxIddYjD5?5t8h#! zbC`Jl1UAb4uG_or$P}Jg9n!z3T`P$1kwmYf6)whn3|Z6D{v^d;Ln4l5#faO%%*MIh zhqHFXb6xJ7xbUxm6=u`@8_gzLV&aBlrHvc!eqdvJ)8oeywHsO6&>Cc#Q{9LyHjpu? zDfBm8Ow>=YBdcae)7!IOHZcpZ8R~xwtK`Iw>sKksKCO_wgt=p@dd{M$C~Rst#Wl%mQ`*2euFzN+Y!(PRk?B*lRc{ckhUVvz~+7*JzTDEd29}5?fTlJ z@I%r0ZRA!qSXo*DLV{5ZZeduDRGF_f9rG!(*|h`+B*M&K3tLv7H@sqDqSl+J*N6Ar zcjWr>82G~Yu*{?OI>J`Jvp%~6Z9=K{wOcinwHC%1pSI~nGv{1t)$45RLakM!1VV^t zvJ7FXL1$%Sdgr6P#i0Oew(E_iyf$Z+o<)#{FX?u~VvI`n25*t;q!8d4Fr4Rl{muf{ zScM|rO-KisF~bsy+VTyRrVgDVKH<*ia#@8^VJerY`o}qQedPree7=eesUIj3j>1Ku zQ^6LR%V=cGN;A+e=?!Dm(qiE1>6J4&t`XzQKY;@+mrO%eB?*8S8EXjIi3lG@8-ag> zT1PUyOoY^do`PyPu*(Cd0QMT30+cUpM-e#YgN0dcPkh5s;qSsx;p5j+(dw=dU4TaTxMo8oD!HI zMyJ&oq@0=*TJ!VWW5ph9nGFq{NkVGd>IfSs$X@gE9m3y!yLiPPh`V?4 z-5ZvTNP3j=usLRTPad;3;u-1E*oO^Ywdo*6GqAV}$Pix4lHHOu7!P!Ca7F1Spvpla z0tMS91Kq8)q@HDMkg0(C^szET?+_Rva0t4-t(@ix!WmI&PEX)iFtD)+AN8mJybq8! zWo3#2)(BQMHd@cr5t}%0a0R`4ybbq_*Dq}wzh?3!A478$3;qO;D{EIera!rS}GJvcS^Py>|TYrTPiKZcyK#3eS&(>4A)q-m!fF zy(9j5n+{LZ;lb982@3=WJ6tv}rlQ`prcllYx1v z{)$s4m`Bp>+*@-Wp8e;!`NxC;rdBw4OL=VTt}6eyQD4=|m2%GQ=i2UTopJSeoiD5; z*Y}^)rVC^mklrKS2kLJD14XwQR2VO?hz~P+_&76f+O z1UD9EkQx{%tJepaAP{f>-C3BDO1@-_TUy4DVsc!kvFX&TP3J^69sAWIy7Fe=B)K z@;)T7(+G|90VGg=rX8Fy`$I0GF`k2|g{5HO{XcE9Khr*buKk?5pSCAFoY?+EyW{`I z>;GTd=ef^w?lzyK2BA|Dx+HxW`k%AxKmTbh^-B*tdmMuXJ0va8f4cJ76T~&zjFYqh z{vQ@nIPiWD?OakUh2v*V6~6wt)d$ZUFogH$XID>ATA~b}40HBDfA+Ng|HH9EE(TeI z0iH?E_3=IMBO?Agve@K>o2wGOR z(3=6+y(7HS|GWsTO9?3vT310r^Z@sVAJP*(%3$j<_LLOtT{`HWrHE%7gPw?~mg+r_ z9jRUd_&&s(0kH>Z)Jix2Tg7}aFfs)LG-*tD$kEtG!c;RF5T_uYsUwqWJ2uo{*}1+( zxMy5v$F>%6K`viKjE@EC8*`h#sBcWSKf3hpqhxsPq)5&BPP*JcW_ONj+15c9T&!l% z$QAqA=yGrR*yvSD_O*{*z2xS?XM|5z6x4cD-II4sIQHvR$3`xyY2Uj7%eH+h=C2;z zzHiB@(d{=cfo(5|n65sINi;ST@)?Ywbk<3jGOvm^W%`!S$Y(-G))Zp$XDlDT`<~t7 z*)OkoHr)Rr?N)3&{OmQUZ*IQ%8+DNhOg!rz&$iI-kjfA8{@#bcMJTGBUj z_iYgVXF>Nf=|__Z(9+4@JW5QLzIU0yyJT(2-G`oP>%96+chjaR4|iqVwRXh%aaGQN zZ-_4__CGJ|KY4hQRx!`dIsPwd0}_psc=!Sa*}EXAng@P(j2M2DLs!h8(kW9DTVg{b zCyPoM>Ipk0>>!&i?7eDHw0&IX{kN|^@9>iw7-jQtvX@-HC3VLw7r#_@xvH&rnM&YV z79vRhcR%)m3D@-hW5u#ta>|xgj><6zPe0Z@U3lQFW%IK-hAGY4AGmkxC3pNb5F;0? zt7s(3PQ0I}Yl)nWGWcJjkOR)3B`9(;K;?O=1Hi~aHCV*|4!%Qq!Ym2W2(tjx1p^O_ z%O(=pN~8r>y>Qi4FQj+un(uPW?`-h-Zs@RdnX^{4&S#H4v}yB04{hG`&~D*hM}!gT zr?;R)*DA-ba+@6&|HK#D*WtGz@tjzwsk8`KFrG#+`- z5LQc-7OHrJ={KbBC}Zi{(|$)$)6f=07#CmzZ!hm%wyamsuk5Or?kFp$S>v#m)^=IV zU2K2GGjgf|bYX8Tqj_c!X9oMHg(OF^ZJinzx&v$*9lLN@M`iJsNIF$**kVT zzjKEKY~!aVNWTE)Sp%zVKJ?@fltBt^XFv?`wV*&*UC@|W(7P7Utcr;!uwM}7prNrQ zS_7aG2}e!PdA&T%4k|+cTm&TvHk_cqHNG5Dy_Id&F~U^zeU(h72rwh_4qaP+UXhRG zo~eppC$ejr2eTG{K)#HpqEE z@fK$SNBuA-QrH+ZL!f0;6VxAV9ySVLAjgqrY5Ml9?1{;YU6Gb3>+eS9g^QHrKFh_1O$xC6bxt*_Sv@CAs7DRfH_Dn#k5n z1@u25ZbBZ&f{t=rd_M^!E6RV3_YxHlOox8-$OQcqXO@^B0ind_8d&nj0plnk%8*0o zbA*&cC~-ziWY#k}QCj$vDdK#V?85RRvI_`p!;Xj}7<5E-7=Yp?*PdCVz&Vc- zBEtFNV#ruyk>moGM6oafY*=FK5rueA$6$E^r8Ev_ury07HK8;l+7k!M0VKfTb!14a z1UJw7JK>_6a$HtEYx|PF90WGN-4pzW@W&f>7X=+M@479-_Nra$2riCo5+1z&PrWu@ zwom1`=-2y6{ydAxll#&+ejw74Wm*wX0Ymg2Yg0Ya3B0 z3wwPz@^EvlI(y1F&LBceBMs4aEuh% z;i*4`b&}7$ntt3ToaYt3@RCBN)l2q!iNTA$XTbj}6%uZxM2i`gX0)#XW`7)Fd z(F7vK2uy{5NYnCC0Q}GH$gCqE92{t+NJ(NsY%e{|ge`00+^x(m(Z+~SCYJ7|b0Byx z=twZQh1fi+NmeZGV@z>OIkYt(hcp_nDAmydiH+U?#veV=C>5X)A{vF2fa)r&NkQ3(-heM@gEEYzonr^c(YK_IBQTJe5D^-}y z3aOTC5#G00lrlYIG%|Xba=OW+l4A|qa@9dd-XTCLuy zCu%j(TXnB%jZPzxO4Wc6z-|u6`rNxN?Ek06=pNtm4DlM`l^5Q1$5)I>snsge|N2U) zDLclr>*WY%)l1V)lD`wBOr?-%$l}x{g|1v9?Fz%iV9^;;I{r3#nAUQ)exEvgl${dFuG0rse z4kn2ce!=PJJ1fz5F2R_DQ4^DxIBX7xGd7vQPxC1g3bv*$TsYXo=848Dv!H!b{R0k+ zOmGOb^8(^VZLl=vpqfEDhItpSjRhnNEuuhe804@&635@D88L=96vkhecM-U11vsLN zKjMa^>m&eO0C%NedfQIcDAmFr)MOToHA_pt<5gN+b*&dc+(gK7AjFs;wbyawo z)%KMgMOu#AE}Gcr-6?5w%-t+p>QR$Q^+_W_;bNrsq=Xsc^va5@P_94{AM@L*g_ANh z;grtUynKa@Va6}LbW_*fl9~K+`NeyXdnQt`imwg+Pg;F)6_T!}(@*rxML`pvv&Wj+TU*o7~HYmz= zLDV=~8vogvUeI#K{*;Ub@iXDs)c!kKgx9)f@eBig0U~9tUVb&hBlenM_*vb*pxW5f zqVyv2k=d!2+t~o3J(=qfrr2(FT4)|&K1;#))9)*MAj5N-$s<4$p6zd$dKml5>Vbv= z1mPK|rrux#`v&PYo2d+_D5wp%5eh+E2);uT`?Hk*Dmcf8dAyRxOLIt4!7l0`!REea znuJf==W%L;pAb%}TG%1H*Zkzuzn~gETe$F6nMuw`IXGZ%UAT}Kh;z}R{W25B;yUX6 zsFN>+k7zp(u|(o{lX?FNDuMozUMkiA6ifKGp`^g|NSPghL!c82rS<&zcg`ZM(=O}C zX&TjDU(_XBJ(cjQ*Od7x>U_WK1@G3`Qe9)#xJ--EuM;~Eg8r__KHX2fQx4+Xf6+T( z2#UiS#8LGM;dVd!3S6pR(npOSqkES^oc;yRO^`yWkDijk@k@IlwwxL72kkOJFoh+M zhr0{U4A2dLH=coC%g=w8ASGD`Op#&@Fq&c*G=Zic(>gOCMl-1taDwzdTk~JXz!Z`P zF*_E?uX*npxn)*rlr?Zf%=N}0{lJ+&1ctHSLr$Jq1FAM0?{lTKg_1t$Uv zBW3hkVWJzD?=tPL64_~||H7|DLBCXPLZ(Zq2vHpf-fn=p^iVp{3vE`t$hs0m5v7o& zB{%^(_s@P=0wIUyj=T%$S&)q7E2qvD{9vt#Y?xrD`Pr#Z%t9=POLj4>7Og_~o+yw^^Ow9b@)&2% zCAb1oXQun;`x9k1QKIet+xJhvb};1^zF8fO9mQB{qrP*5BO-jo4@vvOI%1#Lya7{&d48vLyz?3}H+{eE)=e&kL-c~re%iXYG_KKc~F5+@dTDxx4 zfmJ(iJ9_BBr>bO*rs@Wxuc{=T{GZ$Em}j4}T`GKit24jI5MO@P2jI=T;FY(9J;E2y z^&I%ea1uM*_pf7p`!^F#9nG3IW@7iODUZK7;L{g!&L@zi zI6P=@hVEwI!;n$XpEH^GVA04J!mWR1rU(xT5C86WY$?{h5gzO$dQ4tlUO`5t@8n+k zo$xTxr0--)1N|>q@+|!?1p;g-R!{&-&IM%N`=Kpc`rjeD4!wWzBab{X?R_#2^pjs~ zAx!8H*(KbVn|?3bmVQs8VFI>n2KkAY03`YMC^;O(gVPt`*Fc7ym}!$#6~k1Q%Rttl z*blLyZ6fX-ehw+k&R9aFO?sHP&&!K2(FnC(X1)n_WwL6?mt6Mw-JFg+)rwHwdp^Hl zs``!#XLODr(TDCL_S?zHKmBUMW%Km)>ZZ;_XJLt7cAX>?j-E zUYR?pp|P!NN&UKenErx4th?h=qWs&P7d&1b&0TR@)lElk6+XXRY8Sp-w{w=cP212^ z9&gTR?&@mJxoY*=o#!o1HkMWn%M|ROuPTnk1O9i)y-A~L5-2|>Xdsk@S1GY20KzCs zM5V|hi)A1xGiH^Gxn+5fz#z@MnR(&gq5n*uu>IiEUH5c7ed?>H-R`HmnMSf9Q}6=G zq>5!{Ki%E^G*Ih5ffUwahnt>CuW(Ss6~VgVm|vPs&W=udbu%CQjA{6 ziC_{jfE}X|4TFc?Ps2B;>6ZrM>A+I~7!h5e3>AoY7lYjkIA}ek)?%;RW*oqlo8*6f z7Qy1NWQCt^8(uQM6OinvTjv6uV0M0vRx>|3(rhAt=-%4vkFuO~l-oToughfe1t8UHkOQTpF4kRD`LB6e|+5u(v^{W#I~k}o*RR`YMNxRWGzrXH)680 zL_$$O(C`mR9q5H*5q-i2YcZ@=G>TCM3kHxtwsIED45bvhV?z@}Y=#UVAKEPGUMx#+ z0bB+H<-lRl@(`GGv0KDm;)Db}MLdf(1%R5*1j9h#rol01f@LTSo?UoUxMg9LC$HhU zcMJ{bzl^oIDre5D^qRVYyu50maLdt(2E#koHRP@PRIB~O*L1kDyQpkxSy6Z8;U?cF zTJ5L)#>3T+$iKURM5jC!ODfChttojbXmuSf?XzWrL{5`p*N{$coiWI znoB+ueveq0-+y??B_EO+#IDqQ_|Q*ukhzW0SMCiImsI{LZ-SaJxNFM%hsaHb{1p}M z*-OtCJ_+3W3W)916Y_plS;9;ioiib4^wiGVnv7p5m0uZ~ZtI*X7ESB8t=agcQu(E^ z`L+%w(#WVLre)fq znR7$!ot>e`T_Yrdo%hfB1z%-qT$6QEyc|2p%~>48|#zg`tjqsOT!yIp5+rt=IdBPbKK5`=jJyB z^+%eLTHa^Rlj|-RWkDrEHt255c-whUEDS7^_m$^s+>R19y? z`@uwlI)&{73vrf%Mpr_D<*3|fDWyLOL+SvlRUAD1mB`<6=uLiGtMn> z{$s}8dCR?fs%xq@Y*x2od`NH+X)?Lu>NK^gr8Bbl=(>0Sk@*c;% z$1&4d=hbzWc;ukYlUgD@(!WX%>MFJ4C)TFF99da4dQ^3lb@u!@?9|$>Yc3%#y`Wa+ zW^aDTCXYmY$S&y3A6qFLbyO~Dzq5wR9)G@@vmY39#o@yKr}8H==S>gzr=<5ze&F}f zSWVBQYBB?C9#3_Y2eUUk#R=DL?XyKz=DJY_3EOv;R3MzL6eK4un;VCI7+OfxSnX`R^TYKhc{kv_@ax7yJ|`TKC_x6 zj4anVF&a`>3>K9h)-b-h%{(?C2Q)nS&-jWlNu6AqlxN@96>MHLuEFe6Rhu~^t1Mch z;W@dnEgNPhkU_p}@|&yl);jeSB)6t9VJWW~*)nT%6+gB~Tc##FPnQ32aqe=RIm_aM zk>;jh=5Rp{XP2I5w3>Jru}D7n2c6~NSk%K?ruP)(t~$t> zPm4U^e#ppeB8M#PqjcC4N2|fra^|Ot2@d8!yhP&y3fQPD5u&Ujlv$3VS8P-w4S{=J zEMb~UvU3|7bF*1TY0Qb>% zWIM|$IRmr#?H7?vp15z{{%N}Y!q+E0e13Sx*Tnnvjve2i{ZPBWY4i z_f3B#ykYcc6(*|?3$tuc3O<7u-#s~(jAmyDfwOmiQ#fo9@BaJWX|tndw$E}>%jfn# zdl|F2|E~kjkeL_D#4&-&ANX<^UAB};h69}+?Ew^0s1(s^4nq%wN%7-Sc41nWF^Gts zVNl^pK$!U9zI%li&IgMBGNn#0YkO_={3kCTGv@Lq=g&OUav4oWEdUi5i+Z;%BBpEi zA@VSNauB?CT!iAWZsB>#&2`Oor9*zXf>F+xkJFFhDy@x|BLOzW64K1vTjnfT_wo&y zENw~f7xci0@}qatLFSW4vb2m|l*2(D@}p?7twMiBvKB?~xd+KL=Qs{|3B>N92MLe< zn{TiVJ1}O0U1!^&eVy0B{Pg*)$B zvno3r67>k$Uns6^Fz*OO5H|rCC80KIiY^@LaUv))!AeSh*>m@uvrV%W(KMB$N9bkx zD5!6M*R8j|_xN$CB%O8qY#|HO>EHoO^7!%oUTP*CEFluGIbfTSq+m2orMMsM5rADi zOBpwCm^cPz#)2^Fx5P@bhoBBA&mKl{%%fpCuV$efV?r(EUkyv*5(%b$Hp>mUmWfXNs11uDEuozE5 zR|)R=%UMtGbm+g-bC-kp+AUH8=NYe{FOd@o&!* zdZ-eIIguCrrV_I<@2wrT2i16TGjJlO|I$$s0Hk zS9X1&pi6~V@`QNp-ho>gjl%}-k0;9DRK>dGfXm01hn0@?Gv}Cq2!Qr71d>OhHa?t? z$^c7171WpRQ!j3h z32zLGMu(A{7+M0T{;BGNu_?m`Rgc+}W(}bhhTD+4?g$+nGG90|Q3CmJ&Ndy<=;-yI z_J`>%KMo51+>t-O-ybjIIg#U`j)R@S%OQZ_M>nV2nOU8}_4{Zu!D7fNll;lz^waJL z!$e%n>7U&FAI>7Fv>F6B~0i|3=)Q5JAE;XFJO2j3kToIaVB2zXbyQnZE z(dgOLT@lxoEv`uV|8NSqT%(-NkU2_?p{!#>XH_^{)j0wVg^6eHIu4h_h3V%OeI#Pr zr7Ug~y#w@wsI8ru005!^HVDDenc9payEPyOfNEis&uDY}nKb~coxp5i;Qm2oXFh?d zhEbYsVkG~SUDp2=r8+_aE|C2Wu5o>7>`(X6nE;661-5jO>Fb9lO)N+P6fUum#PQ>_ z&cvlS#-p8zIw0g+*uOEpa8ZH@Dq@615NL3*5Wmv@4Tps#yL)dJst*ghA0`Vo6yDyu z8<^*X?O|c*XXKj5LasWp0LW(?Q@BAqX-BeEcff)W*J&hkBZdB{HiUf^%J4OnQziArTgI@?1AXGOO^WKk$=5m16h z$|*KrKs&Y=66IEQ!R7}y;~)8MQ}^V}n49`Rv!v6aIQ=Sum@x zbQx)ZrIQH1US3j|6^C5*)H#l)X!!;?=F{vJM!j8VCeV@68m(2)vKr%Z~PMQw{(FsuMxco}qr z6XO~q*v4c;U0kpq(+|PoDc%-gxSk_bi#8@K;ac=yl3AHC zbIpcH%!HsTcbZNaG^T&|eAKM$(8)p1YAuYBIR_i1CWGx=il3r+YN#J4C4RfJ8R3GE zTPyG#@%2P0j}8n}+8g?x%CHF5rMwOZ3>Zr3;Ew}dNIm&9DO@_mOW-db@*hGToZM3Q zzg0ZqK~hUc{{ZAHK|>N!ry&5c67f8&4fx~5-~J@q*Po=L1(!V4=l4apw@-;!RW6yr zsW}pj>v z0P9qg`B6D%j_ummwQ)Yvv3cv}5v*~Ka^&Y9e?C&VM{-)FzVwqD#vj}~yNWUFRst|Z zQe@3`*5l$4TiD%~%0*$``2fDD3jo`oj339Rs}& zqnj86MGcdHK2dc}96-?60JOsp1xRZYN+7H>us~3+yNF1KQ2K?@I#CGZIU+olVECxx zl*P^}g2s@7k8HbW-fx!9joVcOF~y^9EExUXvMai~XB(NZL?yfhEdD2azK59**j%(| z8M|)W8ll#$I&9A(4;Rg& zWJgx1I#GI+zzPovY&Z;g1cdlyTv$vCWGV%9p(#j{a^MSKz^9@jG#Qz-6rmLq_(DY+ z*oVSU;n>mytVpHjwqn_%mut(AAd6L>+*+kd3g0rwj;XuN;9NEQlHU+MeAoQDm>Y(T zUcV1S%|(%#=!6!lt$oSXo0%(%^NI_=u}k_=4c6~|9ej<~-2{8`39&iJu|#r`oeGfD zC)NOmpcyq)XrJ7&+9NQ`mh>iOtKPM0`rP5Rkj0zjS6v+-Yi2KOb_6U|KXJ(SmZuN( zSlijBPl*@f#kOfbQ#UkPA{WsHNoe|$FcQoIK6{;HpX4#gA0!`1en8$k2kI25u*f82 zExZEX8WogD&H?2x!Wh9*kBoapaD*8d)D>*%G+HVc0BSD?XGS#>56Yrgi`z;QtOdN1 z)x=U7Ehz<<2=-^hVU)&8L!#+Ntnd(Gs5q)1id*FaYXMsziXoN`vKW4gOX5^-w-(zh zR*TF{VDJt~k*pVxGflx7H{UzVDI>k00ROHuummRZcA9Ua;~ zeg1M=R4RJC;z3-7z5-k^i2)08g6@mbJC&Zj3$9|N*TqgeBz+a}y64{XM<)#I9DE>I zAc#gM`sHX|Zd{A9yTdXD6I+zl6L7tQvUWzm=4PaBocH9VW5!&1Wd4n*ZPRDmzG>=| z&6}r8owjwx^lhmd=O3Z_o}70hGe>5Su^x_>N_iw&;^ho75rGs%`~z?(OHNs>CZpAA zG?6=N_!e@B74nVAc+wWK*+Q34%p?qIqRkzkN_rNGP9A{|J4>ha*>zs8-|O*v@A7yI zPMT=Mt$VOgYjfDlY7oYF3pIA1!>n=mJ^rn7jmA_|wzX%kH&n%=z z%%6uN`rl$%q#@FnbsCLOiOf|<{fb)9@Ocrt!)UTk%<^Sc93cnY_Fyl43f!LFoq}$$ zjxBCH_Sx-b{Uswpp%L_dbCcd2tBaZK0V%^Nbt=2oZuZkvgVtt1)Q8Mk>&nh{)t2mx z`Ld!WtIn^^isJl^Am`?AqTa3{_K00=*IzMssda<9uV`M^YR<07Hlscmu}0`ah|feh zzVY?218?%t(4j!&i^zC6Oo$TH+0zg%(?`aEVO^jzBK!e()Wr$i7y zsX{nL7IJJ2jE`r!6y`EfL>lZ>qAwYpj`of??RBC<2AoK0hKE2nC@+M?O!TG%29Nl_ ze^M$UujuXK|K>F$l_3wJ&T8Eu>6b~9x&DW-vq#OC(Vk!9ZD=6L?1abSvUu!)?8>~F zP(fI3a$AdRIeD$6Nn#CW7uVMpA6va*#p=h%C8HN~)K#3q|Y|^eR zR~AK>-_x5el#>a^j|=xGD!MD$D}{%y)Q>DI6CS#V37t|`j2v0PeTyX($KekcnBy4a zXx2gxbpvG;fi^k{zOR=hf58aOgZMK99L!80X-dI$MF(SyYhhd5Rz`>4l5pmSWPbQk z#4ZQpvS8E_j0R<(@--Ps0aG$-Iav2mhR`6tErHW4fGLXuWDxnO2S+DNj5cwshxnhs z0PK%@nexFxL(qb|M>8WdoqNSC*%=*I+<|e@Z$ay#|7Btf5-y0AMkfl9!IQ31!a-2} z0FZ#O7{^k?wCJJ}%iwij#X_Vn6!#52CiD=JX}~xQqCVOqrX%XZx0ZVeFim3P#y+Ik zIJ*yF zd2w=HzqN6C<@D{2OB^jLdoEZwzLU8@WpLZ0_H4zb(PNPXgd5%U%K5^(Z@qQHb=UE) zW!lyfN5b*8X_=YvAg!IvmdqZna8x+{8hGT8_ zR)wlYT{m^zcIU;85nC>*m*wbuptyB~JX6m*f7Wt#!s7JBqec}c%12)CR*ipH%u`Fg z_S8fc7Ybj!hCekmL!_C)(|& zY%zr*;3?1dTV@fR7nUb%`@L~RP-j)jW&$wgNw36RD{xolfbbR3rB_ahCl0_=c zav)S9Zttv)n}qpNrRf4WY*^?0h450PKeo87y2Wl*EA(K&Qz-ZC)+=~s`F3upT%#mQ zD+W%{to-*=h#u*r?j>54(1Y}eCSnR&aXTA%|3_0XwXqD0=St`-CBPd^#5lefabH(R z_Gac`OsG`)<%4uFFz*gXoRA!W1u)5q~4m((-dPA8D<{IR3#ij*}=vm()!ss_8(ruR9F%d*4&kGb~_jH*ie$LHKKHPc(_WG2bX zg!DF<1V}Oo5K1V45Qx;!JA__D7&;0lMG!$SE24;s;@U-w?%I`AS6p>1aaUd4RoB;D zT}U#Q@8`LbgrK29ZNvq?a;IcW*mv@~9S511Xthz~oXu+4 zFp$p6jrK_U*x$o~PTU5sSQT_gXMIY>}9Qzx0p<#K&)cJ){SPDfezTqimnj+mM zoIrj5vx-x_$>tH3^EgE9TtV_2qTGct357-r#1Pucf4|Q>5Y{|Ec>yy-9(-saeD)}0 z8Bs~-6G@Mg%&;Iprx4jMu;>ZX)N?!1%3AVNTIn}h6~74f%t=)pEme~m=`I$iHV#i` zq4eR#Y8Eh9nzSf8E zj^v9#kVD9>L69yyLSoSxFyj&NKv#yS+-1|_e$EF)ST}g->eAPxubJu9l)71?N=z$E zn+EMX{n(BDcWRU?mD-M;?kDg9|A~(ZJGY=dgGd_TKV* zUPiS_qv11u$&00@AEE)04PyFH2U23766Kg{;f_L%E%x4as~g|yh#;nrk2f{(%4+j6%Dy|XN}UTnw*;`7TrGS zSEo1sY0KE{J}9a*;tFI4;8uxo?!?{=Re3;q|Dekg{?pTlY3T(#LG8@;Epi?|IX@p% zFekW+^VgKkziUdLo=e?B&MKi5{E%@x+ejxll`_ zMX5L={cGaKvvJ{DTKQVQ9VuQ7$k)opW`8oNEhJyt5-pEX0!=l^7|k+;RCMXup#~(+ ze}@8odR%~fk&*mPIih+_w)F6pDXZ5#GJ#vyr{hWgwmK$A-~Zv-vrBuc`j?a&dl}*? z;Y6=gOsuYGi0rs_{1fZLqq%;??LQ2i?-+Pq`sc(uURxm+_*1-96Z@o5ASBU-XuD*0 zqv^>A)#y4jq`|Erc$GR5B3Y^1$XP1oGqi2BlMiMTI~I}lG&5gyha?&Beq;pe{EJF7 z^3;KzciE=+(;b!Kq9VK2m*~n&jZJqrlG18(vTM^^cBel!HPe;os~s0TnIi9GcV3g7 zQ=69LaHP{UKfOghiw6ScgYqIo|6oLER}3l%)L0W!60N>*+|TZW$*7Z<5S!pIn5=Q} ziAiyBQ0O>tAW=RlZ?RBI^lV~$^z4r=jE_rjw7}fcB89qsO}uGXT}>bTzwzKT&}8-|qV_y-mZug_yK4wtYYKG8WOznTvzQ06iXEq-ZAZAM>rvNOBSoNAMK z;hpe4&d?=fi_`LG7!Tv|MsD$s5!}%%dUe-;eI-tCjt$oDv($L1l=b*`f z!p#u-YLC+XVAoV3&lE1;ME`^*77zY4H7#8uaQSJ)P&-&B`n8?`g|%xr)0F8+=>-X_ zuFsTeXQ_X{h;ZGEN9Xdw#8V5NoM_Ya%~*2H(t~%-Zd#V3PIdH33ziJcn0Ih?PcJX_ z>HSq&y*H85>$tRBqcLq@u{O!Jv{q$mY)DcY6MMyry{mWU?w`4GP=3?n)7kt-7cWeR zT~Isd)bcqe=B>0(?mfP=zdvCI_gPPmFuC8$HeSMxO@>uKaYg3cG*aw)DD@3&xaG_O zSO>5;Ih+Z-1ki3w2zUCiMpwM-6)UY;kZ&H+3MA0?N@wCOolH=NOn$fU&=qfF zQm1=tmnZC=D+(jie{%7_G(gdpv9NX%Di?+a7(3R9J?r<+1$76lu_$2+EXp3CZ1tx)>pbH-6&lgQC%tBZt*^OlOamX;Y zWXAQaWCe$f`PcOy$y*AKjp@eEc!Gti-R;R|qzh;E{Jp;7W)|K&YyWSV`b@0U;Vd%f zpwXVZaq}4_KNnA$a(~5CDKq}g4-mMz1ew1cgH;}GnMJ-tsR?eY@*FASACOl^GAv3p z)OTPGhS|T%o@^zU9|GcnCIeqgcEQIkh>iz7kCYgr%N2~)sfa>?<&(n2oK{DteOQQE zgp&q|sm_kM&Qx)b=yM4^m+vo$wn*5Pm}uj|Hg+EwgChzo!f~@Sr;&MX3`;nznd4-- z9`;`@hJ~F;Nlq#3%E{ptrY9z*Cq~9cj)wy^HGyz+$&GJX#9kP_qHo_7!=>Ic<#}N{ z=9CMV7jg(&fMRse73eEM8ut^!Puqk7C5I7!c+09$2U5b6Bl{G-KMu&==nDGixVjJ7 zqAcWfu5e1f56GVLkBvRH8B7Eo4-3X zn=LI!+hpGKf%Ln(e~{))dz#K}#y-nG@jcr=?Mzw$_vh-u!s@~?V@4OGrWM?D;sNRH z(_P!M9{3-&Iklj^{%+}aA8umW_X^VFJ(mCBCh3Rw3Mj5Z2dAy?F&EOeO+f!&E@O)G zP76RCQ{-6b98?WXVFgZDR8y3^oSd4BS2V9+H)_&C+AxYnLDP_;!X*R?a08@WnT5vO zW5;3O%OLcOW+gOA5GDk9;-QDCE(Z#eY8Gk>hqD}E!MK_yCvlF(mEXtlPb^t}+*c~? zbn)Jln2c2E_1n#EW8c*^c~;wqS({S~PPg7yT9srgJQ~;M;*mceJ_tFWM0$CtHzp>t z|Ja66NhVdS$tWcDFLQ^k@$$m;8nuTTSv=|L(?xDNE{gY}D{g z&mnd^r&qu75#E8LZZ8|*GfXu7O||NbI8LSFw@j6;fiY?F z2dN$3r`@$P-Vi(7T{|^YEFI}pvFFZ{_b@IqZ>S|dpc7pwMTu4*wpguciSdruob3aW zm%3sA*mRCl83KcE8=2w>#mqLxqCYtpEHH$f} zmJ15bbo7xgUV83trX)|T#|MT!`n#9P)G-#WqCzn0)qP)l^NknF)CPm- zaaRI~K-2dH{?#`0aQX+n0EDa&d_fZM%4Cm6$h#2WAuM{pnsx5bNQZxz*@h;g;ocb< zf?PFVkvezyRynt1bCdL~ya9pzjcuQ9Vc{*GZjbWB8&(yNE(EHunOyNqplaRr#`ZTFw{LG0@*1~uk1nC7&_ZepR2CIg z2HG5s&*|9b-Rl*H0+p2kX{O!&a7HC}dl7mPn1}vkIOnbpgHPq) z_et;X`;rBvGtwaG4E!@^At~n zEV=|`@*uL>(@EDb5rVqO%i--v*E5Nz$i2JTf^$q9v)s8}k)8Jas(RwQBa zL)qqWdhtwn3HVj1K^~gJpw+{Q#X?9pP6zLS;|aVUR1PSwaFf#RShtxrSr8iY{ z+BKZlZx&UBfS=0c&}(>~U&94>YpRv0Dvbj7G8fw$*(j;_MMmhfbW?expq7IJfog@zuC+)hx%PnE!D8%j+SHi zCzR!FO#dCn-@9R$$ZfDE3({>GjSZ^@)M{sn#b&d4V%0Hhgph30XxMZy*@kPNXAxMM zkN&PLUPCJY^rqB#3u?!J}DhkzR1Qur{-A8OD~z)M=Qnt zBjzCG)$1W?cOom6?h%Z*`m|DHtEyP#T^~MuTFnPwo;T@FGrdlF`3UR%)kkXS!jPA_ znAT4+fp_{WD>UwsKK(F@ZExq$5O%Z|`~(FlAIYVD_*nY9<9g{cmhk64SF<_Dh+#wv z+%^i5DD_nt|DQ1L6tYpZTMLPA-95e?g^z9G0JiYhrjCDZdQ5oZ!BCErm=mhZ<{LIW z!)CTsZ9aQ;bK1k~9>Oq}Y&rd+^kx(2&2_L)P-gF5=;4BbM<=1+NaQ!C9SE7sqVPs{ zL_&%yR=~g6!6P}Pl(N$HI%|Am6q`PApmc5I`9%}Uo48`>*iz)on3iskK9E8yXYs## z_SCk+3)qm??6sBR+|^Q&^z1cb-(XW-zoBy6;>feowS&g7ja={czHB;YTQOnQDybZa z?`;K@qn)p_nuP~9KhQ}Vkmu`PvhOcZa&prI(?LH_aceO=)r$+=3{xGkEAnxk1YKuw z5aG#mNX`!BEOx499Nx6Xdf-6o z^Y^Zuv--htuiSUvcfsG^eDI?Oo0qJ8bNQRc?|Vg9)vhibfAh`bON9&T=gw`vtF)4j z4BxeDcn6=El{$ZZ3co|R<#1I;U17n@d0?W6k3NpMdA!U;Qv?=djbG9`|Kj;5j|%$I z6KO@JEig2G;Id7$x#WfPsmnHlwy}_K{A%0c_OI@0PrK`@b#t`8T0C=jHp_T=f5$$< zw)>8AAKG0mdnA<}03atUBVW^!-A_xYPTrm?Zy&(&uDiba>aJzaBYbZ0ulhaq*L@xP zt4ch71kLrM4a#L%LI7>2JZ*${lLQ13%GH*QZ0`Yh?Un(xdjS0ThQWWg9x*8sL7iv8 zk983um{!7@bv>-C*8^vCk77TtFpewEV?>bZhg^^~P?_2(dd>OcAD~5@J${susOJx^ z0=V<%e{{ak9{iaroB=wEK>wfo5CbDqf0{5D!p)1Zfhi-k+n)|5qiALTI2{Ial%%{? zDmpGi)Z%SzFLC?1V{I>uL^`ABzY60VV={g&c|F@WVvcdnD*RS=t~)B1FxygQU&?IQ zxV+u|xOXYi3|@Ks+u=*Qp6m5Swr_a+@eLavdrW%I-?x8Xf76tBKDpoIq+m&Euy#bS zSGqlAuo2vNn#N^_cf=$G10JZQc1x$&s7n55$5iQkG5zJ2rFWJty}8H#n^JN;hLoHX z`sqD6DJeOg+(|hpIrN*Di;(s=(|+_%x^KkND-SIlk#@y1@%+@sHbzU!u1o8s0V1|N zzpx@h>&QyZ$yG5O@(u&TtT!|AI$p^k&lb)1Jo?^JjK5uwbxiORzfy(;hx?P@JUQB^ zSY|XP-`;xkXe%!rZN2^WR@PdPec|2gii&LZKvszRE|kR{$gW`9>D*Deuxas8p``6h zRz*dY*q@fa`W2RVBk`f>pkMD{Jr2|hxoTyBC`To83q)1Oqd_b{yfC)Fh_5RWNLu;1Ip0#Av!Ma1gdE@r!@79a%M76=*cZT%+ z`YoSqV+rS0ojT%QLgJtGOF{1dM|zxT+S z!3nE2Z&@`V_}HySo~$VolB{+^Y@lKOvUj$=&P-!>+g+-XuAkmG;=TH&U%;jH|SFgI`+P`8dF_u3_ zmvq3r+u`L-zZO-SnBt5&0YNaQ<9+;H)y0*Tc&Uy*Fwymos|=p&j!Syv;3=-ezC2iIM8-Uz6ITRz89wPj@`WoqSFDhFiqO zNv%>FyM~2fsp|+?dRsa|Ca4F(7LO42@QTPR?$(YDUI+tnGTiYO?pAq&g=b0%ORl*? zVY3MebFPI0egUGPVf*iMJ}6_?z`$wF4R@e)UBp_M*)Lt zRET+5@AxupZ;)ZJXV-q ztVTvqFvKiI`9`p?vLQeN6&?@an2e3(YA871UDHi(_#kw^keTR5XFzTV>ws<~y6aFC zs$4u5YHXy22sbhX$7#n@Pf;bRrc{psUJCx{@Sl$n^*Xpe>(g?qTD>ktr`K9@()3OX zKsm%1o-Tny?;U$rcN|!~SCf=8GBEBP2lw1t<^gH$EZ6+L^Ici)v;pR~o>L{fGpgd6 z3=<*>LKGqu3UdVlr?zsO70@jf4UaT+9(BChrb5Q>xYQINB%~stUX03ygB}68Dow|+ z)i>O*x@^hy3#Y_?5DLY>U!*jne0PSoyxg0yyF8<`Bz@$FPdw|JZ=!h=S}?dc2vdH6a#b?oX$O#h8f&HB~XrkD{U1~xAACR|bs=vIRd9U6P>BO#gY z58pa1D~VGqt^de{7#d$}#AB;oVojJqCx5+k)9#yIx$ySV2c6OjsWyvwUv3r@@M0Kh z@hf%i?4Prq**;XI`?Pt{iv#D?e!4Ni-=!H($X*C~n^2JC2xq&TuEaS@kc0qp&V3aL z@$W_2_bf_wCqtqm#XB_jSE}2i{D%U5D6QaeN6<{@fp3DFd{LoMgJ%%T3I;*tf{B9< z%D@_EHCU)f%)8R#gfvmalyIH1q!_;T_3x#&?_a;RYT2rR@mYeH9N)XKG#$}Mc~dt& z^Y$|vr{?j@m|oi0J3d(yvf>A>T2>{6k=i~Asesn22{0(d8|7SA6*J0`lgnmQLW||r33e72nPH0u+Vy8msqDTzhd(siII)*BiaTYC zPq0gQhxdGNA#-pjEiE)S^8)d39CYSku|tlnfi_5?A_rwcm4{z)RF?=7N0+wFoWr0n z#TOPVX=E$HPY6rzz1K>5Kj;#n4vcOd_{WAA-HuPToMaiNpsGw zuP%>XO*gG$>*U9@g)i5INQtb=5W<*u%c8M!fCW{k;P(BqO&IXO!Uk75P#n+?kPY+} znUbiKU4`b$_nbzf$|Y%(UmM+gPkQh4p5qk=bRA$2G&aD{t;`tGu~6mJR&yZe}0Uc-oX;o4ax2Tw8+abbF_%jM^aDALO~F3YgTeIm?5y ztG$5&f%g7|`cW5wJ_SSo0cgHJSEU36MbCGAjdfS6-~NAWj4?6yt1CWeP+Zz-utc_9 zu9k>?g|CC9#jy3#(U-4YL3ASX;n!HE(@<57%s1_gJ-?Rxt>oC!d4wMF-_(u19n_fJ zki(rLq>G3}hm8}ot`n)a*nMRqh`-zj_{i&uW@zHId0M8K19!R*Rh)1KEQT#}$8??; zS9+A~J^Ej^5_N-@j|LWLnL10Ipk3O8w(jw9=1uB6F|B0Xx}UTn>3%>nloDdrOQ6%Q zfpw8AGY$^v-hbNfJwHQ4sE1(IbRgZj381okfy|I#x&%#Ozz@R1;2~~;*A#U*q)V1! zHvHp&{Q0AF20ZYU{ps5~OngYql?4Y6o0%Cn7l2S#qp&EFnli(eFl|BddSqWdUG*}>I!WtblG7ZD5 z*mK~)0x1tD_<<0k;w)!g7_u;>D1bnWc0+SP67|ai)Wwun^t7QBj%4Y($KH~T^;`bN zzFM{BhCgjv@yBcA{?p^jOMOxv-76nNfa@La<9|o^qvJd?yc+m$8yb>tK?C9dLJ0yN z3XMHS+Goj0cdo~T4&@KJzk&mBTz5^A9munB|didgX&N!xjvh~Tmr(W(Hl?rr0 z#ABp&84c;7g;OPu{(fnxX9;mO2tr)($uRlxCZsU@3Pz#f(WQYp2Mg@h_d- z5O~*^BunpREq9l8bay=|bT?rj$b5=yck2U*;mSEP3Xw!o9SyA>vuE(K$K=n>qvv;O zG&vwbJBMF6pANq-di=ig|9)P5XQwtE576uyapn9v{J!Y%`_9Yl`qO!qyClf-Y^j{j z(E&_n4uEYi>spF~fo=vRAj`U4j-Oplp_jV_7xi&5apCuv|CIF3$t|Dk&=F;6rf=Fj zAzFx6ATYiXttSX&Wr}{b;}fFyyll0;9DUG) z<8p1!2O3B+4nHpc52T1?xdBm7slTo!l0*sbC$W@`k7LD>=Jn zR@DNa$-fV{r);hE3F&?Ljhlb2jLi3hR-28B+e4SD#38E~9uYn9L@PB#E9Rk7ETg-9 zq6eRdzNO>qpUkWBw;}ydl!xr%&uGF#9FU9aDy+;d%0EQ33|ICfEi?&G3jgOz) zFf3H!-6tWkNHn#6Iu zan!s8s1C{3m)4-|wnCmLC&Us3j8`Z&SSBhYsuPT+BXfXN0P`zX2s0c0fKuG;5Qpha z6?9m-V90Q*NQPcZG5=cpJtAi|EzB+5GIjURL5v?5o2ZOcS&eFS!2mI(f63$+t+8qS zmnWuAKk=o6)v6KS9R*ou&R15gdPVy3*590zCU2j=>J_e_K_hBCnf^d|_THv>W7XsP zIe5L@wq0c(tW~K8hXQ#jX+-Bkuv-7>@h^wX7H85!q;t}judJH1mF<7%_qXE79fJ}Bf5jy^ZiQZ)3N zf*V!`W-OmRxnH`u4FAlHLn+A&^}(>}Uvm8l6@+fsRX^&92osReGUO%dP$3U71PV}E zK2nFt7z-+qT)&cW?d6I(+;kdn#ps=v>-oqZ_r%4s4?iVNgF>p60twx_14*) zS5){A8*<2IO-xFR_jcDe^6}3<}_O5Q|AsXT#4L(ySAtzr_v_aV|D}gwKbR9VGwm9aK+asZPABUsxY{yvv z*J0a1XAgvK{{-7%G%)5goRn>$4%y2EfqWhnG{kUY4|x2ZKq2YKk=!s87HDhxu{Erpq?rG%QXz#}!Yv&wJgpc&)_4V`D|!!o+vs~}u1Q7x z3It-3!PCf}ssgGOkmR&NOJ@Qk8czc8{p}B*H<=vmtqzmv{KM_w%f6M9IN`~l^-pc- z2yc8`e8rfaZhS?2d?O#;@>E-koU@6&K`>AB4~=@oyXCR{bMNm;z(nuw&T{&*W%*My zXK5$`tDL;aLXnoADONPqD|?QL73sM{Wdvt&=?2iD75M%XV^5ejXdVzyP=2Sxr zmm~<|+vg#1=a<@Cr?AYHXuPE0XLTH9TCTeNPjSim5BSgcj%NmPYdB+~Qu+>BCX@^9 zj4?@gT!>QWiLVatyB}eyBa76PNb17LsP|i}V)P}Y`cC8?j>akHD*D5+-ocd20`FNb z=zL!`kd0)MfJ3>G{hB?;-h%-~;^0sy5>gteU7(sk7V~H(X1`Avl($KA@+qU&V6MeA z49F>+;5z>3tP31eh+3+04!T|kcxOlSiGtTaX^#<)0C+XHW<-~Oe^XeP{jLG0a&Ev<36z*n$Lg|I&(VWrEFU=#2jo9Du>`K zPD67Pl>^7bF27lcdgCSPR3-95qs&S`(a;eR_#J#PAq)CY8md-tkP0H-1+ItU*OaPM zl*uUol^Z+qJ*oBrFI7ubjNFg-Lw)2&i2z%tRw0jG6rX*h_F3Wr92=E@N)@Sm);PE} z)g?F_rTVcc*+aJFrRTOS(T|C4=5Q~wUa1Kw#lE6Mv1tS{2)9oA$J&HN*R2@IeW$jn z*!Xa9UV|etGV)vJ*nD8>a-vnOj58#tG`hqjm)@C}8gH@bRDlNMPc;tbQhbS`KF7dw z+Fn|t(b=DsFHUsZ)utiN-hjA4TIq!Ryn^&Kxn(o=TyM)L@|4E_3o9_SZ+#jQRltg2 zd~fGq3uem1MSTax0`@#Z1NB6fUQG0*a3c&FbxcD*t70}wd}^Z8;E7MrY1N5(r}VvM zluJlRw7G|;#_9XH^detUXdL1)Wa#V;lk4JH*C>t0nwXHD)L$Q$>NOSy1}7Av)Wao1g6+*LehE>mffHY95VQTk2|n3lIWL8;WGY?Th0dX*Y2 zfO!`OJjZ)CGv{6RG5cW;fM(29#`uy#XzEp3PN`AFAh)blm|H5uxJ*E4{BoSPM+ zHfwq(v60A);qSG&K}_9PTsTJW6n^vk)ZPA*v!lclu+oy%I!*|-_fsiC!Mb!F&{ zHvkdSEW{d+%*JTUFldrFQ_O3>et~Ng8&+lb2AFy6n8MpNJPzM$;`U9!_$vbdV#askxc zE05z3*EuZ7I<3Z$l%&xbY=$ItOd>v+aWJPH5b$M|d(2*KoJB-t0-&4dlN{rDYnk;&aHqm8Q^A7;_Xu9{>B&)C@V@q$n z+h7RIFd4OM=~}-3*8J)2xFm~UO}chRvZ42u45iUDz0zE{c9DR#yk;Kn_wBM;RBGF% zz8tsd__F24k1t;)`Opy)R$x%+_(A=i6dD@P?6%RPL?ic7pOtZHrNwk}61UN*-}OQ; z|G8WBcEC3g#*m7Q%fOIS>+?l5fSvFVrm>l=I>4=&ODi<$9KAj%4b2kSY%mR6p^FL3 zD-P6hT;C5WN*0$DZJ&a~2>|Z0I(2$oUB8sq?e=~7sScjEC-x1q+~O*qhYcHw{u67n z2*~4bc2b|6#q$C&x|P)?Lq3X+#Ms0$^wR(+8T_u1Jf@M)`wGtt=0dx|E+Y_0Qk9E2 zSf%Bt#D6w!pE6~8Wa*Ucjg8wQ<4WgkyZ$%OF0#^hcl`dADcO9+!1-&3JuxF`^2Ek! zU(AR@(&-b@2Om7WacTelp4?2j3AfWy%~kQ;w?-pW2>WmrWpjbCMTx*ZM`xxYLUg1Ur*5EYYXMjx z*hMhU7YgJ>1BFdU5+?v!RS;S9D9Vy2YcEkCZ~N_4aG@i^O%lDU)fB1;r1my1A$`FTbMMpuU(@|ICPy?%-!#(6 z#)+FYO^j~sJ$J6-MtDsSCreATEc!@i>=Yn-Wh)bSH3qzip5CZ1@C9UUibU=%**EsQ&7?sWlHESQ&cHTK}bD|V2`6XBwv)BmjjjHN(+u4VlkgFk?L^BcmCtpha?@Ph| zN8bkm(j`&27P_QFyd4Zvst2wI(Nviv^g@+{P&H!qg#~i@kBu*DZLz20@^sHgFInSb zV$#!NViGLuYozv&(r~y2r`d0DPBdqTtr=#~s-Sl$cyRLYaaAz4oq)B>HV>9=ztRJ@ zQ8#cT0)^%xdD~fxGki#DfsP^+3Q6BKA8`-Dt!SZ zlERb=IC__W^PT_Na0hZdU`aV2Xe)vi!w3s=G|K1(R7y*2s8OH|NrH{)hzj9NKshYn zNzt=bSJn-ohn+QKJ!=U~q!$u)S5+x{FtSqo8;WiXm#IGH7MHTSl6!L+tTlg^5C3-L2$kF}sK336IXvY@)pY|Z7h)zmTIz7~DRZw~%IeSUEh@9z^rajEAGZs8vFbeUdjnShe=^c$F zgGS*XWJ#C*c%VT}X;~B1Za-x!cjPOV~^4 ziH{>)dxxUy)l6|giz|-s=n%}EUcxuyTq7<*CU+`Y30_Sfvl9 zt8Pzrs~BLRUkOnJuoaQp$%zjXqzG&S6Ixl3^jh!1eVU9& zuH{)=q*70Pa;jQY*c5~O^vd+w#$}DQ=}O_o;sGMB?w1p+;vshr=8LbuA0iz}SjM^~ ztb=&Orj}C=FhH${=v%+Jm=XiYNEry&a0^ThBfXyf z>(lt(D>9@PdsBK&`VLQcZ{_XGaO8+IbjSC1HQph;^W?qKA5YG>=PO=$MRnvpr|9O@ zz*~wxnuUKHnMR)Xm*;62(=Td603V?YTlMWwmRj{fNN){Ks%n?H0RgN7#$4CAW|>i- zgN<}q=V4*k<%=h=@@84zN)N+h=vpM%rar1rhp{4G)&M+K>JcRdT?}dI&}1rfuTK4M zO4N(S1AiY16^@#t%Q2&ogR-n57P|CnQHu+7!N7=yGFTvx8bUhhKA>y??NnR@ncx-d z5ko~f*GNoHTZ_#4G^SS=Bs*=gzuBj*ooZ))qn$`aRc>xouCROJjr%t5yK!RmlIgPr z%TS9jd-{^3L(nA5DD>NJhJV3nZuM9q7E;Ww@L>NER{D*cy?}8$CSa#syv>m zWrKA)-+c5*mB*uc^3gYU>aKdUr;allIwu7Kx`4yd9o?G z(6uLqk#lCz+_};ssr_=5Atmm?h}gr#%f}*plh!}<-R8~TJ+wYalh>dA`$nR_MEft7onoo}H(#f-?1*zj(cxMDOJ4*+@NU;S2t! z-{9Os4|N!Jy_}Kp@~$iU)4=~_iBqraPfC@Cut5Hc&UF1e?##UF(XIaTO8lfF74F$n zNImL`?_h*=dobwXk4Q=o4#_!czsI0fAd?iX zC@_o9#dnddy+pL-V29`iXdqPPkfAXtkqjNQ(vmKLWf+%`TXy%RpThV+J86L%RRp#X zoy1s_v=%@m47R+Ohj8Q$<>ge#i&R$ZM_w6-#oGB=`DlUPpux$?0#QA>vb3tt?34ue z^qu+z%BI>#c=UYfwV}JF=|ts@$wfJXgfPG%Cg$}+WMrM|K3cctrb_SnD@g2(>y^eH zPV4mp9d=)rUa97)a>8p0hlwm)kW!qlx@r0kg{9Ka*xcHt<)c~p;F+z{cCpDD?E`46 zQTr&Aji3|xKw?*rVpx`wv5tfKmYRtghgt^B0+~aO5+U)l>&ou7K>Qf;Z17Q*%uo0d zB%Y8upW`Ps9>@to48Lba+qh(Q0B`SI1KdIXk1j!&HcNvu^WAxIYa>je34d`$pGf@^`4QTY`tL|f8FiIz;0siMG!tc|X;FCr^q9f6u`FK39z5-I2W zGH22JQG;1sW-(L*uWe7Gb}ua&kmHkH3Gd1eh_2-Wd|KE7&54_8=N>Ts{lMJF^oAYw zdMEedz#)d9C#On#NLyQQNr8>cdUd?r>nI3mnhinTd_i3kNUt)y6hfHK+!rb`XLcy8 z^|}FB+--rHb)J0b-JJ63oHyR6&QgyIWDGKcVs`dDSsqN2@$t};Fbq3+!ZPOVW>)AU z&<8;!Bt^NC!dKgaF-b;YxeH>%$|KqdyGQ3{v9P{uVH($WMN_SW zgf7ybA|KT@-LsP2nGqQ^eV@9rsaDxCG4dOKsG|}AS0=NzFqsc^v|w93D4Pq9PcIQe zTHtjKsG5YaoNv;zvREXjU>Ma(MM-|gKW=|XIsywr?dhAEYTYaE32&P=VwStM>0%3; zc4R%TFY?8^Q*&&|J~vV`8nSwqq#KPbN#03S?s%W-s6Hp*d0Bxak4f3rumBjWpjkdY z1wG3Pvd0klNdQw!YdN5n?}Q{le7-W3C-3xBOn=d_YwfX#218sw#xg>hWYVVsUPC;L zT~RuS+c3n7eC*X>tF1Hi;xg6RiRMjX>o(fzX4y8@U9-h7VU_AyZP1aIk{>tcKxu&_ z_OH+Pm1*u=zeiK%%M0_L7<+4As{|gLom7>o3zR zi$B0uTvAM~VS7povmNZi1lPpv+WPskMoM?G`$o=MI#zqb#Mo3xp~^J5bh?}8lsEaL z&4tQvo-Z4-1J|>d>|>L@GHebsbv*~h!tpRocdm`z9s2pG!KNv1xM5b z8oA!V5#hu0KHvt}$EvnXdT-eRX?JL3lnl9*@3`Xn+9jA>v4Ji5SG9x^M0-XT5z#LuC5g1AjLkm|MFk(F{VBU>~sj zNl(x)WMHtM7PP7A0f*NfuhwtYR^{MuvnJGDslG5Xv*HC%rJB%7hN^VvZ4G(oz5%=`mjy18Z9Idcz;ACk402(i>I z4i2WdjvcPZXQOQKIaS+Crc6ts^bu{Rxmcsc2CVE^j@ZbG0gH0Jf^olQMKv5~pdTHCG*8;MB7-JsBf`?)9kAvn&##OnR=MDl*tWXA0yo6sz zxLzq($%%cS5Cm`)MIjJG5yNCn9)|oi@Y;FDqTdFuoj>TUKy``JTLr@~rqSxR##mU+ z(`x%Fo90Y5v&3xEYc<2MzR{-nK&$2T!iO5$F1>|sU9Puuye;3HWzjD;SghKP3cXHi zj^Tz%V-bvbZ{(pEvsP>1pN%nFBNt*5RH+&SeVM6Bs8A=4r3R7By`ymm1QHHes~AO< z>*D80ff5Y@0gVSzLUbN5mp?Ck`=jScHSi*T_}d$A{FV*vGNbgYcQ$B^oau_eN)K(2--ihb z97gvLas)}S<?ck0Bl{6I@z&V}9WabcIzcen5?o&E(5a0>yaP-o zozbKY=#9K7D=;ei=HEWY$KXMuRq-4eO8EtXMw zfzu-|kQD_dY{c!Ib_BR|)x7X?AA6;)T(sC!Qj7 zsa4e?x@Dgdg+_3y{2CV2@cy7v1Lsi{<64Q>MH;#06ODr;H*0-X`j~6xnj?+aXRVU^ zS>|b!!dxpUR_TO%868fhi#ji(+dgSzVd~?uyejLB$dAPj(up@Y;fv!8`ZZ$E9|U48 zBKxoGy4>r?L-1uoOQZB9bEc17FZJfL*b7o`WC3vED050*rjO-^UZs+cB1+BK@C+`Y z8^gGzioJka{|AqI29Lvy4S>-5X{RJz^#{<`rJ-%Cuq#BfYz_dD(|83cLe7F+y|T-y z3aoeHTMLSz&_nmc7Uc_&4XzGcBX1!(oSixC(c9@>)F*#KD=7 zHjq3zAes}YPlIBKd_p{O@^fwn9BG1ZTMr5wgTsTt;T`_P&5QA0*s!>E#FE9$9RrRn zU3Tow&yNWkk1bnz3_BekOaJrCb#Jd-`}TFu@b^j*;tZtaZ{Iq8?EZ7yNa;IdK}AXh zwoYK{v&uCK4@nmeZ~3A&ca*N)UHj#h!_tLA3pM3gY{7nZ+n-w54O~L>^+Ar_UOb83 zxp*;?%g`df_!#^A*s;%#N$G4IGp;?~c7Cm(TeNWep|_VWee>WXcs}DWJ_BAW2!-nl zZ+Y@I>B6l|(@L&&toBY@d@EDm_T()%K7DZ$`pir?;2pv|tHHN`zp%m$?`kX%k|mP? za?XKA5aldafi0F1k>M001GOU0F?k*3AmthPA-Mqa2NFUKM0{UqyYvIo0=Y*k9e8}x zrpGt2EWMyl&-O2UX)x2dTrtUGlKZ_ReV;rAo5@T!=+!0u>~vhBP0I^;L|fIMrqc0u zd3~NxUK+O?8K%$RNk5!=Yp{8H>LsxT)FJ6+G)LqtOZ3HoNIFBE%H1< zE>)G1l4M~<#V(e}-Nh0A%b9#`gygz^qCUQT;^v7HH?u-*TAyUCZ|%kv2?@!4(zK5B zeswn$-k9%jXdGpZXO;}ZQsZzuQ?zSzzx07;rGK71i-bUHdP1GTa}Q6N82P~#E5@l~ z)6*=LI5F0i-6tzxD7rDP^8rhTMjv^$$Pmct1FyB1v-C9fMMr4mJ@>5STd>5JC4N4v zd|V8}kB@x#WC2n}V+4RVq(DeDmpO8cjPEH6-O8lOaoazWo_*j!>DkY>PY7|(=BBcn zy#w+g`#&u`otl$BAdT(!h~e>-k&6#XEuU}O_BjhZ$f-gT+TZmMz+(OYkMs&F_6*1` zOp(@-PKTi^2SEd7QJ)hLSp-uBq8Jf;kqSgGkKF()Jq0qWLG6j&77*=G2QIi}`H(?8 z007oP90IAg7V`$`rVB^@7QAHOV%aRdD$i%jwCy6oil9oBb} ze8)J}x1ZfJ-@ULRw*O=nI=|0azQl80|Cx$CVHnsap1sD{j`GNNo>|;u`H@Ro;BfLR zZ+oR+=@`+cF5nV-r}pXCJ-v(_&hWEO0|U4MmdoYjRR6vIJNtwAoGMMpSUy)?AXR&i z`k24y%QwKElgkozwTEh=e638QwXo?d0av@X2gM`F6Cuv5T=3ddXbL1vfNQWy)_;)S zaEhN2%n^+v+9k_NMpAGD36>WUQ!WNyki6b8bAuJ8)F;pYK-_|KZ*x>&V467c@aW0R zT*1ijk9gwZeJKUt4JK)pZ{0DOmyW4cZQePFyJ0q;7$@la4Eb=A34DW+nFbAc@qQL- z)nkxwi;pG`(CWngh6S7_LD0w9Y{ObN8#z6$GY+hH?E!y`&b#Q=a{6N zN8J7J$o|GToYy7jlhXN`Pc|C?BY@Wq>UZvb<}k%5tuZl8hg`T$tkN$i(da`pA8m}` zs0#W)f018~Vq7i|x8W*NmP|8P=iKU0q!2m|Bg>lChtE}2b2oi1{gdr) z(9Mua+D@NtJFQf3Yqoyl*WA6Aow)seX?|qRO*bb=WuA*{{Rd1JJRm(IeHf|RV&E2S zVihZtxZ`vijVr`aLXY&aY)x=0fC&o08i-!Ri_;i_M<`J^mD8_;F|eF$2Z*Z2Jm`0^ za##n^uh3smc0plva0Vvu+oaE=0rPuXst?Z6>6Yj-zFt003L;_x`E0@@3UE#g1_BKN z3@gEV19lb(NCgH!a~fL3Ky>B&G;EOG`26wb4ohFnthq)IuBn;HY=@sazFK3F>&GE^%L86W$bF3xPI@#`Ky@v z=5JX4(~lBw%2sw7qdEnX#WQ9wEY`kV~?+5Xugcq6Z@qbhxwP>8nsJQe{Xm)*G&5Y`~qv!8k{px_ii!V$W zv-FlVkL65d7r1xDcW>JL2X1Uh-rnaYj=ue$Tk4iE)zap^_psSNj6iw|3!BWA#|NiY zEj#%rd$4Y5b?!ZjwzaPvGqG;aM_XU#hTM4eEUFlte^g=2KSn~={;@|`)T(LkG6r^Q z-2&K>XD6IdDXjX7FhGLpz)T4!HNj&O+cm!dqG2$kVCnb!N%+1RecHlxQ|9S@w z!AmJbmtlch`4-uNN#$~2Ui>S{PuE^nRjIJHCD|x;D#;HY0mTb$(2I zRYL!>$Bw-;+}A6lkI^}E^WD=QpthBB*NCfSeMzyd0#g)Kb%*h^E`_6ao)Q-wDGEGr|*4vly)8^c~?~OP2_AX8|njjPUbhCF48aR92 zz|g|YjSp=dyldx+FYOG(a%$xNwI|!n`~sJ&<2*}Wo3mie>UU~KX6Gbpbh>!GMm2Xv z_~tDe5-cEn`i=M8dGLCja&dVmRMFJ5ch;ChwK|dU;|8pqIkmW?B#06Vyw%H%l1r>D zs}fC|(V)^+R+*A4VpXNtl`v$*!Z{;rCrqdvHQS>~Fq;ym^=Eb5_QqM~_U?Pbq$?;? z^Stt=Su?5!)(&crru7@V^})$6?Ap0AkisGTxmt7@xf4d`LMbU@v^8f!?Z`Pz>opP&nU^)=EmtwLTRWs^_e8tTs}dcNkG3}MjAG6F#<;oAT~La7Py=kUbw~=dogF= zk6>!R?E_ZLz-MrnDde~Z!t4Vql z(daPh%QxKm@rsq-JbZk5ids-=^wuK!!%a9$=mQrZ8XzaOWm@MM6teH${P-|f8 zfd8*@Zb8mkX>)?tXVCvSeYn-CGx%0+-@R#ec}c@{t9DK+u&0bw+WQvuwMg%0jazqm z=JY$JRK`UbtE&c&b{YE2UQpRrsZ6q(f+PFomycgQv6sdOggjw+{)1!E-!je1uj^&d zTC;C;s5Cr)iK5A3InI=)RK>7+lB)_bbh=jWFq=*1=rcB5nOAqy_|ZEj4(^qx;nr8W z1DwM(YB>C537(sJ|+!H_AXVCJJHXb@sXt6LfNtIPb%1p9ZbU)Irl#?Mx z6N7^g60wY~F2QKoMIj?SwuNvT94%UjcDBk_^w<;?LyIo^uQU?*ZR}h|ku{=TsXeya zEEIakg?{`b`Jq>|j}bB{wGnx+b(%M2>kDQA2FIme#QyBz*VA45C}v@_Y0*|f7>*$= zR5LDw+)xS;RRvgDcQf#c%i9djOjl{OaM4iKjGLnuM&1$>EkCKVL9YMst2Y#hK$!m( zoqfU&&PDDM-pe3s6vurzlAe&!NEAngqW`mY7)ufOXU;@p%%6Tb8g<^af98y)!~Nei z%`FJbzslp}fPZ?t)cXIey=;)9(t#QRtXO#U6KE2eiW*2>{NFW@=#&)5IwQ44Tjm26 zZL0Rh|E^iMzLEl<%kF4<<7x6^BfbBN#voZb%JU|5(h(B=z^!zyFhzHF|wFm&D|vAM^8g7eqt!jo!d*7tt6EN z-tEP>_@g{Wc`42!s)FjSkf)nCf*;0M=v3cdrlwF~Q-3HVmtN(YTJ5gH^tKlHy`gAS zsvkvRi7q0ERk?*Y~*0% zpw?hDW0%7&H=CR7Zja?c?Tt{jw?xRvssDZBeh77ebca8FZsFLHv6-T-Z;WVtM*qlOdHA`-l z8Y|YS627=%xBY}#$tf&Wy;=z*9jg+|dRxe*hJw+Gx!tBlWB&9Ae@UUWwt-3K88$@l z?DXA99&$q-qR15^_;PZH?bHExWmM@}L!&KAM(an#~5!gihJ+=mfgm_V7GDdeYo}Vf0lzJb?@D4xxYjU z@EV=bA$knn_`JM+{&A6;PBH(z_folKI^Lt)IW%|u7{OHN)Hags1bP`TPe2O?)G}D+ zG{E~oAnmFU>8S(0Vjm>)auK>PctA4L%f+r*voEFD(vdfB+Bh~LHs|2AnWY2DUSreV ze3Ol&3Rl;>AhqRJipE%h7ZFq&!>RJ@y<%OuBad7*8F7#FsByIREWG2Z>ziI3QqVYl zWW{`+QoZ9VX8B6maSDy0exRR04LT#31S8l&b--DYGbsHUraZ9m>-%QRxbJKEJ8A@l z_%HN8CA`%2M5Td2ZDw&uBY`ys@e3woc}d$qF7-!FOYib4Bd1xqaFn*W5z>2f6fMaV zqb{{5?-xUI9J-Q0;m`YcXv$Q65-5Vj4yT3Mkv4JAB07}!Yo)W&uRptSYF5Lbddq@g zu_tnFtDn5gndJyp7S5WX)~_iItzvcUeA`#j6lo+=HM1(F96Hs0OZp9J&4wM)Cu1)D z>R0tU;@R~&HGSi#9#sK(kte@m~gm za=r8h-AnyCs(S`w0bj8C&ii4faRyjLFq+#4(I0o)6VD>%5N2!S9TzNsgO0FD|(zW^%wCkPf)x*s0X2LHS!YHx9LF z^@CZk5O{!84i_Ay3wHFG=NN? zx=)vNGr92N8wqO<*?OV|8N`ptMi`KD@@4SChU^rfpX;9%s z71kh+VDS{59tlUCd@6#4pa+BZfimy?A>Z%XcVTz^o);Hx`f}(W7D~6j@+;~6x7V$E zoB4iqo-LL_+#}0iDF5csE=&2NNOp1jy4(GY+uhkQ+Uy?|t-4|Ng}n=3+*7}L{&n}X ztb1E}AJhYnc!#T&nj;b{_Fd+6>H9CGWz7shBqizS+ivhFt@wt7)zXPa5cDv=8KD?v zAUZQ~U*ymPer($#j|;ck_C>y86Qr1qd)Rb<>TbNH%?lmlQg=RALW16?A z>@=F7uPMaEvi%gq(q2&P;&AWfd+;noWBots-UB?2>gpTcduL{QlXkVMu2oz0w%T14 z+p?PFZp*z}bycit6*r0n#x`K8u^pO?3B83-LJh<~0)&JTLJK6s7*a?=38`Rf{Qb_% z$d(Psn|$x{J^$x#YiI7OB27?qt;@uqGejpF5p{d=MAqr#Fzo z?`}uB*XQ%5JEEZL?tI;0b69aK116lB$mtxvY7i#=08co^1YX{Nz5*jdCAX%rRGdvp z$_5ZJ9SV*l=%tNup#*+LI{2$tXbJOxvjwhIS(SbYm>+mlx+V*J3=vB-(VAW(+9w|| z8chc0iQ6*^olz;?6kk*`c#p~sP(EUhZuV8?7ba#!yS$0{1+ntAo=aDf(9X(BJzcQ{ z`H5avbXH!P-Crlb$6gpEfKsaKCXEZ|9-~wio z|G~t^U@y+by1(J@gz)|^FfLh;NvOoRL<>d-!fV7;1n-cHT)?{~f>;W$p;hfptB&!) zW!m0_jAsBV>Tp`&1wT^D=FIXdEUFCWsVHJQDO7;IuRdgO8ggQ-)|5oEciZdd>^c_i zZS>?+=`)SFx(+{>avNN3Q#-#hVig#l`5EGo!7+>Cr7r zx67O3b;aAFdwZj8@$psB?2#!=F$G1jiGsNzdFHHheztAz*2D$g>U_`K{cr3aSa8LQ zpWSucN1n$%lArrs+>=}Hzbe%hH9fwI@viu)3|ssa^>XYBX}0L9_*~A0}Nt$Vj3PmAMLZh(kbpaUoX5thz%5kMGrcDrx!qhctbY6 z(sNm%sAzoQoDjym1aGoY`sMi#Z{Pm#`5zD8kh=HdzQ@jKh3R5bV!@IPi}MqV-o)Ol z?BN5^1>yDUW+ysEuIS9kS+nbfZChTvV6{IvFPtC6^{)6}Mq#4cu`)BWzAe}6uRnjq zyz|!0E>3fqxoy?xl#t9>$Kv>c ze1D)I&1NWDJ#@+X1y}88sR%CK&|O+MJ1@y>j`oLFgq<$NsupC%`oqOjlHw}D)nyIg z**Gj9_*Lm9RexP~_UQrff-tKUDQ3)aMdwRVN~dkWk!W~!r@6y$WoJH(ou%5%nu!rK znJJ`&*-3f5>giV1Kc7U)sq!{BZ-O@cDQ$S2uZlSf!3knc5BWI3_KCPoM4}P;IpdiZ zovG8#4zcX7_U`>keg{|fDYZwL`zohO2})--{P=hFeswC>0+pZj_0K>XPt&jD(eP_M z2|S>x^P}g)>d7UrBmb_izScjd$4rw)`d7VEruN1uV2DjsWa2fC zo2fUS1e1YS4TPa4!Z&^Jfewg4(^-ze{=Ep4(rnVR13VEPpHOxn3x6cW0XDr*2#QD% zv!#+^9@iDl zG7dXPu9QXM)47l51nHU?#}4CL@dw=s_1^4*Oh*phrN>Kgna9sxcTvQ3+3Gt~dG$M1 zU*?Kjw9Yc401;##{f>ee0`=hdhQg^+3;6*APaNeCsXiQ^F6O|Lc3fID!ssNqS?Q|N z;TXi{i0Skqho_0}%I)m&l>?M$V5K~h-I!la;c~!#DsaiKK_>{XGY=10=>i>o!Q}={ zoXC`0sz97`f{OH0A%YTxkK{TXqWO%|Goe%wa-|TJApE*ot`_8S1I%SsvoeR-ES5|0 z^5csPu}7U|ldwQW=mQ*9A@pOqAtjqxO<^S^o4LpkcT|0UDn#X&h#iHa^M4+VJ*l(W z?MGwf$FRIPS^2~r4@YB}`i{+_ck+u9cdM1=fT-)iIM z!+raO%l7X((ZXJ10sMb${GjgSI*2O#02$aI5avIvOfCMLT<4ft#7SVdK5`vi^JT9sjd@DX z1^Jy`Hp)hO!8Lec{3Cqh#JZvKk#eA4q&vkq(l|;wr(Ut<=OXSGota=O$`oWRYHx7J z(KT;g*EoLo6X$)PS|q%{cKoQz2MDx@KIJ~%tiAaurJE-x$>+%_69x>AxTC)si}%O7 zqb1y))S}S=l1?}|Q$H>}j+t(TyrLIAzu*rBQfOta90(K^Y%gGpN+|5@5@Ju> z2%{ho_6px8KQjLL^K#&MV?Zj77;unrqY$e+8ilG8Ccep*7sG-lO!_tBH}ZDx_)ht! zF?qJ}OND>n$*aJH%5OW0IYFl`=p}3f(wU+|o&~b2EI?NGa2Sl;1GrNl-_n$wS_b+G z{YBiiXf}5EurQ-*&+adq*~)+JyFkuXY#WTVt&+zd+xAMOYo4p}m2Hp7}X9wAD z*}>2Gk)z{ptj*x8X>N043uEUUJ@Vvj9orAS-@THtmEG?j+}?59ljKkyD-Xem>C|{m z?6X|p{^w~r-_VmF&t|kQJ@o_j%Y#dK0}+^5dp$%Pu(DJMf0I^XLV8>{0na#J$oH^i zB$hkgEM!@YK6%&cugkl9Myu5*zGK9e?QwYn-}5V6jxDb`o?W$kd6oE1)pEXZY)p4@ z`*xYEAL!KZiCZbhN!>m7U``s3XQK>p{ec4q+^4gVB}rP3v1tVCr_icIqS^Fck0W(R z>p-lM&P^$XvqFhy`K*WsCqN$qznC!e#D%f0@;$GmWvnu1WmQF1hVo5fe&fjSHFK|n z`;buL{GZB;=WSdvrLu5t7N*fNEcEfEi<2e0&Bp4wV>q7m`cq2^QT^T@Y-KK&jJ_E8hqf+-`xG-=A}!$aLSm( zW8tO)AENO-@f~DMgX~Up;_C{TLGFaS`WRyYGzDav02P<@7c0tk2^;+7stiST=o7TYoY!Yg|)iz zteU9K-fgeQADva9T>K3?DWYNOfxn4YM14F9{fkv+VjtzA$!W+^IbgV#0qpgVQBjQj zQU5zwCS+TQ1>lCLr?RU6PXPf?J<_@LQocAXM=#`82KLjuC9IEC*Iw#de7dc_8s3lvS;ec{O=7#* zyU)0B`#U#Y64`b2D{C(uN?`dbZcdhJS0=sbHAKt5i7BcJ{NBy(>Y`%4dV1QPk-cB- z`~JQ?EBmf~8DB+v#tC|#By?9}UYt76RtaeaqX3X(QxCh9BW{=rQ0!We3<>QBNr+bw zGT}Zr!%F79DyU`B`gV%G6$UjI#fQnVQu4Gszc0zFM8zbOrX+>(R|Lzml1fcZi?P=% z8n%6S!F!*|CqB8SqvM`Wn5f*@)n^mMjVMelmK_T;Rwly*OH0f`2Q>_W(x z182D4#S{OPeRTp!_b77?n?ynJQO@YNfow2h>XGCRq&U+3S#TW-$e{;6^N?szh<#^l z?b@+5?6RqKcKK?^ga`)9Hgxbl@2#{Z~h(BIaQ@v(Qb0~}L2nm_eWFh50i1D(2-ou2Ik>+r4 zP4D=#%w>Pa?vj61W{#Hs7UQz?d>oL8{9drd-uF=@@(9aD<7bgqhz|1aZ}c?%Al^aV7m)?$YO znIZ|y9TJxFV*w_{4J-k|OBgJBV2?q_pQKR1v#0lvy94afhMB~|=)bZ$xPY^WNra4` zd%)P!dq9mN3Jf46296b!2yD1fjuM4!xPf=agR(HfUS@`OeQcUdZuXT-1Yxv{UPSU5c?MK6^2{UzlI(?P>t4ri5w{D*da|pTIgmV@wv|=fNseH+=qH22wy9jj(oy zGjj&*C}o7y)eK~X^M%nSo580U-lTB&S10Df|I({Ot)Ko&`oJuS(KCRud2;~jd5^gHdM4ME6yqmwv?$}RH#jwV~F>Z zEY%c4CLZYy1CLh{Y3Ff0IEsqUfJ=5Nq~51D;1RWJa=4IZFpgt4Hj37@l~L zRbg{0f|YdO- z{><*kjyi0ydw#YrYX8=hg#klKL(w@`WltBS;_Rh!3q!-58S%mcr&7eH7bL~0X+&d2 z+2mBw|E4NtPh{y-7q8~9i9I(|o@z|VN()`6-MJFWqSND}QleP0uw zr(p6IGH_?e#SZD+VHtG5>pV!cfas$M0=uWUUG&&RUF35FK}>%5Bgx3hPRl6u9@s!I zeA5RGe^N?%M$o(FhVf^QjXz~gv)*a7>Z@`2IDTgB1#4clrST&gxbM}#pM6N~?dUFr|q~~c%f~`fdMZP#pPJ<_@esS8$-VJ*jJ*zxc{nTh?;*Jw% zsOf=9h0L4uF6`0AflkF)83}?I^ymjt^YQ>12ni5h7GxE@QF@Vhzvvt~we*5YRXPn+ z7Jw~R73m@{3YYreyV2mKWI!4G_fVShW@UBvMrF(>5)-X%Gj~=yUHl7&QSWK2PPyYT zhu)lI^se9WVDs*qvQ~usx3bj2LLUxz8$)>>$pCo<_Tg7E&UvaIrVuyHlZ41E%RMQs zZQ`r3NhuC*rTmXe@|P?qf;@rMJfDT;uNl9?U}J*Qw9e?t*pss6fos>_adBv@yDpJ= zvjVgHsoB%lZEDUnae@8qSnsiCFL#;bYg^@SX9yKlHp349Lk#Ea+aX^!4L;&_qjyLY z7Jsx0M#&l=kg-1iX@0Irvuhh6ZmD2d7*;GfV*%25AW<8#Yo7 zM%wQRo;CpUl3)?^mz29pdv>7*DN(o#1`ekC65gLyvNzi@OJC#zGxD%0t0L@YqFkL* z0n5`_?1}Mz%jT7mz^kI^0jB+v5^qo_JTv_>>7O*5XT< zlW+ysGheiDn?rOITgx`^oV}sy_tSDqGyfQ8PfML23ys*XVq!AW=eqxVu_Goeb3xQI z5o2;Jlt{~SvdV>~=zZB0cNb2T+kAOqxvxAM@`k>tIaxtgEmh~F7ffAmo}QUez?(B! zq3t~HqE!D&=Vfv~{2oXwWkHiHU1ZQArIGz(OQT7z#vXtXu*Lh zNw7+fr4VU$;|RXmO@;9TSW{6lni!#G=Gd)`=dsz(dKj4wnI7j)oa}DH7CD? zD2vN{Zna!*sLT=m`Kie^r2_o>th`uuuEl!kk#&M)sYzZ@T&B zo8G?WAA3`(suTZy=iQ%ta`&qFwv5)fN90%9ndH0t&e!i>Gb8QrxA|Mgrks=?pSxvy zrfdDxap5VMOXKsCoy#h__w`Mi5ABFaeEfJ_4!FJbpn8EBvj7qk#3|-BTuoTzUAuS7LTxpIY;^$AI-Wkr(@P~uWLq4c4kz2O>nb6I46|* z`PbHj34Yi@MQ%>{CK_tmI^&x`+|e-8vPinV#M+~1)t47m2#TZC15=G|ifk2bV2@2^ zhlwXWbsb5DtfH(;w>8@$8l|X=UCUmW7X?`qYqmKi9d8WPyF8b0qr+(}wWn9-&&k7;+(w6wJ?3birdl`x|+Bn)*X{%^*Hpd zOOqr|p-0MfnUd3!@n>{rOCEOoY(5y%Ilvd(h&}Eaj6aYvfh!HAGWCg808%E#0YNbq zM|8r3J`?o^NtO}nQ9&I&M%qf07bG!7!&X}3t~V<2F|u%An8;%CvaJdn>|Fl* z{Ah4cKuftncqnjiDL2}kwo+SqjS2@f>9(NF;V`mGneL3q03fihtRbms4G5+O7i0hk z{PX?uxHC=#0*jr1pooCLtO9|_l_z)v%UN@Q5pP(rbxl~$E~(@XfII^t;8hIVZZMZ5 zW&b4TiI#-$Rv}~xf}tRWIa-G)AbHEGL=e>`-HgH7kjEpKOTCVUnnq($mwb=>>$N{G zTHtidd~C_ic~5}mHd*xgXC1z=V|!)Y#fx_}=31Hl(vOd@z8_1jicmv&(B8rQr88TC zwdZcG)$0n^Hq6c~(no(%m^9s=uTOc=esAb}XR^VNFxQu9OY!5x-6G$SWQbkGSz=*Y z6!?4kGS&|-LncRB!R*2Z#QDwVTvfAp^PE)mOhvJu+5nn)J?uY|Y#W&T!0(fOX<20k zSS>mIBd$Jh`=lSxBi!Ge@e6XuR??gyl#mhaQslCsi$I62%0znvQ3_Q4C%yiY4_w)AJynX_(SpIo&5*5 zuJg_7z=a^?c*2NfST3Ty zz>Dfnxxv(EbQW#MfJD_4gfzpdeL5n#uusA2qbxPb8wDd{K1!rtFG6~qwzPC?tlX$q zDS#zAi;`p0M_W5(5y!HGy^2DuQyXY0=OFh8(<=?~2ust-)6&W>%$b^haXOXYX&Kj+P>7RPj5xFva7d9tqzzkXkGd18re@WLx*MI|?dk0md8 zaPL5yO>U@et)AXKosZ7_R_pw$%8J)?gjQuh_*I;{jCt#(R?45Q5vSy71(czXqVm zr~>{W*Xs7^bnq95Nhd+b*g%>|I9Ds=XpaNl7$9mbK)DJnAfIGt22BE}FF>f}bV>9+R zYUiLRxWa%uP0bQ>ah)|(A*NZf>WdiUZ1~}Lzr8*&=uNbgms_JU;zKDlP7IeqOX(CG znyKuaPHzJs{0+hYRI(Qx=wTTc8{!p!ys!&Ej^K0q!5knV1}Rw#R0#&CH+%(^2aB;P zrlDcmZT(VHabsm;V6DFYwrvd!F;zy(_)nQ(u|oc06b)U*PRr^q**)(hghsoz=xf9KeN1C;PJI6N2f z$gI9<$wKo8m@G_z9t|(c0LQ}>g^$fFq*Rm|XxyL)&`jd7VF!W!LMG}lSZ$J?%`yt+ zygSYpvvL>C$z&{Z&VqcuwB?R0G&a+iU|Ii$G(UevEMu`V@?jjBms#SUUp-@u{Fcy| z+d$C`xsAfxKdubf4Wu@xnE9X%&N+uY4;NbV=Tez-=ND$=9Xqx%hYytEi_
- - - - - - \ No newline at end of file diff --git a/out/jsonEditor/jsoneditor.min.js b/out/jsonEditor/jsoneditor.min.js deleted file mode 100644 index 43cb136..0000000 --- a/out/jsonEditor/jsoneditor.min.js +++ /dev/null @@ -1,48 +0,0 @@ -/*! - * jsoneditor.js - * - * @brief - * JSONEditor is a web-based tool to view, edit, format, and validate JSON. - * It has various modes such as a tree editor, a code editor, and a plain text - * editor. - * - * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+ - * - * @license - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - * Copyright (c) 2011-2016 Jos de Jong, http://jsoneditoronline.org - * - * @author Jos de Jong, - * @version 5.1.5 - * @date 2016-02-15 - */ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):"object"==typeof exports?exports.JSONEditor=t():e.JSONEditor=t()}(this,function(){return function(e){function t(n){if(i[n])return i[n].exports;var r=i[n]={exports:{},id:n,loaded:!1};return e[n].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var i={};return t.m=e,t.c=i,t.p="",t(0)}([function(e,t,i){function n(e,t,i){if(!(this instanceof n))throw new Error('JSONEditor constructor called without "new".');var r=l.getInternetExplorerVersion();if(-1!=r&&9>r)throw new Error("Unsupported browser, IE9 or newer required. Please install the newest version of your browser.");if(t&&(t.error&&(console.warn('Option "error" has been renamed to "onError"'),t.onError=t.error,delete t.error),t.change&&(console.warn('Option "change" has been renamed to "onChange"'),t.onChange=t.change,delete t.change),t.editable&&(console.warn('Option "editable" has been renamed to "onEditable"'),t.onEditable=t.editable,delete t.editable),t)){var o=["ace","theme","ajv","schema","onChange","onEditable","onError","onModeChange","escapeUnicode","history","search","mode","modes","name","indentation"];Object.keys(t).forEach(function(e){-1===o.indexOf(e)&&console.warn('Unknown option "'+e+'". This option will be ignored')})}arguments.length&&this._create(e,t,i)}var r;try{r=i(4)}catch(o){}var s=i(1),a=i(2),l=i(3);n.modes={},n.prototype.DEBOUNCE_INTERVAL=150,n.prototype._create=function(e,t,i){this.container=e,this.options=t||{},this.json=i||{};var n=this.options.mode||"tree";this.setMode(n)},n.prototype._delete=function(){},n.prototype.set=function(e){this.json=e},n.prototype.get=function(){return this.json},n.prototype.setText=function(e){this.json=l.parse(e)},n.prototype.getText=function(){return JSON.stringify(this.json)},n.prototype.setName=function(e){this.options||(this.options={}),this.options.name=e},n.prototype.getName=function(){return this.options&&this.options.name},n.prototype.setMode=function(e){var t,i,r=this.container,o=l.extend({},this.options),s=o.mode;o.mode=e;var a=n.modes[e];if(!a)throw new Error('Unknown mode "'+o.mode+'"');try{var c="text"==a.data;if(i=this.getName(),t=this[c?"getText":"get"](),this._delete(),l.clear(this),l.extend(this,a.mixin),this.create(r,o),this.setName(i),this[c?"setText":"set"](t),"function"==typeof a.load)try{a.load.call(this)}catch(h){console.error(h)}if("function"==typeof o.onModeChange&&e!==s)try{o.onModeChange(e,s)}catch(h){console.error(h)}}catch(h){this._onError(h)}},n.prototype.getMode=function(){return this.options.mode},n.prototype._onError=function(e){if(!this.options||"function"!=typeof this.options.onError)throw e;this.options.onError(e)},n.prototype.setSchema=function(e){if(e){var t;try{t=this.options.ajv||r({allErrors:!0,verbose:!0})}catch(i){console.warn("Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.")}t&&(this.validateSchema=t.compile(e),this.options.schema=e,this.validate())}else this.validateSchema=null,this.options.schema=null,this.validate()},n.prototype.validate=function(){},n.registerMode=function(e){var t,i;if(l.isArray(e))for(t=0;te&&i.scrollTop>0?this.autoScrollStep=(n+s-e)/3:e>o-s&&r+i.scrollTop3?(i.scrollTop+=r/3,n.animateCallback=t,n.animateTimeout=setTimeout(a,50)):(t&&t(!0),i.scrollTop=s,delete n.animateTimeout,delete n.animateCallback)};a()}else t&&t(!1)},h._createFrame=function(){function e(e){t._onEvent&&t._onEvent(e)}this.frame=document.createElement("div"),this.frame.className="jsoneditor jsoneditor-mode-"+this.options.mode,this.container.appendChild(this.frame);var t=this;this.frame.onclick=function(t){var i=t.target;e(t),"BUTTON"==i.nodeName&&t.preventDefault()},this.frame.oninput=e,this.frame.onchange=e,this.frame.onkeydown=e,this.frame.onkeyup=e,this.frame.oncut=e,this.frame.onpaste=e,this.frame.onmousedown=e,this.frame.onmouseup=e,this.frame.onmouseover=e,this.frame.onmouseout=e,c.addEventListener(this.frame,"focus",e,!0),c.addEventListener(this.frame,"blur",e,!0),this.frame.onfocusin=e,this.frame.onfocusout=e,this.menu=document.createElement("div"),this.menu.className="jsoneditor-menu",this.frame.appendChild(this.menu);var i=document.createElement("button");i.className="jsoneditor-expand-all",i.title="Expand all fields",i.onclick=function(){t.expandAll()},this.menu.appendChild(i);var n=document.createElement("button");if(n.title="Collapse all fields",n.className="jsoneditor-collapse-all",n.onclick=function(){t.collapseAll()},this.menu.appendChild(n),this.history){var r=document.createElement("button");r.className="jsoneditor-undo jsoneditor-separator",r.title="Undo last action (Ctrl+Z)",r.onclick=function(){t._onUndo()},this.menu.appendChild(r),this.dom.undo=r;var s=document.createElement("button");s.className="jsoneditor-redo",s.title="Redo (Ctrl+Shift+Z)",s.onclick=function(){t._onRedo()},this.menu.appendChild(s),this.dom.redo=s,this.history.onChange=function(){r.disabled=!t.history.canUndo(),s.disabled=!t.history.canRedo()},this.history.onChange()}if(this.options&&this.options.modes&&this.options.modes.length){var a=l.create(this,this.options.modes,this.options.mode);this.menu.appendChild(a),this.dom.modeBox=a}this.options.search&&(this.searchBox=new o(this,this.menu))},h._onUndo=function(){this.history&&(this.history.undo(),this._onChange())},h._onRedo=function(){this.history&&(this.history.redo(),this._onChange())},h._onEvent=function(e){"keydown"==e.type&&this._onKeyDown(e),"focus"==e.type&&(u=e.target),"mousedown"==e.type&&this._startDragDistance(e),("mousemove"==e.type||"mouseup"==e.type||"click"==e.type)&&this._updateDragDistance(e);var t=a.getNodeFromTarget(e.target);if(t&&t.selected){if("click"==e.type){if(e.target==t.dom.menu)return void this.showContextMenu(e.target);e.hasMoved||this.deselect()}"mousedown"==e.type&&a.onDragStart(this.multiselection.nodes,e)}else"mousedown"==e.type&&(this.deselect(),t&&e.target==t.dom.drag?a.onDragStart(t,e):(!t||e.target!=t.dom.field&&e.target!=t.dom.value)&&this._onMultiSelectStart(e));t&&t.onEvent(e)},h._startDragDistance=function(e){this.dragDistanceEvent={initialTarget:e.target,initialPageX:e.pageX,initialPageY:e.pageY,dragDistance:0,hasMoved:!1}},h._updateDragDistance=function(e){this.dragDistanceEvent||this._startDragDistance(e);var t=e.pageX-this.dragDistanceEvent.initialPageX,i=e.pageY-this.dragDistanceEvent.initialPageY;return this.dragDistanceEvent.dragDistance=Math.sqrt(t*t+i*i),this.dragDistanceEvent.hasMoved=this.dragDistanceEvent.hasMoved||this.dragDistanceEvent.dragDistance>10,e.dragDistance=this.dragDistanceEvent.dragDistance,e.hasMoved=this.dragDistanceEvent.hasMoved,e.dragDistance},h._onMultiSelectStart=function(e){var t=a.getNodeFromTarget(e.target);if("tree"===this.options.mode&&void 0===this.options.onEditable){this.multiselection={start:t||null,end:null,nodes:[]},this._startDragDistance(e);var i=this;this.mousemove||(this.mousemove=c.addEventListener(window,"mousemove",function(e){i._onMultiSelect(e)})),this.mouseup||(this.mouseup=c.addEventListener(window,"mouseup",function(e){i._onMultiSelectEnd(e)}))}},h._onMultiSelect=function(e){if(e.preventDefault(),this._updateDragDistance(e),e.hasMoved){var t=a.getNodeFromTarget(e.target);t&&(null==this.multiselection.start&&(this.multiselection.start=t),this.multiselection.end=t),this.deselect();var i=this.multiselection.start,n=this.multiselection.end||this.multiselection.start;i&&n&&(this.multiselection.nodes=this._findTopLevelNodes(i,n),this.select(this.multiselection.nodes))}},h._onMultiSelectEnd=function(e){this.multiselection.nodes[0]&&this.multiselection.nodes[0].dom.menu.focus(),this.multiselection.start=null,this.multiselection.end=null,this.mousemove&&(c.removeEventListener(window,"mousemove",this.mousemove),delete this.mousemove),this.mouseup&&(c.removeEventListener(window,"mouseup",this.mouseup),delete this.mouseup)},h.deselect=function(e){this.multiselection.nodes.forEach(function(e){e.setSelected(!1)}),this.multiselection.nodes=[],e&&(this.multiselection.start=null,this.multiselection.end=null)},h.select=function(e){if(!Array.isArray(e))return this.select([e]);if(e){this.deselect(),this.multiselection.nodes=e.slice(0);var t=e[0];e.forEach(function(e){e.setSelected(!0,e===t)})}},h._findTopLevelNodes=function(e,t){for(var i=e.getPath(),n=t.getPath(),r=0;r0){var o=i.length>l;if(o){i=i.slice(0,l);var a=this.validateSchema.errors.length-l;i.push("("+a+" more errors...)")}var c=document.createElement("div");c.innerHTML=''+i.map(function(e){var t;return t="string"==typeof e?'":"",''+t+""}).join("")+"
'+e+"
"+e.dataPath+""+e.message+"
",this.dom.validationErrors=c,this.frame.appendChild(c);var h=c.clientHeight;this.content.style.marginBottom=-h+"px",this.content.style.paddingBottom=h+"px"}if(this.aceEditor){var d=!1;this.aceEditor.resize(d)}},e.exports=[{mode:"text",mixin:a,data:"text",load:a.format},{mode:"code",mixin:a,data:"text",load:a.format}]},function(e,t,i){var n=i(12);t.parse=function(e){try{return JSON.parse(e)}catch(i){throw t.validate(e),i}},t.sanitize=function(e){function t(){return e.charAt(h)}function i(){return e.charAt(h+1)}function n(){return e.charAt(h-1)}function r(){for(var e=c.length-1;e>=0;){var t=c[e];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)return t;e--}return""}function o(){for(h+=2;hn;n++){var o=i[n];o.style&&o.removeAttribute("style");var s=o.attributes;if(s)for(var a=s.length-1;a>=0;a--){var l=s[a];l.specified===!0&&o.removeAttribute(l.name)}t.stripFormatting(o)}},t.setEndOfContentEditable=function(e){var t,i;document.createRange&&(t=document.createRange(),t.selectNodeContents(e),t.collapse(!1),i=window.getSelection(),i.removeAllRanges(),i.addRange(t))},t.selectContentEditable=function(e){if(e&&"DIV"==e.nodeName){var t,i;window.getSelection&&document.createRange&&(i=document.createRange(),i.selectNodeContents(e),t=window.getSelection(),t.removeAllRanges(),t.addRange(i))}},t.getSelection=function(){if(window.getSelection){var e=window.getSelection();if(e.getRangeAt&&e.rangeCount)return e.getRangeAt(0)}return null},t.setSelection=function(e){if(e&&window.getSelection){var t=window.getSelection();t.removeAllRanges(),t.addRange(e)}},t.getSelectionOffset=function(){var e=t.getSelection();return e&&"startOffset"in e&&"endOffset"in e&&e.startContainer&&e.startContainer==e.endContainer?{startOffset:e.startOffset,endOffset:e.endOffset,container:e.startContainer.parentNode}:null},t.setSelectionOffset=function(e){if(document.createRange&&window.getSelection){var i=window.getSelection();if(i){var n=document.createRange();e.container.firstChild||e.container.appendChild(document.createTextNode("")),n.setStart(e.container.firstChild,e.startOffset),n.setEnd(e.container.firstChild,e.endOffset),t.setSelection(n)}}},t.getInnerText=function(e,i){var n=void 0==i;if(n&&(i={text:"",flush:function(){var e=this.text;return this.text="",e},set:function(e){this.text=e}}),e.nodeValue)return i.flush()+e.nodeValue;if(e.hasChildNodes()){for(var r=e.childNodes,o="",s=0,a=r.length;a>s;s++){var l=r[s];if("DIV"==l.nodeName||"P"==l.nodeName){var c=r[s-1],h=c?c.nodeName:void 0;h&&"DIV"!=h&&"P"!=h&&"BR"!=h&&(o+="\n",i.flush()),o+=t.getInnerText(l,i),i.set("\n")}else"BR"==l.nodeName?(o+=i.flush(),i.set("\n")):o+=t.getInnerText(l,i)}return o}return"P"==e.nodeName&&-1!=t.getInternetExplorerVersion()?i.flush():""},t.getInternetExplorerVersion=function(){if(-1==o){var e=-1;if("Microsoft Internet Explorer"==navigator.appName){var t=navigator.userAgent,i=new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})");null!=i.exec(t)&&(e=parseFloat(RegExp.$1))}o=e}return o},t.isFirefox=function(){return-1!=navigator.userAgent.indexOf("Firefox")};var o=-1;t.addEventListener=function(e,i,n,r){if(e.addEventListener)return void 0===r&&(r=!1),"mousewheel"===i&&t.isFirefox()&&(i="DOMMouseScroll"),e.addEventListener(i,n,r),n;if(e.attachEvent){var o=function(){return n.call(e,window.event)};return e.attachEvent("on"+i,o),o}},t.removeEventListener=function(e,i,n,r){e.removeEventListener?(void 0===r&&(r=!1),"mousewheel"===i&&t.isFirefox()&&(i="DOMMouseScroll"),e.removeEventListener(i,n,r)):e.detachEvent&&e.detachEvent("on"+i,n)},t.parsePath=function s(e){var t,i;if(0===e.length)return[];var n=e.match(/^\.(\w+)/);if(n)t=n[1],i=e.substr(t.length+1);else{if("["!==e[0])throw new SyntaxError("Failed to parse path");var r=e.indexOf("]");if(-1===r)throw new SyntaxError("Character ] expected in path");if(1===r)throw new SyntaxError("Index expected after [");t=JSON.parse(e.substring(1,r)),i=e.substr(r+1)}return[t].concat(s(i))},t.improveSchemaError=function(e){if("enum"===e.keyword&&Array.isArray(e.schema)){var t=e.schema;if(t){if(t=t.map(function(e){return JSON.stringify(e)}),t.length>5){var i=["("+(t.length-5)+" more...)"];t=t.slice(0,5),t.push(i)}e.message="should be equal to one of: "+t.join(", ")}}return e},t.insideRect=function(e,t,i){var n=void 0!==i?i:0;return t.left-n>=e.left&&t.right+n<=e.right&&t.top-n>=e.top&&t.bottom+n<=e.bottom},t.debounce=function(e,t,i){var n;return function(){var r=this,o=arguments,s=function(){n=null,i||e.apply(r,o)},a=i&&!n;clearTimeout(n),n=setTimeout(s,t),a&&e.apply(r,o)}},t.textDiff=function(e,t){for(var i=t.length,n=0,r=e.length,o=t.length;t.charAt(n)===e.charAt(n)&&i>n;)n++;for(;t.charAt(o-1)===e.charAt(r-1)&&o>n&&r>0;)o--,r--;return{start:n,end:o}}},function(e,t,i){"use strict";function n(e){return p.test(e)}function r(e){function t(e,t){var i;if("string"==typeof e){if(i=A(e),!i)throw new Error('no schema with key or ref "'+e+'"')}else{var n=E(e);i=n.validate||b(n)}var r=i(t);return k.errors=i.errors,r}function g(e){var t=E(e);return t.validate||b(t)}function m(e,t,i,n){if(Array.isArray(e))for(var r=0;r=0},n.prototype.canRedo=function(){return this.indexthis.results.length-1&&(t=0),this._setActiveResult(t,e)}},n.prototype.previous=function(e){if(void 0!=this.results){var t=this.results.length-1,i=void 0!=this.resultIndex?this.resultIndex-1:t;0>i&&(i=t),this._setActiveResult(i,e)}},n.prototype._setActiveResult=function(e,t){if(this.activeResult){var i=this.activeResult.node,n=this.activeResult.elem;"field"==n?delete i.searchFieldActive:delete i.searchValueActive,i.updateDom()}if(!this.results||!this.results[e])return this.resultIndex=void 0,void(this.activeResult=void 0);this.resultIndex=e;var r=this.results[this.resultIndex].node,o=this.results[this.resultIndex].elem;"field"==o?r.searchFieldActive=!0:r.searchValueActive=!0,this.activeResult=this.results[this.resultIndex],r.updateDom(),r.scrollTo(function(){t&&r.focus(o)})},n.prototype._clearDelay=function(){void 0!=this.timeout&&(clearTimeout(this.timeout),delete this.timeout)},n.prototype._onDelayedSearch=function(e){this._clearDelay();var t=this;this.timeout=setTimeout(function(e){t._onSearch()},this.delay)},n.prototype._onSearch=function(e){this._clearDelay();var t=this.dom.search.value,i=t.length>0?t:void 0;if(i!=this.lastText||e)if(this.lastText=i,this.results=this.editor.search(i),this._setActiveResult(void 0),void 0!=i){var n=this.results.length;switch(n){case 0:this.dom.results.innerHTML="no results";break;case 1:this.dom.results.innerHTML="1 result";break;default:this.dom.results.innerHTML=n+" results"}}else this.dom.results.innerHTML=""},n.prototype._onKeyDown=function(e){var t=e.which;27==t?(this.dom.search.value="",this._onSearch(),e.preventDefault(),e.stopPropagation()):13==t&&(e.ctrlKey?this._onSearch(!0):e.shiftKey?this.previous():this.next(),e.preventDefault(),e.stopPropagation())},n.prototype._onKeyUp=function(e){var t=e.keyCode;27!=t&&13!=t&&this._onDelayedSearch(e)},n.prototype.clear=function(){this.dom.search.value="",this._onSearch()},e.exports=n},function(e,t,i){function n(e,t){function i(e,t,r){r.forEach(function(r){if("separator"==r.type){var o=document.createElement("div");o.className="jsoneditor-separator",a=document.createElement("li"),a.appendChild(o),e.appendChild(a)}else{var s={},a=document.createElement("li");e.appendChild(a);var l=document.createElement("button");if(l.className=r.className,s.button=l,r.title&&(l.title=r.title),r.click&&(l.onclick=function(e){e.preventDefault(),n.hide(),r.click()}),a.appendChild(l),r.submenu){var c=document.createElement("div");c.className="jsoneditor-icon",l.appendChild(c),l.appendChild(document.createTextNode(r.text));var h;if(r.click){l.className+=" jsoneditor-default";var d=document.createElement("button");s.buttonExpand=d,d.className="jsoneditor-expand",d.innerHTML='
',a.appendChild(d),r.submenuTitle&&(d.title=r.submenuTitle),h=d}else{var u=document.createElement("div");u.className="jsoneditor-expand",l.appendChild(u),h=l}h.onclick=function(e){e.preventDefault(),n._onExpandItem(s),h.focus()};var f=[];s.subItems=f;var p=document.createElement("ul");s.ul=p,p.className="jsoneditor-menu",p.style.height="0",a.appendChild(p),i(p,f,r.submenu)}else l.innerHTML='
'+r.text;t.push(s)}})}this.dom={};var n=this,r=this.dom;this.anchor=void 0,this.items=e,this.eventListeners={},this.selection=void 0,this.onClose=t?t.close:void 0;var o=document.createElement("div");o.className="jsoneditor-contextmenu-root",r.root=o;var s=document.createElement("div");s.className="jsoneditor-contextmenu",r.menu=s,o.appendChild(s);var a=document.createElement("ul");a.className="jsoneditor-menu",s.appendChild(a),r.list=a,r.items=[];var l=document.createElement("button");r.focusButton=l;var c=document.createElement("li");c.style.overflow="hidden",c.style.height="0",c.appendChild(l),a.appendChild(c),i(a,this.dom.items,e),this.maxHeight=0,e.forEach(function(t){var i=24*(e.length+(t.submenu?t.submenu.length:0));n.maxHeight=Math.max(n.maxHeight,i)})}var r=i(3);n.prototype._getVisibleButtons=function(){var e=[],t=this;return this.dom.items.forEach(function(i){e.push(i.button),i.buttonExpand&&e.push(i.buttonExpand),i.subItems&&i==t.expandedItem&&i.subItems.forEach(function(t){e.push(t.button),t.buttonExpand&&e.push(t.buttonExpand)})}),e},n.visibleMenu=void 0,n.prototype.show=function(e,t){this.hide();var i=!0;if(t){var o=e.getBoundingClientRect(),s=t.getBoundingClientRect();o.bottom+this.maxHeights.top&&(i=!1)}if(i){var a=e.offsetHeight;this.dom.menu.style.left="0px",this.dom.menu.style.top=a+"px",this.dom.menu.style.bottom=""}else this.dom.menu.style.left="0px",this.dom.menu.style.top="",this.dom.menu.style.bottom="0px";var l=e.parentNode;l.insertBefore(this.dom.root,l.firstChild);var c=this,h=this.dom.list;this.eventListeners.mousedown=r.addEventListener(window,"mousedown",function(e){var t=e.target;t==h||c._isChildOf(t,h)||(c.hide(),e.stopPropagation(),e.preventDefault())}),this.eventListeners.keydown=r.addEventListener(window,"keydown",function(e){c._onKeyDown(e)}),this.selection=r.getSelection(),this.anchor=e,setTimeout(function(){c.dom.focusButton.focus()},0),n.visibleMenu&&n.visibleMenu.hide(),n.visibleMenu=this},n.prototype.hide=function(){this.dom.root.parentNode&&(this.dom.root.parentNode.removeChild(this.dom.root),this.onClose&&this.onClose());for(var e in this.eventListeners)if(this.eventListeners.hasOwnProperty(e)){var t=this.eventListeners[e];t&&r.removeEventListener(window,e,t),delete this.eventListeners[e]}n.visibleMenu==this&&(n.visibleMenu=void 0)},n.prototype._onExpandItem=function(e){var t=this,i=e==this.expandedItem,n=this.expandedItem;if(n&&(n.ul.style.height="0",n.ul.style.padding="",setTimeout(function(){t.expandedItem!=n&&(n.ul.style.display="",r.removeClassName(n.ul.parentNode,"jsoneditor-selected"))},300),this.expandedItem=void 0),!i){var o=e.ul;o.style.display="block";o.clientHeight;setTimeout(function(){t.expandedItem==e&&(o.style.height=24*o.childNodes.length+"px",o.style.padding="5px 10px")},0),r.addClassName(o.parentNode,"jsoneditor-selected"),this.expandedItem=e}},n.prototype._onKeyDown=function(e){var t,i,n,o,s=e.target,a=e.which,l=!1;27==a?(this.selection&&r.setSelection(this.selection),this.anchor&&this.anchor.focus(),this.hide(),l=!0):9==a?e.shiftKey?(t=this._getVisibleButtons(),i=t.indexOf(s),0==i&&(t[t.length-1].focus(),l=!0)):(t=this._getVisibleButtons(),i=t.indexOf(s),i==t.length-1&&(t[0].focus(),l=!0)):37==a?("jsoneditor-expand"==s.className&&(t=this._getVisibleButtons(),i=t.indexOf(s),n=t[i-1],n&&n.focus()),l=!0):38==a?(t=this._getVisibleButtons(),i=t.indexOf(s),n=t[i-1],n&&"jsoneditor-expand"==n.className&&(n=t[i-2]),n||(n=t[t.length-1]),n&&n.focus(),l=!0):39==a?(t=this._getVisibleButtons(),i=t.indexOf(s),o=t[i+1],o&&"jsoneditor-expand"==o.className&&o.focus(),l=!0):40==a&&(t=this._getVisibleButtons(),i=t.indexOf(s),o=t[i+1],o&&"jsoneditor-expand"==o.className&&(o=t[i+2]),o||(o=t[0]),o&&(o.focus(),l=!0),l=!0),l&&(e.stopPropagation(),e.preventDefault())},n.prototype._isChildOf=function(e,t){for(var i=e.parentNode;i;){if(i==t)return!0;i=i.parentNode}return!1},e.exports=n},function(e,t,i){function n(e,t){this.editor=e,this.dom={},this.expanded=!1,t&&t instanceof Object?(this.setField(t.field,t.fieldEditable),this.setValue(t.value,t.type)):(this.setField(""),this.setValue(null)),this._debouncedOnChangeValue=s.debounce(this._onChangeValue.bind(this),n.prototype.DEBOUNCE_INTERVAL),this._debouncedOnChangeField=s.debounce(this._onChangeField.bind(this),n.prototype.DEBOUNCE_INTERVAL)}var r=i(9),o=i(21),s=i(3);n.prototype.DEBOUNCE_INTERVAL=150,n.prototype._updateEditability=function(){if(this.editable={field:!0,value:!0},this.editor&&(this.editable.field="tree"===this.editor.options.mode,this.editable.value="view"!==this.editor.options.mode,("tree"===this.editor.options.mode||"form"===this.editor.options.mode)&&"function"==typeof this.editor.options.onEditable)){var e=this.editor.options.onEditable({field:this.field,value:this.value,path:this.getFieldsPath()});"boolean"==typeof e?(this.editable.field=e,this.editable.value=e):("boolean"==typeof e.field&&(this.editable.field=e.field),"boolean"==typeof e.value&&(this.editable.value=e.value))}},n.prototype.getFieldsPath=function(){for(var e=this,t=[];e;){var i=void 0!=e.field?e.field:e.index;void 0!==i&&t.unshift(i),e=e.parent}return t},n.prototype.findNode=function(e){for(var t=s.parsePath(e),i=this;i&&t.length>0;){var n=t.shift();if("number"==typeof n){if("array"!==i.type)throw new Error("Cannot get child node at index "+n+": node is no array");i=i.childs[n]}else{if("object"!==i.type)throw new Error("Cannot get child node "+n+": node is no object");i=i.childs.filter(function(e){return e.field===n})[0]}}return i},n.prototype.findParents=function(){for(var e=[],t=this.parent;t;)e.unshift(t),t=t.parent;return e},n.prototype.setError=function(e,t){this.getDom(),this.error=e;var i=this.dom.tdError;if(e){i||(i=document.createElement("td"),this.dom.tdError=i,this.dom.tdValue.parentNode.appendChild(i));var n=document.createElement("div");n.className="jsoneditor-popover jsoneditor-right",n.appendChild(document.createTextNode(e.message));var r=document.createElement("button");for(r.className="jsoneditor-schema-error",r.appendChild(n),r.onmouseover=r.onfocus=function(){for(var e=["right","above","below","left"],t=0;ts;s++)i=e[s],void 0===i||i instanceof Function||(r=new n(this.editor,{value:i}),this.appendChild(r));this.value=""}else if("object"==this.type){this.childs=[];for(var l in e)e.hasOwnProperty(l)&&(i=e[l],void 0===i||i instanceof Function||(r=new n(this.editor,{field:l,value:i}),this.appendChild(r)));this.value=""}else this.childs=void 0,this.value=e;this.previousValue=this.value},n.prototype.getValue=function(){if("array"==this.type){var e=[];return this.childs.forEach(function(t){e.push(t.getValue())}),e}if("object"==this.type){var t={};return this.childs.forEach(function(e){t[e.getField()]=e.getValue()}),t}return void 0===this.value&&this._getDomValue(),this.value},n.prototype.getLevel=function(){return this.parent?this.parent.getLevel()+1:0},n.prototype.getPath=function(){var e=this.parent?this.parent.getPath():[];return e.push(this),e},n.prototype.clone=function(){var e=new n(this.editor);if(e.type=this.type,e.field=this.field,e.fieldInnerText=this.fieldInnerText,e.fieldEditable=this.fieldEditable,e.value=this.value,e.valueInnerText=this.valueInnerText,e.expanded=this.expanded,this.childs){var t=[];this.childs.forEach(function(i){var n=i.clone();n.setParent(e),t.push(n)}),e.childs=t}else e.childs=void 0;return e},n.prototype.expand=function(e){this.childs&&(this.expanded=!0,this.dom.expand&&(this.dom.expand.className="jsoneditor-expanded"),this.showChilds(),e!==!1&&this.childs.forEach(function(t){t.expand(e)}))},n.prototype.collapse=function(e){this.childs&&(this.hideChilds(),e!==!1&&this.childs.forEach(function(t){t.collapse(e)}),this.dom.expand&&(this.dom.expand.className="jsoneditor-collapsed"),this.expanded=!1)},n.prototype.showChilds=function(){var e=this.childs;if(e&&this.expanded){var t=this.dom.tr,i=t?t.parentNode:void 0;if(i){var n=this.getAppend(),r=t.nextSibling;r?i.insertBefore(n,r):i.appendChild(n),this.childs.forEach(function(e){i.insertBefore(e.getDom(),n),e.showChilds()})}}},n.prototype.hide=function(){var e=this.dom.tr,t=e?e.parentNode:void 0;t&&t.removeChild(e),this.hideChilds()},n.prototype.hideChilds=function(){var e=this.childs;if(e&&this.expanded){var t=this.getAppend();t.parentNode&&t.parentNode.removeChild(t),this.childs.forEach(function(e){e.hide()})}},n.prototype.appendChild=function(e){if(this._hasChilds()){if(e.setParent(this),e.fieldEditable="object"==this.type,"array"==this.type&&(e.index=this.childs.length),this.childs.push(e),this.expanded){var t=e.getDom(),i=this.getAppend(),n=i?i.parentNode:void 0;i&&n&&n.insertBefore(t,i),e.showChilds()}this.updateDom({updateIndexes:!0}),e.updateDom({recurse:!0})}},n.prototype.moveBefore=function(e,t){if(this._hasChilds()){var i=this.dom.tr?this.dom.tr.parentNode:void 0;if(i){var n=document.createElement("tr");n.style.height=i.clientHeight+"px",i.appendChild(n)}e.parent&&e.parent.removeChild(e),t instanceof a?this.appendChild(e):this.insertBefore(e,t),i&&i.removeChild(n)}},n.prototype.moveTo=function(e,t){if(e.parent==this){var i=this.childs.indexOf(e);t>i&&t++}var n=this.childs[t]||this.append;this.moveBefore(e,n)},n.prototype.insertBefore=function(e,t){if(this._hasChilds()){if(t==this.append)e.setParent(this),e.fieldEditable="object"==this.type,this.childs.push(e);else{var i=this.childs.indexOf(t);if(-1==i)throw new Error("Node not found");e.setParent(this),e.fieldEditable="object"==this.type,this.childs.splice(i,0,e)}if(this.expanded){var n=e.getDom(),r=t.getDom(),o=r?r.parentNode:void 0;r&&o&&o.insertBefore(n,r),e.showChilds()}this.updateDom({updateIndexes:!0}),e.updateDom({recurse:!0})}},n.prototype.insertAfter=function(e,t){if(this._hasChilds()){var i=this.childs.indexOf(t),n=this.childs[i+1];n?this.insertBefore(e,n):this.appendChild(e)}},n.prototype.search=function(e){var t,i=[],n=e?e.toLowerCase():void 0;if(delete this.searchField,delete this.searchValue,void 0!=this.field){var r=String(this.field).toLowerCase();t=r.indexOf(n),-1!=t&&(this.searchField=!0,i.push({node:this,elem:"field"})),this._updateDomField()}if(this._hasChilds()){if(this.childs){var o=[];this.childs.forEach(function(t){o=o.concat(t.search(e))}),i=i.concat(o)}if(void 0!=n){var s=!1;0==o.length?this.collapse(s):this.expand(s)}}else{if(void 0!=this.value){var a=String(this.value).toLowerCase();t=a.indexOf(n),-1!=t&&(this.searchValue=!0,i.push({node:this,elem:"value"}))}this._updateDomValue()}return i},n.prototype.scrollTo=function(e){if(!this.dom.tr||!this.dom.tr.parentNode)for(var t=this.parent,i=!1;t;)t.expand(i),t=t.parent;this.dom.tr&&this.dom.tr.parentNode&&this.editor.scrollTo(this.dom.tr.offsetTop,e)},n.focusElement=void 0,n.prototype.focus=function(e){if(n.focusElement=e,this.dom.tr&&this.dom.tr.parentNode){var t=this.dom;switch(e){case"drag":t.drag?t.drag.focus():t.menu.focus();break;case"menu":t.menu.focus();break;case"expand":this._hasChilds()?t.expand.focus():t.field&&this.fieldEditable?(t.field.focus(),s.selectContentEditable(t.field)):t.value&&!this._hasChilds()?(t.value.focus(),s.selectContentEditable(t.value)):t.menu.focus();break;case"field":t.field&&this.fieldEditable?(t.field.focus(),s.selectContentEditable(t.field)):t.value&&!this._hasChilds()?(t.value.focus(),s.selectContentEditable(t.value)):this._hasChilds()?t.expand.focus():t.menu.focus();break;case"value":default:t.value&&!this._hasChilds()?(t.value.focus(),s.selectContentEditable(t.value)):t.field&&this.fieldEditable?(t.field.focus(),s.selectContentEditable(t.field)):this._hasChilds()?t.expand.focus():t.menu.focus()}}},n.select=function(e){setTimeout(function(){s.selectContentEditable(e)},0)},n.prototype.blur=function(){this._getDomValue(!1),this._getDomField(!1)},n.prototype.containsNode=function(e){if(this==e)return!0;var t=this.childs;if(t)for(var i=0,n=t.length;n>i;i++)if(t[i].containsNode(e))return!0;return!1},n.prototype._move=function(e,t){if(e!=t){if(e.containsNode(this))throw new Error("Cannot move a field into a child of itself");e.parent&&e.parent.removeChild(e);var i=e.clone();e.clearDom(),t?this.insertBefore(i,t):this.appendChild(i)}},n.prototype.removeChild=function(e){if(this.childs){var t=this.childs.indexOf(e);if(-1!=t){e.hide(),delete e.searchField,delete e.searchValue;var i=this.childs.splice(t,1)[0];return i.parent=null,this.updateDom({updateIndexes:!0}),i}}return void 0},n.prototype._remove=function(e){this.removeChild(e)},n.prototype.changeType=function(e){var t=this.type;if(t!=e){if("string"!=e&&"auto"!=e||"string"!=t&&"auto"!=t){var i,n=this.dom.tr?this.dom.tr.parentNode:void 0;i=this.expanded?this.getAppend():this.getDom();var r=i&&i.parentNode?i.nextSibling:void 0;this.hide(),this.clearDom(),this.type=e,"object"==e?(this.childs||(this.childs=[]),this.childs.forEach(function(e,t){e.clearDom(),delete e.index,e.fieldEditable=!0,void 0==e.field&&(e.field="")}),("string"==t||"auto"==t)&&(this.expanded=!0)):"array"==e?(this.childs||(this.childs=[]),this.childs.forEach(function(e,t){e.clearDom(),e.fieldEditable=!1,e.index=t}),("string"==t||"auto"==t)&&(this.expanded=!0)):this.expanded=!1,n&&(r?n.insertBefore(this.getDom(),r):n.appendChild(this.getDom())),this.showChilds()}else this.type=e;("auto"==e||"string"==e)&&("string"==e?this.value=String(this.value):this.value=this._stringCast(String(this.value)),this.focus()),this.updateDom({updateIndexes:!0})}},n.prototype._getDomValue=function(e){if(this.dom.value&&"array"!=this.type&&"object"!=this.type&&(this.valueInnerText=s.getInnerText(this.dom.value)),void 0!=this.valueInnerText)try{var t;if("string"==this.type)t=this._unescapeHTML(this.valueInnerText);else{var i=this._unescapeHTML(this.valueInnerText);t=this._stringCast(i)}t!==this.value&&(this.value=t,this._debouncedOnChangeValue())}catch(n){if(this.value=void 0,e!==!0)throw n}},n.prototype._onChangeValue=function(){var e=this.editor.getSelection();if(e.range){var t=s.textDiff(String(this.value),String(this.previousValue));e.range.startOffset=t.start,e.range.endOffset=t.end}var i=this.editor.getSelection();if(i.range){var n=s.textDiff(String(this.previousValue),String(this.value));i.range.startOffset=n.start,i.range.endOffset=n.end}this.editor._onAction("editValue",{node:this,oldValue:this.previousValue,newValue:this.value,oldSelection:e,newSelection:i}),this.previousValue=this.value},n.prototype._onChangeField=function(){var e=this.editor.getSelection();if(e.range){var t=s.textDiff(this.field,this.previousField);e.range.startOffset=t.start,e.range.endOffset=t.end}var i=this.editor.getSelection();if(i.range){var n=s.textDiff(this.previousField,this.field);i.range.startOffset=n.start,i.range.endOffset=n.end}this.editor._onAction("editField",{node:this,oldValue:this.previousField,newValue:this.field,oldSelection:e,newSelection:i}),this.previousField=this.field},n.prototype._updateDomValue=function(){var e=this.dom.value;if(e){var t=["jsoneditor-value"],i=this.value,n="auto"==this.type?s.type(i):this.type,r="string"==n&&s.isUrl(i);t.push("jsoneditor-"+n),r&&t.push("jsoneditor-url");var o=""==String(this.value)&&"array"!=this.type&&"object"!=this.type;if(o&&t.push("jsoneditor-empty"),this.searchValueActive&&t.push("jsoneditor-highlight-active"),this.searchValue&&t.push("jsoneditor-highlight"),e.className=t.join(" "),"array"==n||"object"==n){var a=this.childs?this.childs.length:0;e.title=this.type+" containing "+a+" items"}else r&&this.editable.value?e.title="Ctrl+Click or Ctrl+Enter to open url in new window":e.title="";"boolean"===n&&this.editable.value?(this.dom.checkbox||(this.dom.checkbox=document.createElement("input"),this.dom.checkbox.type="checkbox",this.dom.tdCheckbox=document.createElement("td"),this.dom.tdCheckbox.className="jsoneditor-tree",this.dom.tdCheckbox.appendChild(this.dom.checkbox),this.dom.tdValue.parentNode.insertBefore(this.dom.tdCheckbox,this.dom.tdValue)),this.dom.checkbox.checked=this.value):this.dom.tdCheckbox&&(this.dom.tdCheckbox.parentNode.removeChild(this.dom.tdCheckbox),delete this.dom.tdCheckbox,delete this.dom.checkbox),s.stripFormatting(e)}},n.prototype._updateDomField=function(){var e=this.dom.field;if(e){var t=""==String(this.field)&&"array"!=this.parent.type;t?s.addClassName(e,"jsoneditor-empty"):s.removeClassName(e,"jsoneditor-empty"),this.searchFieldActive?s.addClassName(e,"jsoneditor-highlight-active"):s.removeClassName(e,"jsoneditor-highlight-active"),this.searchField?s.addClassName(e,"jsoneditor-highlight"):s.removeClassName(e,"jsoneditor-highlight"),s.stripFormatting(e)}},n.prototype._getDomField=function(e){if(this.dom.field&&this.fieldEditable&&(this.fieldInnerText=s.getInnerText(this.dom.field)),void 0!=this.fieldInnerText)try{var t=this._unescapeHTML(this.fieldInnerText);t!==this.field&&(this.field=t,this._debouncedOnChangeField())}catch(i){if(this.field=void 0,e!==!0)throw i}},n.prototype.validate=function(){var e=[];if("object"===this.type){for(var t={},i=[],n=0;n0&&(e=this.childs.filter(function(e){return-1!==i.indexOf(e.field)}).map(function(e){return{node:e,error:{message:'duplicate key "'+e.field+'"'}}}))}if(this.childs)for(var n=0;n0&&(e=e.concat(o))}return e},n.prototype.clearDom=function(){this.dom={}},n.prototype.getDom=function(){var e=this.dom;if(e.tr)return e.tr;if(this._updateEditability(),e.tr=document.createElement("tr"),e.tr.node=this,"tree"===this.editor.options.mode){var t=document.createElement("td");if(this.editable.field&&this.parent){var i=document.createElement("button");e.drag=i,i.className="jsoneditor-dragarea",i.title="Drag to move this field (Alt+Shift+Arrows)",t.appendChild(i)}e.tr.appendChild(t);var n=document.createElement("td"),r=document.createElement("button");e.menu=r,r.className="jsoneditor-contextmenu",r.title="Click to open the actions menu (Ctrl+M)",n.appendChild(e.menu),e.tr.appendChild(n)}var o=document.createElement("td");return e.tr.appendChild(o),e.tree=this._createDomTree(),o.appendChild(e.tree),this.updateDom({updateIndexes:!0}),e.tr},n.onDragStart=function(e,t){if(!Array.isArray(e))return n.onDragStart([e],t);if(0!==e.length){var i=e[0],r=e[e.length-1],o=n.getNodeFromTarget(t.target),a=r._nextSibling(),l=i.editor,c=s.getAbsoluteTop(o.dom.tr)-s.getAbsoluteTop(i.dom.tr);l.mousemove||(l.mousemove=s.addEventListener(window,"mousemove",function(t){n.onDrag(e,t)})),l.mouseup||(l.mouseup=s.addEventListener(window,"mouseup",function(t){n.onDragEnd(e,t)})),l.highlighter.lock(),l.drag={oldCursor:document.body.style.cursor,oldSelection:l.getSelection(),oldBeforeNode:a,mouseX:t.pageX,offsetY:c,level:i.getLevel()},document.body.style.cursor="move",t.preventDefault()}},n.onDrag=function(e,t){if(!Array.isArray(e))return n.onDrag([e],t);if(0!==e.length){var i,r,o,l,c,h,d,u,f,p,g,m,v,w,A=e[0].editor,y=t.pageY-A.drag.offsetY,C=t.pageX,E=!1,b=e[0];if(i=b.dom.tr,f=s.getAbsoluteTop(i),m=i.offsetHeight,f>y){r=i;do r=r.previousSibling,d=n.getNodeFromTarget(r),p=r?s.getAbsoluteTop(r):0;while(r&&p>y);d&&!d.parent&&(d=void 0),d||(h=i.parentNode.firstChild,r=h?h.nextSibling:void 0,d=n.getNodeFromTarget(r),d==b&&(d=void 0)),d&&(r=d.dom.tr,p=r?s.getAbsoluteTop(r):0,y>p+m&&(d=void 0)),d&&(e.forEach(function(e){d.parent.moveBefore(e,d)}),E=!0)}else{var F=e[e.length-1];if(c=F.expanded&&F.append?F.append.getDom():F.dom.tr,l=c?c.nextSibling:void 0){g=s.getAbsoluteTop(l),o=l;do u=n.getNodeFromTarget(o),o&&(v=o.nextSibling?s.getAbsoluteTop(o.nextSibling):0,w=o?v-g:0,u.parent.childs.length==e.length&&u.parent.childs[e.length-1]==F&&(f+=27)),o=o.nextSibling;while(o&&y>f+w);if(u&&u.parent){var x=C-A.drag.mouseX,S=Math.round(x/24/2),$=A.drag.level+S,D=u.getLevel();for(r=u.dom.tr.previousSibling;$>D&&r;){d=n.getNodeFromTarget(r);var k=e.some(function(e){return e===d||d._isChildOf(e)});if(k);else{if(!(d instanceof a))break;var B=d.parent.childs;if(B.length==e.length&&B[e.length-1]==F)break;u=n.getNodeFromTarget(r),D=u.getLevel()}r=r.previousSibling}c.nextSibling!=u.dom.tr&&(e.forEach(function(e){u.parent.moveBefore(e,u)}),E=!0)}}}E&&(A.drag.mouseX=C,A.drag.level=b.getLevel()),A.startAutoScroll(y),t.preventDefault()}},n.onDragEnd=function(e,t){if(!Array.isArray(e))return n.onDrag([e],t);if(0!==e.length){var i=e[0],r=i.editor,o=i.parent,a=o.childs.indexOf(i),l=o.childs[a+e.length]||o.append;e[0]&&e[0].dom.menu.focus();var c={nodes:e,oldSelection:r.drag.oldSelection,newSelection:r.getSelection(),oldBeforeNode:r.drag.oldBeforeNode,newBeforeNode:l};c.oldBeforeNode!=c.newBeforeNode&&r._onAction("moveNodes",c),document.body.style.cursor=r.drag.oldCursor,r.highlighter.unlock(),e.forEach(function(e){t.target!==e.dom.drag&&t.target!==e.dom.menu&&r.highlighter.unhighlight()}),delete r.drag,r.mousemove&&(s.removeEventListener(window,"mousemove",r.mousemove),delete r.mousemove),r.mouseup&&(s.removeEventListener(window,"mouseup",r.mouseup),delete r.mouseup),r.stopAutoScroll(),t.preventDefault()}},n.prototype._isChildOf=function(e){for(var t=this.parent;t;){if(t==e)return!0;t=t.parent}return!1},n.prototype._createDomField=function(){return document.createElement("div")},n.prototype.setHighlight=function(e){this.dom.tr&&(e?s.addClassName(this.dom.tr,"jsoneditor-highlight"):s.removeClassName(this.dom.tr,"jsoneditor-highlight"),this.append&&this.append.setHighlight(e),this.childs&&this.childs.forEach(function(t){t.setHighlight(e)}))},n.prototype.setSelected=function(e,t){this.selected=e,this.dom.tr&&(e?s.addClassName(this.dom.tr,"jsoneditor-selected"):s.removeClassName(this.dom.tr,"jsoneditor-selected"),t?s.addClassName(this.dom.tr,"jsoneditor-first"):s.removeClassName(this.dom.tr,"jsoneditor-first"), -this.append&&this.append.setSelected(e),this.childs&&this.childs.forEach(function(t){t.setSelected(e)}))},n.prototype.updateValue=function(e){this.value=e,this.updateDom()},n.prototype.updateField=function(e){this.field=e,this.updateDom()},n.prototype.updateDom=function(e){var t=this.dom.tree;t&&(t.style.marginLeft=24*this.getLevel()+"px");var i=this.dom.field;if(i){this.fieldEditable?(i.contentEditable=this.editable.field,i.spellcheck=!1,i.className="jsoneditor-field"):i.className="jsoneditor-readonly";var n;n=void 0!=this.index?this.index:void 0!=this.field?this.field:this._hasChilds()?this.type:"",i.innerHTML=this._escapeHTML(n)}var r=this.dom.value;if(r){var o=this.childs?this.childs.length:0;"array"==this.type?(r.innerHTML="["+o+"]",s.addClassName(this.dom.tr,"jsoneditor-expandable")):"object"==this.type?(r.innerHTML="{"+o+"}",s.addClassName(this.dom.tr,"jsoneditor-expandable")):(r.innerHTML=this._escapeHTML(this.value),s.removeClassName(this.dom.tr,"jsoneditor-expandable"))}this._updateDomField(),this._updateDomValue(),e&&e.updateIndexes===!0&&this._updateDomIndexes(),e&&e.recurse===!0&&this.childs&&this.childs.forEach(function(t){t.updateDom(e)}),this.append&&this.append.updateDom()},n.prototype._updateDomIndexes=function(){var e=this.dom.value,t=this.childs;e&&t&&("array"==this.type?t.forEach(function(e,t){e.index=t;var i=e.dom.field;i&&(i.innerHTML=t)}):"object"==this.type&&t.forEach(function(e){void 0!=e.index&&(delete e.index,void 0==e.field&&(e.field=""))}))},n.prototype._createDomValue=function(){var e;return"array"==this.type?(e=document.createElement("div"),e.innerHTML="[...]"):"object"==this.type?(e=document.createElement("div"),e.innerHTML="{...}"):!this.editable.value&&s.isUrl(this.value)?(e=document.createElement("a"),e.href=this.value,e.target="_blank",e.innerHTML=this._escapeHTML(this.value)):(e=document.createElement("div"),e.contentEditable=this.editable.value,e.spellcheck=!1,e.innerHTML=this._escapeHTML(this.value)),e},n.prototype._createDomExpandButton=function(){var e=document.createElement("button");return this._hasChilds()?(e.className=this.expanded?"jsoneditor-expanded":"jsoneditor-collapsed",e.title="Click to expand/collapse this field (Ctrl+E). \nCtrl+Click to expand/collapse including all childs."):(e.className="jsoneditor-invisible",e.title=""),e},n.prototype._createDomTree=function(){var e=this.dom,t=document.createElement("table"),i=document.createElement("tbody");t.style.borderCollapse="collapse",t.className="jsoneditor-values",t.appendChild(i);var n=document.createElement("tr");i.appendChild(n);var r=document.createElement("td");r.className="jsoneditor-tree",n.appendChild(r),e.expand=this._createDomExpandButton(),r.appendChild(e.expand),e.tdExpand=r;var o=document.createElement("td");o.className="jsoneditor-tree",n.appendChild(o),e.field=this._createDomField(),o.appendChild(e.field),e.tdField=o;var s=document.createElement("td");s.className="jsoneditor-tree",n.appendChild(s),"object"!=this.type&&"array"!=this.type&&(s.appendChild(document.createTextNode(":")),s.className="jsoneditor-separator"),e.tdSeparator=s;var a=document.createElement("td");return a.className="jsoneditor-tree",n.appendChild(a),e.value=this._createDomValue(),a.appendChild(e.value),e.tdValue=a,t},n.prototype.onEvent=function(e){var t,i=e.type,n=e.target||e.srcElement,r=this.dom,o=this,a=this._hasChilds();if((n==r.drag||n==r.menu)&&("mouseover"==i?this.editor.highlighter.highlight(this):"mouseout"==i&&this.editor.highlighter.unhighlight()),"click"==i&&n==r.menu){var l=o.editor.highlighter;l.highlight(o),l.lock(),s.addClassName(r.menu,"jsoneditor-selected"),this.showContextMenu(r.menu,function(){s.removeClassName(r.menu,"jsoneditor-selected"),l.unlock(),l.unhighlight()})}if("click"==i&&(n==r.expand||("view"===o.editor.options.mode||"form"===o.editor.options.mode)&&"DIV"===n.nodeName)&&a){var c=e.ctrlKey;this._onExpand(c)}"change"==i&&n==r.checkbox&&(this.dom.value.innerHTML=!this.value,this._getDomValue());var h=r.value;if(n==h)switch(i){case"focus":t=this;break;case"blur":case"change":this._getDomValue(!0),this._updateDomValue(),this.value&&(h.innerHTML=this._escapeHTML(this.value));break;case"input":this._getDomValue(!0),this._updateDomValue();break;case"keydown":case"mousedown":this.editor.selection=this.editor.getSelection();break;case"click":(e.ctrlKey||!this.editable.value)&&s.isUrl(this.value)&&window.open(this.value,"_blank");break;case"keyup":this._getDomValue(!0),this._updateDomValue();break;case"cut":case"paste":setTimeout(function(){o._getDomValue(!0),o._updateDomValue()},1)}var d=r.field;if(n==d)switch(i){case"focus":t=this;break;case"blur":case"change":this._getDomField(!0),this._updateDomField(),this.field&&(d.innerHTML=this._escapeHTML(this.field));break;case"input":this._getDomField(!0),this._updateDomField();break;case"keydown":case"mousedown":this.editor.selection=this.editor.getSelection();break;case"keyup":this._getDomField(!0),this._updateDomField();break;case"cut":case"paste":setTimeout(function(){o._getDomField(!0),o._updateDomField()},1)}var u=r.tree;if(n==u.parentNode&&"click"==i&&!e.hasMoved){var f=void 0!=e.offsetX?e.offsetX<24*(this.getLevel()+1):e.pageX0?this.editor.multiselection.nodes:[this],y=A[0],C=A[A.length-1];if(13==u){if(f==this.dom.value)(!this.editable.value||e.ctrlKey)&&s.isUrl(this.value)&&(window.open(this.value,"_blank"),v=!0);else if(f==this.dom.expand){var E=this._hasChilds();if(E){var b=e.ctrlKey;this._onExpand(b),f.focus(),v=!0}}}else if(68==u)p&&w&&(n.onDuplicate(A),v=!0);else if(69==u)p&&(this._onExpand(g),f.focus(),v=!0);else if(77==u&&w)p&&(this.showContextMenu(f),v=!0);else if(46==u&&w)p&&(n.onRemove(A),v=!0);else if(45==u&&w)p&&!g?(this._onInsertBefore(),v=!0):p&&g&&(this._onInsertAfter(),v=!0);else if(35==u){if(m){var F=this._lastNode();F&&F.focus(n.focusElement||this._getElementName(f)),v=!0}}else if(36==u){if(m){var x=this._firstNode();x&&x.focus(n.focusElement||this._getElementName(f)),v=!0}}else if(37==u){if(m&&!g){var S=this._previousElement(f);S&&this.focus(this._getElementName(S)),v=!0}else if(m&&g&&w){if(C.expanded){var $=C.getAppend();r=$?$.nextSibling:void 0}else{var D=C.getDom();r=D.nextSibling}r&&(i=n.getNodeFromTarget(r),o=r.nextSibling,_=n.getNodeFromTarget(o),i&&i instanceof a&&1!=C.parent.childs.length&&_&&_.parent&&(l=this.editor.getSelection(),c=C._nextSibling(),A.forEach(function(e){_.parent.moveBefore(e,_)}),this.focus(n.focusElement||this._getElementName(f)),this.editor._onAction("moveNodes",{nodes:A,oldBeforeNode:c,newBeforeNode:_,oldSelection:l,newSelection:this.editor.getSelection()})))}}else if(38==u)m&&!g?(t=this._previousNode(),t&&(this.editor.deselect(!0),t.focus(n.focusElement||this._getElementName(f))),v=!0):!m&&p&&g&&w?(t=this._previousNode(),t&&(d=this.editor.multiselection,d.start=d.start||this,d.end=t,h=this.editor._findTopLevelNodes(d.start,d.end),this.editor.select(h),t.focus("field")),v=!0):m&&g&&w&&(t=y._previousNode(),t&&t.parent&&(l=this.editor.getSelection(),c=C._nextSibling(),A.forEach(function(e){t.parent.moveBefore(e,t)}),this.focus(n.focusElement||this._getElementName(f)),this.editor._onAction("moveNodes",{nodes:A,oldBeforeNode:c,newBeforeNode:t,oldSelection:l,newSelection:this.editor.getSelection()})),v=!0);else if(39==u){if(m&&!g){var k=this._nextElement(f);k&&this.focus(this._getElementName(k)),v=!0}else if(m&&g&&w){D=y.getDom();var B=D.previousSibling;B&&(t=n.getNodeFromTarget(B),t&&t.parent&&t instanceof a&&!t.isVisible()&&(l=this.editor.getSelection(),c=C._nextSibling(),A.forEach(function(e){t.parent.moveBefore(e,t)}),this.focus(n.focusElement||this._getElementName(f)),this.editor._onAction("moveNodes",{nodes:A,oldBeforeNode:c,newBeforeNode:t,oldSelection:l,newSelection:this.editor.getSelection()})))}}else if(40==u)if(m&&!g)i=this._nextNode(),i&&(this.editor.deselect(!0),i.focus(n.focusElement||this._getElementName(f))),v=!0;else if(!m&&p&&g&&w)i=this._nextNode(),i&&(d=this.editor.multiselection,d.start=d.start||this,d.end=i,h=this.editor._findTopLevelNodes(d.start,d.end),this.editor.select(h),i.focus("field")),v=!0;else if(m&&g&&w){i=C.expanded?C.append?C.append._nextNode():void 0:C._nextNode();var _=i&&(i._nextNode()||i.parent.append);_&&_.parent&&(l=this.editor.getSelection(),c=C._nextSibling(),A.forEach(function(e){_.parent.moveBefore(e,_)}),this.focus(n.focusElement||this._getElementName(f)),this.editor._onAction("moveNodes",{nodes:A,oldBeforeNode:c,newBeforeNode:_,oldSelection:l,newSelection:this.editor.getSelection()})),v=!0}v&&(e.preventDefault(),e.stopPropagation())},n.prototype._onExpand=function(e){if(e){var t=this.dom.tr.parentNode,i=t.parentNode,n=i.scrollTop;i.removeChild(t)}this.expanded?this.collapse(e):this.expand(e),e&&(i.appendChild(t),i.scrollTop=n)},n.onRemove=function(e){if(!Array.isArray(e))return n.onRemove([e]);if(e&&e.length>0){var t=e[0],i=t.parent,r=t.editor,o=t.getIndex();r.highlighter.unhighlight();var s=r.getSelection();n.blurNodes(e);var a=r.getSelection();e.forEach(function(e){e.parent._remove(e)}),r._onAction("removeNodes",{nodes:e.slice(0),parent:i,index:o,oldSelection:s,newSelection:a})}},n.onDuplicate=function(e){if(!Array.isArray(e))return n.onDuplicate([e]);if(e&&e.length>0){var t=e[e.length-1],i=t.parent,r=t.editor;r.deselect(r.multiselection.nodes);var o=r.getSelection(),s=t,a=e.map(function(e){var t=e.clone();return i.insertAfter(t,s),s=t,t});1===e.length?a[0].focus():r.select(a);var l=r.getSelection();r._onAction("duplicateNodes",{afterNode:t,nodes:a,parent:i,oldSelection:o,newSelection:l})}},n.prototype._onInsertBefore=function(e,t,i){var r=this.editor.getSelection(),o=new n(this.editor,{field:void 0!=e?e:"",value:void 0!=t?t:"",type:i});o.expand(!0),this.parent.insertBefore(o,this),this.editor.highlighter.unhighlight(),o.focus("field");var s=this.editor.getSelection();this.editor._onAction("insertBeforeNodes",{nodes:[o],beforeNode:this,parent:this.parent,oldSelection:r,newSelection:s})},n.prototype._onInsertAfter=function(e,t,i){var r=this.editor.getSelection(),o=new n(this.editor,{field:void 0!=e?e:"",value:void 0!=t?t:"",type:i});o.expand(!0),this.parent.insertAfter(o,this),this.editor.highlighter.unhighlight(),o.focus("field");var s=this.editor.getSelection();this.editor._onAction("insertAfterNodes",{nodes:[o],afterNode:this,parent:this.parent,oldSelection:r,newSelection:s})},n.prototype._onAppend=function(e,t,i){var r=this.editor.getSelection(),o=new n(this.editor,{field:void 0!=e?e:"",value:void 0!=t?t:"",type:i});o.expand(!0),this.parent.appendChild(o),this.editor.highlighter.unhighlight(),o.focus("field");var s=this.editor.getSelection();this.editor._onAction("appendNodes",{nodes:[o],parent:this.parent,oldSelection:r,newSelection:s})},n.prototype._onChangeType=function(e){var t=this.type;if(e!=t){var i=this.editor.getSelection();this.changeType(e);var n=this.editor.getSelection();this.editor._onAction("changeType",{node:this,oldType:t,newType:e,oldSelection:i,newSelection:n})}},n.prototype._onSort=function(e){if(this._hasChilds()){var t="desc"==e?-1:1,i="array"==this.type?"value":"field";this.hideChilds();var n=this.childs,r=this.sort;this.childs=this.childs.concat(),this.childs.sort(function(e,n){return e[i]>n[i]?t:e[i]/g,">").replace(/ /g,"  ").replace(/^ /," ").replace(/ $/," "),i=JSON.stringify(t),n=i.substring(1,i.length-1);return this.editor.options.escapeUnicode===!0&&(n=s.escapeUnicodeChars(n)),n},n.prototype._unescapeHTML=function(e){var t='"'+this._escapeJSON(e)+'"',i=s.parse(t);return i.replace(/</g,"<").replace(/>/g,">").replace(/ |\u00A0/g," ").replace(/&/g,"&")},n.prototype._escapeJSON=function(e){for(var t="",i=0;i2&&b.push("'"+this.terminals_[y]+"'");var x="";x=this.lexer.showPosition?"Parse error on line "+(c+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+b.join(", ")+", got '"+this.terminals_[g]+"'":"Parse error on line "+(c+1)+": Unexpected "+(1==g?"end of input":"'"+(this.terminals_[g]||g)+"'"),this.parseError(x,{text:this.lexer.match,token:this.terminals_[g]||g,line:this.lexer.yylineno,loc:p,expected:b})}if(3==d){if(g==f)throw new Error(x||"Parsing halted.");h=this.lexer.yyleng,l=this.lexer.yytext,c=this.lexer.yylineno,p=this.lexer.yylloc,g=i()}for(;;){if(u.toString()in a[v])break;if(0==v)throw new Error(x||"Parsing halted.");t(1),v=r[r.length-1]}m=g,g=u,v=r[r.length-1],w=a[v]&&a[v][u],d=3}if(w[0]instanceof Array&&w.length>1)throw new Error("Parse Error: multiple actions possible at state: "+v+", token: "+g);switch(w[0]){case 1:r.push(g),o.push(this.lexer.yytext),s.push(this.lexer.yylloc),r.push(w[1]),g=null,m?(g=m,m=null):(h=this.lexer.yyleng,l=this.lexer.yytext,c=this.lexer.yylineno,p=this.lexer.yylloc,d>0&&d--);break;case 2:if(C=this.productions_[w[1]][1],F.$=o[o.length-C],F._$={first_line:s[s.length-(C||1)].first_line,last_line:s[s.length-1].last_line,first_column:s[s.length-(C||1)].first_column,last_column:s[s.length-1].last_column},A=this.performAction.call(F,l,h,c,this.yy,w[1],o,s),"undefined"!=typeof A)return A;C&&(r=r.slice(0,-1*C*2),o=o.slice(0,-1*C),s=s.slice(0,-1*C)),r.push(this.productions_[w[1]][0]),o.push(F.$),s.push(F._$),E=a[r[r.length-2]][r[r.length-1]],r.push(E);break;case 3:return!0}}return!0}},t=function(){var e={EOF:1,parseError:function(e,t){if(!this.yy.parseError)throw new Error(e);this.yy.parseError(e,t)},setInput:function(e){return this._input=e,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this},input:function(){var e=this._input[0];this.yytext+=e,this.yyleng++,this.match+=e,this.matched+=e;var t=e.match(/\n/);return t&&this.yylineno++,this._input=this._input.slice(1),e},unput:function(e){return this._input=e+this._input,this},more:function(){return this._more=!0,this},less:function(e){this._input=this.match.slice(e)+this._input},pastInput:function(){var e=this.matched.substr(0,this.matched.length-this.match.length);return(e.length>20?"...":"")+e.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var e=this.match;return e.length<20&&(e+=this._input.substr(0,20-e.length)),(e.substr(0,20)+(e.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var e=this.pastInput(),t=new Array(e.length+1).join("-");return e+this.upcomingInput()+"\n"+t+"^"},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var e,t,i,n,r;this._more||(this.yytext="",this.match="");for(var o=this._currentRules(),s=0;st[0].length)||(t=i,n=s,this.options.flex));s++);return t?(r=t[0].match(/\n.*/g),r&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-1:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.yyleng=this.yytext.length,this._more=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],e=this.performAction.call(this,this.yy,this,o[n],this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),e?e:void 0):""===this._input?this.EOF:void this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var e=this.next();return"undefined"!=typeof e?e:this.lex()},begin:function(e){this.conditionStack.push(e)},popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(e){this.begin(e)}};return e.options={},e.performAction=function(e,t,i,n){switch(i){case 0:break;case 1:return 6;case 2:return t.yytext=t.yytext.substr(1,t.yyleng-2),4;case 3:return 17;case 4:return 18;case 5:return 23;case 6:return 24;case 7:return 22;case 8:return 21;case 9:return 10;case 10:return 11;case 11:return 8;case 12:return 14;case 13:return"INVALID"}},e.rules=[/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt\/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/],e.conditions={INITIAL:{rules:[0,1,2,3,4,5,6,7,8,9,10,11,12,13],inclusive:!0}},e}();return e.lexer=t,e}();t.parser=n,t.parse=n.parse.bind(n)},function(e,t,i){"use strict";function n(e,t,i){var o=this._refs[i];if("string"==typeof o){if(!this._refs[o])return n.call(this,e,t,o);o=this._refs[o]}if(o=o||this._schemas[i],o instanceof w)return a(o.schema,this.opts.inlineRefs)?o.schema:o.validate||this._compile(o);var s,l,c,h=r.call(this,t,i);return h&&(s=h.schema,t=h.root,c=h.baseId),s instanceof w?l=s.validate||e.call(this,s.schema,t,void 0,c):s&&(l=a(s,this.opts.inlineRefs)?s:e.call(this,s,t,void 0,c)),l}function r(e,t){var i=g.parse(t,!1,!0),n=d(i),r=h(e.schema.id);if(n!==r){var a=u(n),l=this._refs[a];if("string"==typeof l)return o.call(this,e,l,i);if(l instanceof w)l.validate||this._compile(l),e=l;else if(l=this._schemas[a],l instanceof w){if(l.validate||this._compile(l),a==u(t))return{schema:l,root:e,baseId:r};e=l}if(!e.schema)return;r=h(e.schema.id)}return s.call(this,i,r,e.schema,e)}function o(e,t,i){var n=r.call(this,e,t);if(n){var o=n.schema,a=n.baseId;return e=n.root,o.id&&(a=f(a,o.id)),s.call(this,i,a,o,e)}}function s(e,t,i,n){if(e.hash=e.hash||"","#/"==e.hash.slice(0,2)){for(var o=e.hash.split("/"),s=1;s=1&&12>=i&&n>=1&&n<=g[i]}function o(e,t){var i=e.match(m);if(!i)return!1;var n=i[1],r=i[2],o=i[3],s=i[5];return 23>=n&&59>=r&&59>=o&&(!t||s)}function s(e){var t=e.split(E);return r(t[0])&&o(t[1],!0)}function a(e){return e.length<=255&&v.test(e)}function l(e){return b.test(e)&&w.test(e)}function c(e){try{return new RegExp(e),!0}catch(t){return!1}}function h(e,t){return e&&t?e>t?1:t>e?-1:e===t?0:void 0:void 0}function d(e,t){return e&&t&&(e=e.match(m),t=t.match(m),e&&t)?(e=e[1]+e[2]+e[3]+(e[4]||""),t=t[1]+t[2]+t[3]+(t[4]||""),e>t?1:t>e?-1:e===t?0:void 0):void 0}function u(e,t){if(e&&t){e=e.split(E),t=t.split(E);var i=h(e[0],t[0]);if(void 0!==i)return i||d(e[1],t[1])}}var f=i(30),p=/^\d\d\d\d-(\d\d)-(\d\d)$/,g=[0,31,29,31,30,31,30,31,31,30,31,30,31],m=/^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i,v=/^[a-z](?:(?:[-0-9a-z]{0,61})?[0-9a-z])?(\.[a-z](?:(?:[-0-9a-z]{0,61})?[0-9a-z])?)*$/i,w=/^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9a-f]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9a-f]{2})*)?$/i,A=/^(?:urn\:uuid\:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i,y=/^(?:\/(?:[^~\/]|~0|~1)+)*(?:\/)?$|^\#(?:\/(?:[a-z0-9_\-\.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)+)*(?:\/)?$/i,C=/^(?:0|[1-9][0-9]*)(?:\#|(?:\/(?:[^~\/]|~0|~1)+)*(?:\/)?)$/; -e.exports=n,n.fast={date:/^\d\d\d\d-[0-1]\d-[0-3]\d$/,time:/^[0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:z|[+-]\d\d:\d\d)?$/i,"date-time":/^\d\d\d\d-[0-1]\d-[0-3]\d[t\s][0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:z|[+-]\d\d:\d\d)$/i,uri:/^(?:[a-z][a-z0-9+-.]*)?(?:\:|\/)\/?[^\s]*$/i,email:/^[a-z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i,hostname:v,ipv4:/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,ipv6:/^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,regex:c,uuid:A,"json-pointer":y,"relative-json-pointer":C},n.full={date:r,time:o,"date-time":s,uri:l,email:/^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&''*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,hostname:a,ipv4:/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,ipv6:/^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,regex:c,uuid:A,"json-pointer":y,"relative-json-pointer":C},n.compare={date:h,time:d,"date-time":u};var E=/t|\s/i,b=/\/|\:/},function(e,t,i){"use strict";var n=i(31),r=i(30);e.exports=function(){var e=[{type:"number",rules:["maximum","minimum","multipleOf"]},{type:"string",rules:["maxLength","minLength","pattern","format"]},{type:"array",rules:["maxItems","minItems","uniqueItems","items"]},{type:"object",rules:["maxProperties","minProperties","required","dependencies","properties"]},{rules:["$ref","enum","not","anyOf","oneOf","allOf"]}];return e.all=["type","additionalProperties","patternProperties"],e.keywords=["additionalItems","$schema","id","title","description","default"],e.types=["number","integer","string","array","object","boolean","null"],e.forEach(function(t){t.rules=t.rules.map(function(t){return e.all.push(t),{keyword:t,code:n[t]}})}),e.keywords=r.toHash(e.all.concat(e.keywords)),e.all=r.toHash(e.all),e.types=r.toHash(e.types),e}},function(e,t,i){"use strict";function n(e){if(e.opts.meta!==!1){var t=i(32);e.addMetaSchema(t,o)}e.addKeyword("constant",{inline:i(33),statements:!0,errors:"full"}),e.addKeyword("contains",{type:"array",macro:r});var n=i(34);e.addKeyword("formatMaximum",{type:"string",inline:n,statements:!0,errors:"full"}),e.addKeyword("formatMinimum",{type:"string",inline:n,statements:!0,errors:"full"}),e.addKeyword("exclusiveFormatMaximum"),e.addKeyword("exclusiveFormatMinimum"),e.addKeyword("patternGroups"),e.addKeyword("switch",{inline:i(35),statements:!0,errors:"full"})}function r(e){return{not:{items:{not:e}}}}var o="https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json";e.exports={enable:n,META_SCHEMA_ID:o}},function(e,t,i){"use strict";e.exports=function(e,t){function i(e,t,n){function o(n){function o(n,o){if(n)t(n);else{if(!r._refs[s]&&!r._schemas[s])try{r.addSchema(o,s)}catch(a){return void t(a)}i(e,t)}}var s=n.missingSchema;if(r._refs[s]||r._schemas[s])return t(new Error("Schema "+s+" is loaded but"+n.missingRef+"cannot be resolved"));var a=r._loadingSchemas[s];a?"function"==typeof a?r._loadingSchemas[s]=[a,o]:a[a.length]=o:(r._loadingSchemas[s]=o,r.opts.loadSchema(s,function(e,t){var i=r._loadingSchemas[s];if(delete r._loadingSchemas[s],"function"==typeof i)i(e,t);else for(var n=0;na;a++)r(s[a]);for(a=0;l>a;a++)i(e,s[a],t)}else s&&r(s),i(e,s,t)}this.RULES.keywords[e]=!0,this.RULES.all[e]=!0}},function(e,t,i){function n(e){function t(e){this.editor=e,this.dom={}}return t.prototype=new e,t.prototype.getDom=function(){var e=this.dom;if(e.tr)return e.tr;this._updateEditability();var t=document.createElement("tr");if(t.node=this,e.tr=t,this.editable.field){e.tdDrag=document.createElement("td");var i=document.createElement("td");e.tdMenu=i;var n=document.createElement("button");n.className="jsoneditor-contextmenu",n.title="Click to open the actions menu (Ctrl+M)",e.menu=n,i.appendChild(e.menu)}var r=document.createElement("td"),o=document.createElement("div");return o.innerHTML="(empty)",o.className="jsoneditor-readonly",r.appendChild(o),e.td=r,e.text=o,this.updateDom(),t},t.prototype.updateDom=function(){var e=this.dom,t=e.td;t&&(t.style.paddingLeft=24*this.getLevel()+26+"px");var i=e.text;i&&(i.innerHTML="(empty "+this.parent.type+")");var n=e.tr;this.isVisible()?e.tr.firstChild||(e.tdDrag&&n.appendChild(e.tdDrag),e.tdMenu&&n.appendChild(e.tdMenu),n.appendChild(t)):e.tr.firstChild&&(e.tdDrag&&n.removeChild(e.tdDrag),e.tdMenu&&n.removeChild(e.tdMenu),n.removeChild(t))},t.prototype.isVisible=function(){return 0==this.parent.childs.length},t.prototype.showContextMenu=function(t,i){var n=this,r=e.TYPE_TITLES,s=[{text:"Append",title:"Append a new field with type 'auto' (Ctrl+Shift+Ins)",submenuTitle:"Select the type of the field to be appended",className:"jsoneditor-insert",click:function(){n._onAppend("","","auto")},submenu:[{text:"Auto",className:"jsoneditor-type-auto",title:r.auto,click:function(){n._onAppend("","","auto")}},{text:"Array",className:"jsoneditor-type-array",title:r.array,click:function(){n._onAppend("",[])}},{text:"Object",className:"jsoneditor-type-object",title:r.object,click:function(){n._onAppend("",{})}},{text:"String",className:"jsoneditor-type-string",title:r.string,click:function(){n._onAppend("","","string")}}]}],a=new o(s,{close:i});a.show(t,this.editor.content)},t.prototype.onEvent=function(e){var t=e.type,i=e.target||e.srcElement,n=this.dom,o=n.menu;if(i==o&&("mouseover"==t?this.editor.highlighter.highlight(this.parent):"mouseout"==t&&this.editor.highlighter.unhighlight()),"click"==t&&i==n.menu){var s=this.editor.highlighter;s.highlight(this.parent),s.lock(),r.addClassName(n.menu,"jsoneditor-selected"),this.showContextMenu(n.menu,function(){r.removeClassName(n.menu,"jsoneditor-selected"),s.unlock(),s.unhighlight()})}"keydown"==t&&this.onKeyDown(e)},t}var r=i(3),o=i(9);e.exports=n},function(e,t,i){ace.define("ace/theme/jsoneditor",["require","exports","module","ace/lib/dom"],function(e,t,i){t.isDark=!1,t.cssClass="ace-jsoneditor",t.cssText='.ace-jsoneditor .ace_gutter { background: #ebebeb; color: #333 } .ace-jsoneditor.ace_editor { font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif; line-height: 1.3; } .ace-jsoneditor .ace_print-margin { width: 1px; background: #e8e8e8 } .ace-jsoneditor .ace_scroller { background-color: #FFFFFF } .ace-jsoneditor .ace_text-layer { color: gray } .ace-jsoneditor .ace_variable { color: #1a1a1a } .ace-jsoneditor .ace_cursor { border-left: 2px solid #000000 } .ace-jsoneditor .ace_overwrite-cursors .ace_cursor { border-left: 0px; border-bottom: 1px solid #000000 } .ace-jsoneditor .ace_marker-layer .ace_selection { background: lightgray } .ace-jsoneditor.ace_multiselect .ace_selection.ace_start { box-shadow: 0 0 3px 0px #FFFFFF; border-radius: 2px } .ace-jsoneditor .ace_marker-layer .ace_step { background: rgb(255, 255, 0) } .ace-jsoneditor .ace_marker-layer .ace_bracket { margin: -1px 0 0 -1px; border: 1px solid #BFBFBF } .ace-jsoneditor .ace_marker-layer .ace_active-line { background: #FFFBD1 } .ace-jsoneditor .ace_gutter-active-line { background-color : #dcdcdc } .ace-jsoneditor .ace_marker-layer .ace_selected-word { border: 1px solid lightgray } .ace-jsoneditor .ace_invisible { color: #BFBFBF } .ace-jsoneditor .ace_keyword, .ace-jsoneditor .ace_meta, .ace-jsoneditor .ace_support.ace_constant.ace_property-value { color: #AF956F } .ace-jsoneditor .ace_keyword.ace_operator { color: #484848 } .ace-jsoneditor .ace_keyword.ace_other.ace_unit { color: #96DC5F } .ace-jsoneditor .ace_constant.ace_language { color: darkorange } .ace-jsoneditor .ace_constant.ace_numeric { color: red } .ace-jsoneditor .ace_constant.ace_character.ace_entity { color: #BF78CC } .ace-jsoneditor .ace_invalid { color: #FFFFFF; background-color: #FF002A; } .ace-jsoneditor .ace_fold { background-color: #AF956F; border-color: #000000 } .ace-jsoneditor .ace_storage, .ace-jsoneditor .ace_support.ace_class, .ace-jsoneditor .ace_support.ace_function, .ace-jsoneditor .ace_support.ace_other, .ace-jsoneditor .ace_support.ace_type { color: #C52727 } .ace-jsoneditor .ace_string { color: green } .ace-jsoneditor .ace_comment { color: #BCC8BA } .ace-jsoneditor .ace_entity.ace_name.ace_tag, .ace-jsoneditor .ace_entity.ace_other.ace_attribute-name { color: #606060 } .ace-jsoneditor .ace_markup.ace_underline { text-decoration: underline } .ace-jsoneditor .ace_indent-guide { background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y }';var n=e("../lib/dom");n.importCssString(t.cssText,t.cssClass)})},function(module,exports,__webpack_require__){"use strict";function compile(schema,root,localRefs,baseId){function localCompile(_schema,_root,localRefs,baseId){var isRoot=!_root||_root&&_root.schema==_schema;if(_root.schema!=root.schema)return compile.call(self,_schema,_root,localRefs,baseId);var validateCode=validateGenerator({isTop:!0,schema:_schema,isRoot:isRoot,baseId:baseId,root:_root,schemaPath:"",errSchemaPath:"#",errorPath:'""',RULES:RULES,validate:validateGenerator,util:util,resolve:resolve,resolveRef:resolveRef,usePattern:usePattern,useDefault:useDefault,useCustomRule:useCustomRule,opts:self.opts,formats:formats,self:self});if(validateCode=vars(refVal,refValCode)+vars(patterns,patternCode)+vars(defaults,defaultCode)+vars(customRules,customRuleCode)+validateCode,self.opts.beautify){var opts=self.opts.beautify===!0?{indent_size:2}:self.opts.beautify;beautify?validateCode=beautify(validateCode,opts):console.error('"npm install js-beautify" to use beautify option')}var validate;try{eval(validateCode),refVal[0]=validate}catch(e){throw console.log("Error compiling schema, function code:",validateCode),e}return validate.schema=_schema,validate.errors=null,validate.refs=refs,validate.refVal=refVal,validate.root=isRoot?validate:_root,validate}function resolveRef(e,t,i){t=resolve.url(e,t);var n,r,o=refs[t];if(void 0!==o)return n=refVal[o],r="refVal["+o+"]",resolvedRef(n,r);if(!i){var s=root.refs[t];if(void 0!==s)return n=root.refVal[s],r=addLocalRef(t,n),resolvedRef(n,r)}r=addLocalRef(t);var a=resolve.call(self,localCompile,root,t);if(!a){var l=localRefs&&localRefs[t];l&&(a=resolve.inlineRef(l,self.opts.inlineRefs)?l:compile.call(self,l,root,localRefs,e))}return a?(replaceLocalRef(t,a),resolvedRef(a,r)):void 0}function addLocalRef(e,t){var i=refVal.length;return refVal[i]=t,refs[e]=i,"refVal"+i}function replaceLocalRef(e,t){var i=refs[e];refVal[i]=t}function resolvedRef(e,t){return"object"==typeof e?{schema:e,code:t}:t}function usePattern(e){var t=patternsHash[e];return void 0===t&&(t=patternsHash[e]=patterns.length,patterns[t]=e),"pattern"+t}function useDefault(e){switch(typeof e){case"boolean":case"number":return""+e;case"string":return util.toQuotedString(e);case"object":if(null===e)return"null";var t=stableStringify(e),i=defaultsHash[t];return void 0===i&&(i=defaultsHash[t]=defaults.length,defaults[i]=e),"default"+i}}function useCustomRule(e,t,i,n){var r,o=e.definition.compile,s=e.definition.inline,a=e.definition.macro;o?r=o.call(self,t,i):a?(r=a.call(self,t,i),self.opts.validateSchema!==!1&&self.validateSchema(r,!0)):r=s?s.call(self,n,e.keyword,t,i):e.definition.validate;var l=customRules.length;return customRules[l]=r,{code:"customRule"+l,validate:r}}var self=this,refVal=[void 0],refs={},patterns=[],patternsHash={},defaults=[],defaultsHash={},customRules=[],customRulesHash={};root=root||{schema:schema,refVal:refVal,refs:refs};var formats=this._formats,RULES=this.RULES;return localCompile(schema,root,localRefs,baseId)}function patternCode(e,t){return"var pattern"+e+" = new RegExp("+util.toQuotedString(t[e])+");"}function defaultCode(e){return"var default"+e+" = defaults["+e+"];"}function refValCode(e,t){return t[e]?"var refVal"+e+" = refVal["+e+"];":""}function customRuleCode(e){return"var customRule"+e+" = customRules["+e+"];"}function vars(e,t){if(!e.length)return"";for(var i="",n=0;ns;++s){var c=a(e,t[s]);if(void 0==c&&o.original)return;r.push(c)}return i&&i.apply(null,r)||!0}},o=function(e,t){var i=r("",e,t);return void 0==i&&o.original?o.original.apply(this,arguments):i},s=function(e,t){if(-1!==t.indexOf("!")){var i=t.split("!");return s(e,i[0])+"!"+s(e,i[1])}if("."==t.charAt(0)){var n=e.split("/").slice(0,-1).join("/");for(t=n+"/"+t;-1!==t.indexOf(".")&&r!=t;){var r=t;t=t.replace(/\/\.\//,"/").replace(/[^\/]+\/\.\.\//,"")}}return t},a=function(e,t){t=s(e,t);var i=n.modules[t];if(!i){if(i=n.payloads[t],"function"==typeof i){var o={},a={id:t,uri:"",exports:o,packaged:!0},l=function(e,i){return r(t,e,i)},c=i(l,o,a);o=c||a.exports,n.modules[t]=o,delete n.payloads[t]}i=n.modules[t]=o||i}return i};e(t)}}(),ace.define("ace/lib/regexp",["require","exports","module"],function(e,t,i){"use strict";function n(e){return(e.global?"g":"")+(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.extended?"x":"")+(e.sticky?"y":"")}function r(e,t,i){if(Array.prototype.indexOf)return e.indexOf(t,i);for(var n=i||0;n1&&r(l,"")>-1&&(i=RegExp(this.source,o.replace.call(n(this),"g","")),o.replace.call(e.slice(l.index),i,function(){for(var e=1;el.index&&this.lastIndex--}return l},a||(RegExp.prototype.test=function(e){var t=o.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t}))}),ace.define("ace/lib/es5-shim",["require","exports","module"],function(e,t,i){function n(){}function r(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}function o(e){return e=+e,e!==e?e=0:0!==e&&e!==1/0&&e!==-(1/0)&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}Function.prototype.bind||(Function.prototype.bind=function(e){var t=this;if("function"!=typeof t)throw new TypeError("Function.prototype.bind called on incompatible "+t);var i=p.call(arguments,1),r=function(){if(this instanceof r){var n=t.apply(this,i.concat(p.call(arguments)));return Object(n)===n?n:this}return t.apply(e,i.concat(p.call(arguments)))};return t.prototype&&(n.prototype=t.prototype,r.prototype=new n,n.prototype=null),r});var s,a,l,c,h,d=Function.prototype.call,u=Array.prototype,f=Object.prototype,p=u.slice,g=d.bind(f.toString),m=d.bind(f.hasOwnProperty);if((h=m(f,"__defineGetter__"))&&(s=d.bind(f.__defineGetter__),a=d.bind(f.__defineSetter__),l=d.bind(f.__lookupGetter__),c=d.bind(f.__lookupSetter__)),2!=[1,2].splice(0).length)if(function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t,i=[];return i.splice.apply(i,e(20)),i.splice.apply(i,e(26)),t=i.length,i.splice(5,0,"XXX"),t+1==i.length,t+1==i.length?!0:void 0}()){var v=Array.prototype.splice;Array.prototype.splice=function(e,t){return arguments.length?v.apply(this,[void 0===e?0:e,void 0===t?this.length-e:t].concat(p.call(arguments,2))):[]}}else Array.prototype.splice=function(e,t){var i=this.length;e>0?e>i&&(e=i):void 0==e?e=0:0>e&&(e=Math.max(i+e,0)),i>e+t||(t=i-e);var n=this.slice(e,e+t),r=p.call(arguments,2),o=r.length;if(e===i)o&&this.push.apply(this,r);else{var s=Math.min(t,i-e),a=e+s,l=a+o-s,c=i-a,h=i-s;if(a>l)for(var d=0;c>d;++d)this[l+d]=this[a+d];else if(l>a)for(d=c;d--;)this[l+d]=this[a+d];if(o&&e===h)this.length=h,this.push.apply(this,r);else for(this.length=h+o,d=0;o>d;++d)this[e+d]=r[d]}return n};Array.isArray||(Array.isArray=function(e){return"[object Array]"==g(e)});var w=Object("a"),A="a"!=w[0]||!(0 in w);if(Array.prototype.forEach||(Array.prototype.forEach=function(e){var t=M(this),i=A&&"[object String]"==g(this)?this.split(""):t,n=arguments[1],r=-1,o=i.length>>>0;if("[object Function]"!=g(e))throw new TypeError;for(;++r>>0,r=Array(n),o=arguments[1];if("[object Function]"!=g(e))throw new TypeError(e+" is not a function");for(var s=0;n>s;s++)s in i&&(r[s]=e.call(o,i[s],s,t));return r}),Array.prototype.filter||(Array.prototype.filter=function(e){var t,i=M(this),n=A&&"[object String]"==g(this)?this.split(""):i,r=n.length>>>0,o=[],s=arguments[1];if("[object Function]"!=g(e))throw new TypeError(e+" is not a function");for(var a=0;r>a;a++)a in n&&(t=n[a],e.call(s,t,a,i)&&o.push(t));return o}),Array.prototype.every||(Array.prototype.every=function(e){var t=M(this),i=A&&"[object String]"==g(this)?this.split(""):t,n=i.length>>>0,r=arguments[1];if("[object Function]"!=g(e))throw new TypeError(e+" is not a function");for(var o=0;n>o;o++)if(o in i&&!e.call(r,i[o],o,t))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(e){var t=M(this),i=A&&"[object String]"==g(this)?this.split(""):t,n=i.length>>>0,r=arguments[1];if("[object Function]"!=g(e))throw new TypeError(e+" is not a function");for(var o=0;n>o;o++)if(o in i&&e.call(r,i[o],o,t))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(e){var t=M(this),i=A&&"[object String]"==g(this)?this.split(""):t,n=i.length>>>0;if("[object Function]"!=g(e))throw new TypeError(e+" is not a function");if(!n&&1==arguments.length)throw new TypeError("reduce of empty array with no initial value");var r,o=0;if(arguments.length>=2)r=arguments[1];else for(;;){if(o in i){r=i[o++];break}if(++o>=n)throw new TypeError("reduce of empty array with no initial value")}for(;n>o;o++)o in i&&(r=e.call(void 0,r,i[o],o,t));return r}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(e){var t=M(this),i=A&&"[object String]"==g(this)?this.split(""):t,n=i.length>>>0;if("[object Function]"!=g(e))throw new TypeError(e+" is not a function");if(!n&&1==arguments.length)throw new TypeError("reduceRight of empty array with no initial value");var r,o=n-1;if(arguments.length>=2)r=arguments[1];else for(;;){if(o in i){r=i[o--];break}if(--o<0)throw new TypeError("reduceRight of empty array with no initial value")}do o in this&&(r=e.call(void 0,r,i[o],o,t));while(o--);return r}),Array.prototype.indexOf&&-1==[0,1].indexOf(1,2)||(Array.prototype.indexOf=function(e){var t=A&&"[object String]"==g(this)?this.split(""):M(this),i=t.length>>>0;if(!i)return-1;var n=0;for(arguments.length>1&&(n=o(arguments[1])),n=n>=0?n:Math.max(0,i+n);i>n;n++)if(n in t&&t[n]===e)return n;return-1}),Array.prototype.lastIndexOf&&-1==[0,1].lastIndexOf(0,-3)||(Array.prototype.lastIndexOf=function(e){var t=A&&"[object String]"==g(this)?this.split(""):M(this),i=t.length>>>0;if(!i)return-1;var n=i-1;for(arguments.length>1&&(n=Math.min(n,o(arguments[1]))),n=n>=0?n:i-Math.abs(n);n>=0;n--)if(n in t&&e===t[n])return n;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(e){return e.__proto__||(e.constructor?e.constructor.prototype:f)}),!Object.getOwnPropertyDescriptor){var y="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(e,t){if("object"!=typeof e&&"function"!=typeof e||null===e)throw new TypeError(y+e);if(m(e,t)){var i,n,r;if(i={enumerable:!0,configurable:!0},h){var o=e.__proto__;e.__proto__=f;var n=l(e,t),r=c(e,t);if(e.__proto__=o,n||r)return n&&(i.get=n),r&&(i.set=r),i}return i.value=e[t],i}}}if(Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(e){return Object.keys(e)}),!Object.create){var C;C=null===Object.prototype.__proto__?function(){return{__proto__:null}}:function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(e,t){var i;if(null===e)i=C();else{if("object"!=typeof e)throw new TypeError("typeof prototype["+typeof e+"] != 'object'");var n=function(){};n.prototype=e,i=new n,i.__proto__=e}return void 0!==t&&Object.defineProperties(i,t),i}}if(Object.defineProperty){var E=r({}),b="undefined"==typeof document||r(document.createElement("div"));if(!E||!b)var F=Object.defineProperty}if(!Object.defineProperty||F){var x="Property description must be an object: ",S="Object.defineProperty called on non-object: ",$="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(e,t,i){if("object"!=typeof e&&"function"!=typeof e||null===e)throw new TypeError(S+e);if("object"!=typeof i&&"function"!=typeof i||null===i)throw new TypeError(x+i);if(F)try{return F.call(Object,e,t,i)}catch(n){}if(m(i,"value"))if(h&&(l(e,t)||c(e,t))){var r=e.__proto__;e.__proto__=f,delete e[t],e[t]=i.value,e.__proto__=r}else e[t]=i.value;else{if(!h)throw new TypeError($);m(i,"get")&&s(e,t,i.get),m(i,"set")&&a(e,t,i.set)}return e}}Object.defineProperties||(Object.defineProperties=function(e,t){for(var i in t)m(t,i)&&Object.defineProperty(e,i,t[i]);return e}),Object.seal||(Object.seal=function(e){return e}),Object.freeze||(Object.freeze=function(e){return e});try{Object.freeze(function(){})}catch(D){Object.freeze=function(e){return function(t){return"function"==typeof t?t:e(t)}}(Object.freeze)}if(Object.preventExtensions||(Object.preventExtensions=function(e){return e}),Object.isSealed||(Object.isSealed=function(e){return!1}),Object.isFrozen||(Object.isFrozen=function(e){return!1}),Object.isExtensible||(Object.isExtensible=function(e){if(Object(e)===e)throw new TypeError;for(var t="";m(e,t);)t+="?";e[t]=!0;var i=m(e,t);return delete e[t],i}),!Object.keys){var k=!0,B=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],_=B.length;for(var L in{toString:null})k=!1;Object.keys=function O(e){if("object"!=typeof e&&"function"!=typeof e||null===e)throw new TypeError("Object.keys called on a non-object");var O=[];for(var t in e)m(e,t)&&O.push(t);if(k)for(var i=0,n=_;n>i;i++){var r=B[i];m(e,r)&&O.push(r)}return O}}Date.now||(Date.now=function(){return(new Date).getTime()});var R=" \n \f\r   ᠎              \u2028\u2029\ufeff";if(!String.prototype.trim||R.trim()){R="["+R+"]";var T=new RegExp("^"+R+R+"*"),P=new RegExp(R+R+"*$");String.prototype.trim=function(){return String(this).replace(T,"").replace(P,"")}}var M=function(e){if(null==e)throw new TypeError("can't convert "+e+" to object");return Object(e)}}),ace.define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"],function(e,t,i){"use strict";e("./regexp"),e("./es5-shim")}),ace.define("ace/lib/dom",["require","exports","module"],function(e,t,i){"use strict";var n="http://www.w3.org/1999/xhtml";return t.getDocumentHead=function(e){return e||(e=document),e.head||e.getElementsByTagName("head")[0]||e.documentElement},t.createElement=function(e,t){return document.createElementNS?document.createElementNS(t||n,e):document.createElement(e)},t.hasCssClass=function(e,t){var i=(e.className||"").split(/\s+/g);return-1!==i.indexOf(t)},t.addCssClass=function(e,i){t.hasCssClass(e,i)||(e.className+=" "+i)},t.removeCssClass=function(e,t){for(var i=e.className.split(/\s+/g);;){var n=i.indexOf(t);if(-1==n)break;i.splice(n,1)}e.className=i.join(" ")},t.toggleCssClass=function(e,t){for(var i=e.className.split(/\s+/g),n=!0;;){var r=i.indexOf(t);if(-1==r)break;n=!1,i.splice(r,1)}return n&&i.push(t),e.className=i.join(" "),n},t.setCssClass=function(e,i,n){n?t.addCssClass(e,i):t.removeCssClass(e,i)},t.hasCssString=function(e,t){var i,n=0;if(t=t||document,t.createStyleSheet&&(i=t.styleSheets)){for(;n=0?(r.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]:(r.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]),t.isOldIE=t.isIE&&t.isIE<9,t.isGecko=t.isMozilla=(window.Controllers||window.controllers)&&"Gecko"===window.navigator.product,t.isOldGecko=t.isGecko&&parseInt((r.match(/rv\:(\d+)/)||[])[1],10)<4,t.isOpera=window.opera&&"[object Opera]"==Object.prototype.toString.call(window.opera),t.isWebKit=parseFloat(r.split("WebKit/")[1])||void 0,t.isChrome=parseFloat(r.split(" Chrome/")[1])||void 0,t.isAIR=r.indexOf("AdobeAIR")>=0,t.isIPad=r.indexOf("iPad")>=0,t.isTouchPad=r.indexOf("TouchPad")>=0,t.isChromeOS=r.indexOf(" CrOS ")>=0}}),ace.define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent"],function(e,t,i){"use strict";function n(e,t,i){var n=c(t);if(!s.isMac&&a){if(a.OSKey&&(n|=8),a.altGr){if(3==(3&n))return;a.altGr=0}if(18===i||17===i){var r="location"in t?t.location:t.keyLocation;if(17===i&&1===r)1==a[i]&&(l=t.timeStamp);else if(18===i&&3===n&&2===r){var h=t.timeStamp-l;50>h&&(a.altGr=!0)}}}if(i in o.MODIFIER_KEYS&&(i=-1),8&n&&i>=91&&93>=i&&(i=-1),!n&&13===i){var r="location"in t?t.location:t.keyLocation;if(3===r&&(e(t,n,-i),t.defaultPrevented))return}if(s.isChromeOS&&8&n){if(e(t,n,i),t.defaultPrevented)return;n&=-9}return n||i in o.FUNCTION_KEYS||i in o.PRINTABLE_KEYS?e(t,n,i):!1}function r(){a=Object.create(null),a.count=0,a.lastT=0}var o=e("./keys"),s=e("./useragent"),a=null,l=0;t.addListener=function(e,t,i){if(e.addEventListener)return e.addEventListener(t,i,!1);if(e.attachEvent){var n=function(){i.call(e,window.event)};i._wrapper=n,e.attachEvent("on"+t,n)}},t.removeListener=function(e,t,i){return e.removeEventListener?e.removeEventListener(t,i,!1):void(e.detachEvent&&e.detachEvent("on"+t,i._wrapper||i))},t.stopEvent=function(e){return t.stopPropagation(e),t.preventDefault(e),!1},t.stopPropagation=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},t.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},t.getButton=function(e){return"dblclick"==e.type?0:"contextmenu"==e.type||s.isMac&&e.ctrlKey&&!e.altKey&&!e.shiftKey?2:e.preventDefault?e.button:{1:0,2:2,4:1}[e.button]},t.capture=function(e,i,n){function r(e){i&&i(e),n&&n(e),t.removeListener(document,"mousemove",i,!0),t.removeListener(document,"mouseup",r,!0),t.removeListener(document,"dragstart",r,!0)}return t.addListener(document,"mousemove",i,!0),t.addListener(document,"mouseup",r,!0),t.addListener(document,"dragstart",r,!0),r},t.addTouchMoveListener=function(e,i){if("ontouchmove"in e){var n,r;t.addListener(e,"touchstart",function(e){var t=e.changedTouches[0];n=t.clientX,r=t.clientY}),t.addListener(e,"touchmove",function(e){var t=1,o=e.changedTouches[0];e.wheelX=-(o.clientX-n)/t,e.wheelY=-(o.clientY-r)/t,n=o.clientX,r=o.clientY,i(e)})}},t.addMouseWheelListener=function(e,i){"onmousewheel"in e?t.addListener(e,"mousewheel",function(e){var t=8;void 0!==e.wheelDeltaX?(e.wheelX=-e.wheelDeltaX/t,e.wheelY=-e.wheelDeltaY/t):(e.wheelX=0,e.wheelY=-e.wheelDelta/t),i(e)}):"onwheel"in e?t.addListener(e,"wheel",function(e){var t=.35;switch(e.deltaMode){case e.DOM_DELTA_PIXEL:e.wheelX=e.deltaX*t||0,e.wheelY=e.deltaY*t||0;break;case e.DOM_DELTA_LINE:case e.DOM_DELTA_PAGE:e.wheelX=5*(e.deltaX||0),e.wheelY=5*(e.deltaY||0)}i(e)}):t.addListener(e,"DOMMouseScroll",function(e){e.axis&&e.axis==e.HORIZONTAL_AXIS?(e.wheelX=5*(e.detail||0),e.wheelY=0):(e.wheelX=0,e.wheelY=5*(e.detail||0)),i(e)})},t.addMultiMouseDownListener=function(e,i,n,r){var o,a,l,c=0,h={2:"dblclick",3:"tripleclick",4:"quadclick"};t.addListener(e,"mousedown",function(e){if(0!==t.getButton(e)?c=0:e.detail>1?(c++,c>4&&(c=1)):c=1,s.isIE){var d=Math.abs(e.clientX-o)>5||Math.abs(e.clientY-a)>5;(!l||d)&&(c=1),l&&clearTimeout(l),l=setTimeout(function(){l=null},i[c-1]||600),1==c&&(o=e.clientX,a=e.clientY)}if(e._clicks=c,n[r]("mousedown",e),c>4)c=0;else if(c>1)return n[r](h[c],e)}),s.isOldIE&&t.addListener(e,"dblclick",function(e){c=2,l&&clearTimeout(l),l=setTimeout(function(){l=null},i[c-1]||600),n[r]("mousedown",e),n[r](h[c],e)})};var c=!s.isMac||!s.isOpera||"KeyboardEvent"in window?function(e){return 0|(e.ctrlKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.metaKey?8:0)}:function(e){return 0|(e.metaKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.ctrlKey?8:0)};if(t.getModifierString=function(e){return o.KEY_MODS[c(e)]},t.addCommandKeyListener=function(e,i){var o=t.addListener;if(s.isOldGecko||s.isOpera&&!("KeyboardEvent"in window)){var l=null;o(e,"keydown",function(e){l=e.keyCode}),o(e,"keypress",function(e){return n(i,e,l)})}else{var c=null;o(e,"keydown",function(e){var t=e.keyCode;a[t]=(a[t]||0)+1,91==t||92==t?a.OSKey=!0:a.OSKey&&e.timeStamp-a.lastT>200&&1==a.count&&r(),1==a[t]&&a.count++,a.lastT=e.timeStamp;var o=n(i,e,t);return c=e.defaultPrevented,o}),o(e,"keypress",function(e){c&&(e.ctrlKey||e.altKey||e.shiftKey||e.metaKey)&&(t.stopEvent(e),c=null)}),o(e,"keyup",function(e){var t=e.keyCode;a[t]?a.count=Math.max(a.count-1,0):r(),(91==t||92==t)&&(a.OSKey=!1),a[t]=null}),a||(r(),o(window,"focus",r))}},"object"==typeof window&&window.postMessage&&!s.isOldIE){var h=1;t.nextTick=function(e,i){i=i||window;var n="zero-timeout-message-"+h;t.addListener(i,"message",function r(o){o.data==n&&(t.stopPropagation(o),t.removeListener(i,"message",r),e())}),i.postMessage(n,"*")}}t.nextFrame="object"==typeof window&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame),t.nextFrame?t.nextFrame=t.nextFrame.bind(window):t.nextFrame=function(e){setTimeout(e,17)}}),ace.define("ace/lib/lang",["require","exports","module"],function(e,t,i){"use strict";t.last=function(e){return e[e.length-1]},t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){for(var i="";t>0;)1&t&&(i+=e),(t>>=1)&&(e+=e);return i};var n=/^\s\s*/,r=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(n,"")},t.stringTrimRight=function(e){return e.replace(r,"")},t.copyObject=function(e){var t={};for(var i in e)t[i]=e[i];return t},t.copyArray=function(e){for(var t=[],i=0,n=e.length;n>i;i++)e[i]&&"object"==typeof e[i]?t[i]=this.copyObject(e[i]):t[i]=e[i];return t},t.deepCopy=function o(e){if("object"!=typeof e||!e)return e;var t;if(Array.isArray(e)){t=[];for(var i=0;ii?{cursor:e.start,anchor:e.end}:{cursor:e.end,anchor:e.start}}var s=(e("../lib/dom"),e("../lib/event"),e("../lib/useragent"),0);(function(){this.onMouseDown=function(e){var t=e.inSelection(),i=e.getDocumentPosition();this.mousedownEvent=e;var n=this.editor,r=e.getButton();if(0!==r){var o=n.getSelectionRange(),s=o.isEmpty();return n.$blockScrolling++,s&&n.selection.moveToPosition(i),n.$blockScrolling--,void n.textInput.onContextMenu(e.domEvent)}return this.mousedownEvent.time=Date.now(),!t||n.isFocused()||(n.focus(),!this.$focusTimout||this.$clickSelection||n.inMultiSelectMode)?(this.captureMouse(e),this.startSelect(i,e.domEvent._clicks>1),e.preventDefault()):(this.setState("focusWait"),void this.captureMouse(e))},this.startSelect=function(e,t){e=e||this.editor.renderer.screenToTextCoordinates(this.x,this.y);var i=this.editor;i.$blockScrolling++,this.mousedownEvent.getShiftKey()?i.selection.selectToPosition(e):t||i.selection.moveToPosition(e),t||this.select(),i.renderer.scroller.setCapture&&i.renderer.scroller.setCapture(),i.setStyle("ace_selecting"),this.setState("select"),i.$blockScrolling--},this.select=function(){var e,t=this.editor,i=t.renderer.screenToTextCoordinates(this.x,this.y);if(t.$blockScrolling++,this.$clickSelection){var n=this.$clickSelection.comparePoint(i);if(-1==n)e=this.$clickSelection.end;else if(1==n)e=this.$clickSelection.start;else{var r=o(this.$clickSelection,i);i=r.cursor,e=r.anchor}t.selection.setSelectionAnchor(e.row,e.column)}t.selection.selectToPosition(i),t.$blockScrolling--,t.renderer.scrollCursorIntoView()},this.extendSelectionBy=function(e){var t,i=this.editor,n=i.renderer.screenToTextCoordinates(this.x,this.y),r=i.selection[e](n.row,n.column);if(i.$blockScrolling++,this.$clickSelection){var s=this.$clickSelection.comparePoint(r.start),a=this.$clickSelection.comparePoint(r.end);if(-1==s&&0>=a)t=this.$clickSelection.end,(r.end.row!=n.row||r.end.column!=n.column)&&(n=r.start);else if(1==a&&s>=0)t=this.$clickSelection.start,(r.start.row!=n.row||r.start.column!=n.column)&&(n=r.end);else if(-1==s&&1==a)n=r.end,t=r.start;else{var l=o(this.$clickSelection,n);n=l.cursor,t=l.anchor}i.selection.setSelectionAnchor(t.row,t.column)}i.selection.selectToPosition(n),i.$blockScrolling--,i.renderer.scrollCursorIntoView()},this.selectEnd=this.selectAllEnd=this.selectByWordsEnd=this.selectByLinesEnd=function(){this.$clickSelection=null,this.editor.unsetStyle("ace_selecting"),this.editor.renderer.scroller.releaseCapture&&this.editor.renderer.scroller.releaseCapture()},this.focusWait=function(){var e=r(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),t=Date.now();(e>s||t-this.mousedownEvent.time>this.$focusTimout)&&this.startSelect(this.mousedownEvent.getDocumentPosition())},this.onDoubleClick=function(e){var t=e.getDocumentPosition(),i=this.editor,n=i.session,r=n.getBracketRange(t);r?(r.isEmpty()&&(r.start.column--,r.end.column++),this.setState("select")):(r=i.selection.getWordRange(t.row,t.column),this.setState("selectByWords")),this.$clickSelection=r,this.select()},this.onTripleClick=function(e){var t=e.getDocumentPosition(),i=this.editor;this.setState("selectByLines");var n=i.getSelectionRange();n.isMultiLine()&&n.contains(t.row,t.column)?(this.$clickSelection=i.selection.getLineRange(n.start.row),this.$clickSelection.end=i.selection.getLineRange(n.end.row).end):this.$clickSelection=i.selection.getLineRange(t.row),this.select()},this.onQuadClick=function(e){var t=this.editor;t.selectAll(),this.$clickSelection=t.getSelectionRange(),this.setState("selectAll")},this.onMouseWheel=function(e){if(!e.getAccelKey()){e.getShiftKey()&&e.wheelY&&!e.wheelX&&(e.wheelX=e.wheelY,e.wheelY=0);var t=e.domEvent.timeStamp,i=t-(this.$lastScrollTime||0),n=this.editor,r=n.renderer.isScrollableBy(e.wheelX*e.speed,e.wheelY*e.speed);return r||200>i?(this.$lastScrollTime=t,n.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.stop()):void 0}},this.onTouchMove=function(e){var t=e.domEvent.timeStamp,i=t-(this.$lastScrollTime||0),n=this.editor,r=n.renderer.isScrollableBy(e.wheelX*e.speed,e.wheelY*e.speed);return r||200>i?(this.$lastScrollTime=t,n.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.stop()):void 0}}).call(n.prototype),t.DefaultHandlers=n}),ace.define("ace/tooltip",["require","exports","module","ace/lib/oop","ace/lib/dom"],function(e,t,i){"use strict";function n(e){this.isOpen=!1,this.$element=null,this.$parentNode=e}var r=(e("./lib/oop"),e("./lib/dom"));(function(){this.$init=function(){return this.$element=r.createElement("div"),this.$element.className="ace_tooltip",this.$element.style.display="none",this.$parentNode.appendChild(this.$element),this.$element},this.getElement=function(){return this.$element||this.$init()},this.setText=function(e){r.setInnerText(this.getElement(),e)},this.setHtml=function(e){this.getElement().innerHTML=e},this.setPosition=function(e,t){this.getElement().style.left=e+"px",this.getElement().style.top=t+"px"},this.setClassName=function(e){r.addCssClass(this.getElement(),e)},this.show=function(e,t,i){null!=e&&this.setText(e),null!=t&&null!=i&&this.setPosition(t,i),this.isOpen||(this.getElement().style.display="block",this.isOpen=!0)},this.hide=function(){this.isOpen&&(this.getElement().style.display="none",this.isOpen=!1)},this.getHeight=function(){return this.getElement().offsetHeight},this.getWidth=function(){return this.getElement().offsetWidth}}).call(n.prototype),t.Tooltip=n}),ace.define("ace/mouse/default_gutter_handler",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event","ace/tooltip"],function(e,t,i){"use strict";function n(e){function t(){var t=d.getDocumentPosition().row,r=l.$annotations[t];if(!r)return i();var o=s.session.getLength();if(t==o){var a=s.renderer.pixelToScreenCoordinates(0,d.y).row,h=d.$pos;if(a>s.session.documentToScreenRow(h.row,h.column))return i()}if(u!=r)if(u=r.text.join("
"),c.setHtml(u),c.show(),s.on("mousewheel",i),e.$tooltipFollowsMouse)n(d);else{var f=d.domEvent.target,p=f.getBoundingClientRect(),g=c.getElement().style;g.left=p.right+"px",g.top=p.bottom+"px"}}function i(){h&&(h=clearTimeout(h)),u&&(c.hide(),u=null,s.removeEventListener("mousewheel",i))}function n(e){c.setPosition(e.x,e.y)}var s=e.editor,l=s.renderer.$gutterLayer,c=new r(s.container);e.editor.setDefaultHandler("guttermousedown",function(t){if(s.isFocused()&&0==t.getButton()){var i=l.getRegion(t);if("foldWidgets"!=i){var n=t.getDocumentPosition().row,r=s.session.selection;if(t.getShiftKey())r.selectTo(n,0);else{if(2==t.domEvent.detail)return s.selectAll(),t.preventDefault();e.$clickSelection=s.selection.getLineRange(n)}return e.setState("selectByLines"),e.captureMouse(t),t.preventDefault()}}});var h,d,u;e.editor.setDefaultHandler("guttermousemove",function(r){var s=r.domEvent.target||r.domEvent.srcElement;return o.hasCssClass(s,"ace_fold-widget")?i():(u&&e.$tooltipFollowsMouse&&n(r),d=r,void(h||(h=setTimeout(function(){h=null,d&&!e.isMousePressed?t():i()},50))))}),a.addListener(s.renderer.$gutter,"mouseout",function(e){d=null,u&&!h&&(h=setTimeout(function(){h=null,i()},50))}),s.on("changeSession",i)}function r(e){l.call(this,e)}var o=e("../lib/dom"),s=e("../lib/oop"),a=e("../lib/event"),l=e("../tooltip").Tooltip;s.inherits(r,l),function(){this.setPosition=function(e,t){var i=window.innerWidth||document.documentElement.clientWidth,n=window.innerHeight||document.documentElement.clientHeight,r=this.getWidth(),o=this.getHeight();e+=15,t+=15,e+r>i&&(e-=e+r-i),t+o>n&&(t-=20+o),l.prototype.setPosition.call(this,e,t)}}.call(r.prototype),t.GutterHandler=n}),ace.define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"],function(e,t,i){"use strict";var n=e("../lib/event"),r=e("../lib/useragent"),o=t.MouseEvent=function(e,t){this.domEvent=e,this.editor=t,this.x=this.clientX=e.clientX,this.y=this.clientY=e.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1};(function(){this.stopPropagation=function(){n.stopPropagation(this.domEvent),this.propagationStopped=!0},this.preventDefault=function(){n.preventDefault(this.domEvent),this.defaultPrevented=!0},this.stop=function(){this.stopPropagation(),this.preventDefault()},this.getDocumentPosition=function(){return this.$pos?this.$pos:(this.$pos=this.editor.renderer.screenToTextCoordinates(this.clientX,this.clientY),this.$pos)},this.inSelection=function(){if(null!==this.$inSelection)return this.$inSelection;var e=this.editor,t=e.getSelectionRange();if(t.isEmpty())this.$inSelection=!1;else{var i=this.getDocumentPosition();this.$inSelection=t.contains(i.row,i.column)}return this.$inSelection},this.getButton=function(){return n.getButton(this.domEvent)},this.getShiftKey=function(){return this.domEvent.shiftKey},this.getAccelKey=r.isMac?function(){return this.domEvent.metaKey}:function(){return this.domEvent.ctrlKey}}).call(o.prototype)}),ace.define("ace/mouse/dragdrop_handler",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"],function(e,t,i){"use strict";function n(e){function t(e,t){var i=Date.now(),n=!t||e.row!=t.row,o=!t||e.column!=t.column;if(!D||n||o)m.$blockScrolling+=1,m.moveCursorToPosition(e),m.$blockScrolling-=1,D=i,k={x:y,y:C};else{var s=r(k.x,k.y,y,C);s>h?D=null:i-D>=c&&(m.renderer.scrollCursorIntoView(),D=null)}}function i(e,t){var i=Date.now(),n=m.renderer.layerConfig.lineHeight,r=m.renderer.layerConfig.characterWidth,o=m.renderer.scroller.getBoundingClientRect(),s={x:{left:y-o.left,right:o.right-y},y:{top:C-o.top,bottom:o.bottom-C}},a=Math.min(s.x.left,s.x.right),c=Math.min(s.y.top,s.y.bottom),h={row:e.row,column:e.column};2>=a/r&&(h.column+=s.x.left=c/n&&(h.row+=s.y.top=l&&m.renderer.scrollCursorIntoView(h):$=i:$=null}function n(){var e=F;F=m.renderer.screenToTextCoordinates(y,C),t(F,e),i(F,e)}function d(){b=m.selection.toOrientedRange(),A=m.session.addMarker(b,"ace_selection",m.getSelectionStyle()),m.clearSelection(),m.isFocused()&&m.renderer.$cursorLayer.setBlinking(!1),clearInterval(E),n(),E=setInterval(n,20),_=0,s.addListener(document,"mousemove",f)}function u(){clearInterval(E),m.session.removeMarker(A),A=null,m.$blockScrolling+=1,m.selection.fromOrientedRange(b),m.$blockScrolling-=1,m.isFocused()&&!S&&m.renderer.$cursorLayer.setBlinking(!m.getReadOnly()),b=null,F=null,_=0,$=null,D=null,s.removeListener(document,"mousemove",f)}function f(){null==L&&(L=setTimeout(function(){null!=L&&A&&u()},20))}function p(e){var t=e.types;return!t||Array.prototype.some.call(t,function(e){return"text/plain"==e||"Text"==e})}function g(e){var t=["copy","copymove","all","uninitialized"],i=["move","copymove","linkmove","all","uninitialized"],n=a.isMac?e.altKey:e.ctrlKey,r="uninitialized";try{r=e.dataTransfer.effectAllowed.toLowerCase()}catch(e){}var o="none";return n&&t.indexOf(r)>=0?o="copy":i.indexOf(r)>=0?o="move":t.indexOf(r)>=0&&(o="copy"),o}var m=e.editor,v=o.createElement("img");v.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",a.isOpera&&(v.style.cssText="width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;");var w=["dragWait","dragWaitEnd","startDrag","dragReadyEnd","onMouseDrag"];w.forEach(function(t){e[t]=this[t]},this),m.addEventListener("mousedown",this.onMouseDown.bind(e));var A,y,C,E,b,F,x,S,$,D,k,B=m.container,_=0;this.onDragStart=function(e){if(this.cancelDrag||!B.draggable){var t=this;return setTimeout(function(){t.startSelect(),t.captureMouse(e)},0),e.preventDefault()}b=m.getSelectionRange();var i=e.dataTransfer;i.effectAllowed=m.getReadOnly()?"copy":"copyMove",a.isOpera&&(m.container.appendChild(v),v.scrollTop=0),i.setDragImage&&i.setDragImage(v,0,0),a.isOpera&&m.container.removeChild(v),i.clearData(),i.setData("Text",m.session.getTextRange()),S=!0,this.setState("drag")},this.onDragEnd=function(e){if(B.draggable=!1,S=!1,this.setState(null),!m.getReadOnly()){var t=e.dataTransfer.dropEffect;x||"move"!=t||m.session.remove(m.getSelectionRange()),m.renderer.$cursorLayer.setBlinking(!0)}this.editor.unsetStyle("ace_dragging"),this.editor.renderer.setCursorStyle("")},this.onDragEnter=function(e){return!m.getReadOnly()&&p(e.dataTransfer)?(y=e.clientX,C=e.clientY,A||d(),_++,e.dataTransfer.dropEffect=x=g(e),s.preventDefault(e)):void 0},this.onDragOver=function(e){return!m.getReadOnly()&&p(e.dataTransfer)?(y=e.clientX,C=e.clientY,A||(d(),_++),null!==L&&(L=null),e.dataTransfer.dropEffect=x=g(e),s.preventDefault(e)):void 0},this.onDragLeave=function(e){return _--,0>=_&&A?(u(),x=null,s.preventDefault(e)):void 0},this.onDrop=function(e){if(F){var t=e.dataTransfer;if(S)switch(x){case"move":b=b.contains(F.row,F.column)?{start:F,end:F}:m.moveText(b,F);break;case"copy":b=m.moveText(b,F,!0)}else{var i=t.getData("Text");b={start:F,end:m.session.insert(F,i)},m.focus(),x=null}return u(),s.preventDefault(e)}},s.addListener(B,"dragstart",this.onDragStart.bind(e)),s.addListener(B,"dragend",this.onDragEnd.bind(e)),s.addListener(B,"dragenter",this.onDragEnter.bind(e)),s.addListener(B,"dragover",this.onDragOver.bind(e)),s.addListener(B,"dragleave",this.onDragLeave.bind(e)),s.addListener(B,"drop",this.onDrop.bind(e));var L=null}function r(e,t,i,n){return Math.sqrt(Math.pow(i-e,2)+Math.pow(n-t,2))}var o=e("../lib/dom"),s=e("../lib/event"),a=e("../lib/useragent"),l=200,c=200,h=5;(function(){this.dragWait=function(){var e=Date.now()-this.mousedownEvent.time;e>this.editor.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(){var e=this.editor.container;e.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()),this.selectEnd()},this.dragReadyEnd=function(e){this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly()),this.editor.unsetStyle("ace_dragging"),this.editor.renderer.setCursorStyle(""),this.dragWaitEnd()},this.startDrag=function(){this.cancelDrag=!1;var e=this.editor,t=e.container;t.draggable=!0,e.renderer.$cursorLayer.setBlinking(!1),e.setStyle("ace_dragging");var i=a.isWin?"default":"move";e.renderer.setCursorStyle(i),this.setState("dragReady")},this.onMouseDrag=function(e){var t=this.editor.container;if(a.isIE&&"dragReady"==this.state){ -var i=r(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);i>3&&t.dragDrop()}if("dragWait"===this.state){var i=r(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);i>0&&(t.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()))}},this.onMouseDown=function(e){if(this.$dragEnabled){this.mousedownEvent=e;var t=this.editor,i=e.inSelection(),n=e.getButton(),r=e.domEvent.detail||1;if(1===r&&0===n&&i){if(e.editor.inMultiSelectMode&&(e.getAccelKey()||e.getShiftKey()))return;this.mousedownEvent.time=Date.now();var o=e.domEvent.target||e.domEvent.srcElement;if("unselectable"in o&&(o.unselectable="on"),t.getDragDelay()){if(a.isWebKit){this.cancelDrag=!0;var s=t.container;s.draggable=!0}this.setState("dragWait")}else this.startDrag();this.captureMouse(e,this.onMouseDrag.bind(this)),e.defaultPrevented=!0}}}}).call(n.prototype),t.DragdropHandler=n}),ace.define("ace/lib/net",["require","exports","module","ace/lib/dom"],function(e,t,i){"use strict";var n=e("./dom");t.get=function(e,t){var i=new XMLHttpRequest;i.open("GET",e,!0),i.onreadystatechange=function(){4===i.readyState&&t(i.responseText)},i.send(null)},t.loadScript=function(e,t){var i=n.getDocumentHead(),r=document.createElement("script");r.src=e,i.appendChild(r),r.onload=r.onreadystatechange=function(e,i){(i||!r.readyState||"loaded"==r.readyState||"complete"==r.readyState)&&(r=r.onload=r.onreadystatechange=null,i||t())}},t.qualifyURL=function(e){var t=document.createElement("a");return t.href=e,t.href}}),ace.define("ace/lib/event_emitter",["require","exports","module"],function(e,t,i){"use strict";var n={},r=function(){this.propagationStopped=!0},o=function(){this.defaultPrevented=!0};n._emit=n._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var i=this._eventRegistry[e]||[],n=this._defaultHandlers[e];if(i.length||n){"object"==typeof t&&t||(t={}),t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=r),t.preventDefault||(t.preventDefault=o),i=i.slice();for(var s=0;sv;v++){var A=m[v];0===A.name.indexOf("data-ace-")&&(s[o(A.name.replace(/^data-ace-/,""))]=A.value)}var y=g.match(/^(.*)\/ace(\-\w+)?\.js(\?|$)/);y&&(a=y[1])}}a&&(s.base=s.base||a,s.packaged=!0),s.basePath=s.base,s.workerPath=s.workerPath||s.base,s.modePath=s.modePath||s.base,s.themePath=s.themePath||s.base,delete s.base;for(var C in s)"undefined"!=typeof s[C]&&t.set(C,s[C])}function o(e){return e.replace(/-(.)/g,function(e,t){return t.toUpperCase()})}var s=e("./lib/lang"),a=(e("./lib/oop"),e("./lib/net")),l=e("./lib/app_config").AppConfig;n.exports=t=new l;var c=function(){return this||"undefined"!=typeof window&&window}(),h={packaged:!1,workerPath:null,modePath:null,themePath:null,basePath:"",suffix:".js",$moduleUrls:{}};t.get=function(e){if(!h.hasOwnProperty(e))throw new Error("Unknown config key: "+e);return h[e]},t.set=function(e,t){if(!h.hasOwnProperty(e))throw new Error("Unknown config key: "+e);h[e]=t},t.all=function(){return s.copyObject(h)},t.moduleUrl=function(e,t){if(h.$moduleUrls[e])return h.$moduleUrls[e];var i=e.split("/");t=t||i[i.length-2]||"";var n="snippets"==t?"/":"-",r=i[i.length-1];if("worker"==t&&"-"==n){var o=new RegExp("^"+t+"[\\-_]|[\\-_]"+t+"$","g");r=r.replace(o,"")}(!r||r==t)&&i.length>1&&(r=i[i.length-2]);var s=h[t+"Path"];return null==s?s=h.basePath:"/"==n&&(t=n=""),s&&"/"!=s.slice(-1)&&(s+="/"),s+t+n+r+this.get("suffix")},t.setModuleUrl=function(e,t){return h.$moduleUrls[e]=t},t.$loading={},t.loadModule=function(i,n){var r,o;Array.isArray(i)&&(o=i[0],i=i[1]);try{r=e(i)}catch(s){}if(r&&!t.$loading[i])return n&&n(r);if(t.$loading[i]||(t.$loading[i]=[]),t.$loading[i].push(n),!(t.$loading[i].length>1)){var l=function(){e([i],function(e){t._emit("load.module",{name:i,module:e});var n=t.$loading[i];t.$loading[i]=null,n.forEach(function(t){t&&t(e)})})};return t.get("packaged")?void a.loadScript(t.moduleUrl(i,o),l):l()}},r(!0),t.init=r}),ace.define("ace/mouse/mouse_handler",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/mouse/default_handlers","ace/mouse/default_gutter_handler","ace/mouse/mouse_event","ace/mouse/dragdrop_handler","ace/config"],function(e,t,i){"use strict";var n=e("../lib/event"),r=e("../lib/useragent"),o=e("./default_handlers").DefaultHandlers,s=e("./default_gutter_handler").GutterHandler,a=e("./mouse_event").MouseEvent,l=e("./dragdrop_handler").DragdropHandler,c=e("../config"),h=function(e){var t=this;this.editor=e,new o(this),new s(this),new l(this);var i=function(t){document.hasFocus&&document.hasFocus()||window.focus(),e.focus(),e.isFocused()||window.focus()},a=e.renderer.getMouseEventTarget();n.addListener(a,"click",this.onMouseEvent.bind(this,"click")),n.addListener(a,"mousemove",this.onMouseMove.bind(this,"mousemove")),n.addMultiMouseDownListener(a,[400,300,250],this,"onMouseEvent"),e.renderer.scrollBarV&&(n.addMultiMouseDownListener(e.renderer.scrollBarV.inner,[400,300,250],this,"onMouseEvent"),n.addMultiMouseDownListener(e.renderer.scrollBarH.inner,[400,300,250],this,"onMouseEvent"),r.isIE&&(n.addListener(e.renderer.scrollBarV.element,"mousedown",i),n.addListener(e.renderer.scrollBarH.element,"mousedown",i))),n.addMouseWheelListener(e.container,this.onMouseWheel.bind(this,"mousewheel")),n.addTouchMoveListener(e.container,this.onTouchMove.bind(this,"touchmove"));var c=e.renderer.$gutter;n.addListener(c,"mousedown",this.onMouseEvent.bind(this,"guttermousedown")),n.addListener(c,"click",this.onMouseEvent.bind(this,"gutterclick")),n.addListener(c,"dblclick",this.onMouseEvent.bind(this,"gutterdblclick")),n.addListener(c,"mousemove",this.onMouseEvent.bind(this,"guttermousemove")),n.addListener(a,"mousedown",i),n.addListener(c,"mousedown",function(t){return e.focus(),n.preventDefault(t)}),e.on("mousemove",function(i){if(!t.state&&!t.$dragDelay&&t.$dragEnabled){var n=e.renderer.screenToTextCoordinates(i.x,i.y),r=e.session.selection.getRange(),o=e.renderer;o.setCursorStyle(!r.isEmpty()&&r.insideStart(n.row,n.column)?"default":"")}})};(function(){this.onMouseEvent=function(e,t){this.editor._emit(e,new a(t,this.editor))},this.onMouseMove=function(e,t){var i=this.editor._eventRegistry&&this.editor._eventRegistry.mousemove;i&&i.length&&this.editor._emit(e,new a(t,this.editor))},this.onMouseWheel=function(e,t){var i=new a(t,this.editor);i.speed=2*this.$scrollSpeed,i.wheelX=t.wheelX,i.wheelY=t.wheelY,this.editor._emit(e,i)},this.onTouchMove=function(e,t){var i=new a(t,this.editor);i.speed=1,i.wheelX=t.wheelX,i.wheelY=t.wheelY,this.editor._emit(e,i)},this.setState=function(e){this.state=e},this.captureMouse=function(e,t){this.x=e.x,this.y=e.y,this.isMousePressed=!0;var i=this.editor.renderer;i.$keepTextAreaAtCursor&&(i.$keepTextAreaAtCursor=null);var o=this,s=function(e){if(e){if(r.isWebKit&&!e.which&&o.releaseMouse)return o.releaseMouse();o.x=e.clientX,o.y=e.clientY,t&&t(e),o.mouseEvent=new a(e,o.editor),o.$mouseMoved=!0}},l=function(e){clearInterval(h),c(),o[o.state+"End"]&&o[o.state+"End"](e),o.state="",null==i.$keepTextAreaAtCursor&&(i.$keepTextAreaAtCursor=!0,i.$moveTextAreaToCursor()),o.isMousePressed=!1,o.$onCaptureMouseMove=o.releaseMouse=null,e&&o.onMouseEvent("mouseup",e)},c=function(){o[o.state]&&o[o.state](),o.$mouseMoved=!1};if(r.isOldIE&&"dblclick"==e.domEvent.type)return setTimeout(function(){l(e)});o.$onCaptureMouseMove=s,o.releaseMouse=n.capture(this.editor.container,s,l);var h=setInterval(c,20)},this.releaseMouse=null,this.cancelContextMenu=function(){var e=function(t){t&&t.domEvent&&"contextmenu"!=t.domEvent.type||(this.editor.off("nativecontextmenu",e),t&&t.domEvent&&n.stopEvent(t.domEvent))}.bind(this);setTimeout(e,10),this.editor.on("nativecontextmenu",e)}}).call(h.prototype),c.defineOptions(h.prototype,"mouseHandler",{scrollSpeed:{initialValue:2},dragDelay:{initialValue:r.isMac?150:0},dragEnabled:{initialValue:!0},focusTimout:{initialValue:0},tooltipFollowsMouse:{initialValue:!0}}),t.MouseHandler=h}),ace.define("ace/mouse/fold_handler",["require","exports","module"],function(e,t,i){"use strict";function n(e){e.on("click",function(t){var i=t.getDocumentPosition(),n=e.session,r=n.getFoldAt(i.row,i.column,1);r&&(t.getAccelKey()?n.removeFold(r):n.expandFold(r),t.stop())}),e.on("gutterclick",function(t){var i=e.renderer.$gutterLayer.getRegion(t);if("foldWidgets"==i){var n=t.getDocumentPosition().row,r=e.session;r.foldWidgets&&r.foldWidgets[n]&&e.session.onFoldWidgetClick(n,t),e.isFocused()||e.focus(),t.stop()}}),e.on("gutterdblclick",function(t){var i=e.renderer.$gutterLayer.getRegion(t);if("foldWidgets"==i){var n=t.getDocumentPosition().row,r=e.session,o=r.getParentFoldRangeData(n,!0),s=o.range||o.firstRange;if(s){n=s.start.row;var a=r.getFoldAt(n,r.getLine(n).length,1);a?r.removeFold(a):(r.addFold("...",s),e.renderer.scrollCursorIntoView({row:s.start.row,column:0}))}t.stop()}})}t.FoldHandler=n}),ace.define("ace/keyboard/keybinding",["require","exports","module","ace/lib/keys","ace/lib/event"],function(e,t,i){"use strict";var n=e("../lib/keys"),r=e("../lib/event"),o=function(e){this.$editor=e,this.$data={editor:e},this.$handlers=[],this.setDefaultHandler(e.commands)};(function(){this.setDefaultHandler=function(e){this.removeKeyboardHandler(this.$defaultHandler),this.$defaultHandler=e,this.addKeyboardHandler(e,0)},this.setKeyboardHandler=function(e){var t=this.$handlers;if(t[t.length-1]!=e){for(;t[t.length-1]&&t[t.length-1]!=this.$defaultHandler;)this.removeKeyboardHandler(t[t.length-1]);this.addKeyboardHandler(e,1)}},this.addKeyboardHandler=function(e,t){if(e){"function"!=typeof e||e.handleKeyboard||(e.handleKeyboard=e);var i=this.$handlers.indexOf(e);-1!=i&&this.$handlers.splice(i,1),void 0==t?this.$handlers.push(e):this.$handlers.splice(t,0,e),-1==i&&e.attach&&e.attach(this.$editor)}},this.removeKeyboardHandler=function(e){var t=this.$handlers.indexOf(e);return-1==t?!1:(this.$handlers.splice(t,1),e.detach&&e.detach(this.$editor),!0)},this.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},this.getStatusText=function(){var e=this.$data,t=e.editor;return this.$handlers.map(function(i){return i.getStatusText&&i.getStatusText(t,e)||""}).filter(Boolean).join(" ")},this.$callKeyboardHandlers=function(e,t,i,n){for(var o,s=!1,a=this.$editor.commands,l=this.$handlers.length;l--&&(o=this.$handlers[l].handleKeyboard(this.$data,e,t,i,n),!(o&&o.command&&(s="null"==o.command?!0:a.exec(o.command,this.$editor,o.args,n),s&&n&&-1!=e&&1!=o.passEvent&&1!=o.command.passEvent&&r.stopEvent(n),s))););return s||-1!=e||(o={command:"insertstring"},s=a.exec("insertstring",this.$editor,t)),s&&this.$editor._signal("keyboardActivity",o),s},this.onCommandKey=function(e,t,i){var r=n.keyCodeToString(i);this.$callKeyboardHandlers(t,r,i,e)},this.onTextInput=function(e){this.$callKeyboardHandlers(-1,e)}}).call(o.prototype),t.KeyBinding=o}),ace.define("ace/range",["require","exports","module"],function(e,t,i){"use strict";var n=function(e,t){return e.row-t.row||e.column-t.column},r=function(e,t,i,n){this.start={row:e,column:t},this.end={row:i,column:n}};(function(){this.isEqual=function(e){return this.start.row===e.start.row&&this.end.row===e.end.row&&this.start.column===e.start.column&&this.end.column===e.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return 0==this.compare(e,t)},this.compareRange=function(e){var t,i=e.end,n=e.start;return t=this.compare(i.row,i.column),1==t?(t=this.compare(n.row,n.column),1==t?2:0==t?1:0):-1==t?-2:(t=this.compare(n.row,n.column),-1==t?-1:1==t?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return 0==this.comparePoint(e.start)&&0==this.comparePoint(e.end)},this.intersects=function(e){var t=this.compareRange(e);return-1==t||0==t||1==t},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){"object"==typeof e?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){"object"==typeof e?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return 0==this.compare(e,t)?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return 0==this.compare(e,t)?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return 0==this.compare(e,t)?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return this.isMultiLine()||e!==this.start.row?ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0:tthis.end.column?1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var i={row:t+1,column:0};else if(this.end.rowt)var n={row:t+1,column:0};else if(this.start.rowt.row||e.row==t.row&&e.column>t.column},this.getRange=function(){var e=this.anchor,t=this.lead;return this.isEmpty()?s.fromPoints(t,t):this.isBackwards()?s.fromPoints(t,e):s.fromPoints(e,t)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit("changeSelection"))},this.selectAll=function(){var e=this.doc.getLength()-1;this.setSelectionAnchor(0,0),this.moveCursorTo(e,this.doc.getLine(e).length)},this.setRange=this.setSelectionRange=function(e,t){t?(this.setSelectionAnchor(e.end.row,e.end.column),this.selectTo(e.start.row,e.start.column)):(this.setSelectionAnchor(e.start.row,e.start.column),this.selectTo(e.end.row,e.end.column)),this.getRange().isEmpty()&&(this.$isEmpty=!0),this.$desiredColumn=null},this.$moveSelection=function(e){var t=this.lead;this.$isEmpty&&this.setSelectionAnchor(t.row,t.column),e.call(this)},this.selectTo=function(e,t){this.$moveSelection(function(){this.moveCursorTo(e,t)})},this.selectToPosition=function(e){this.$moveSelection(function(){this.moveCursorToPosition(e)})},this.moveTo=function(e,t){this.clearSelection(),this.moveCursorTo(e,t)},this.moveToPosition=function(e){this.clearSelection(),this.moveCursorToPosition(e)},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.getWordRange=function(e,t){if("undefined"==typeof t){var i=e||this.lead;e=i.row,t=i.column}return this.session.getWordRange(e,t)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var e=this.getCursor(),t=this.session.getAWordRange(e.row,e.column);this.setSelectionRange(t)},this.getLineRange=function(e,t){var i,n="number"==typeof e?e:this.lead.row,r=this.session.getFoldLine(n);return r?(n=r.start.row,i=r.end.row):i=n,t===!0?new s(n,0,i,this.session.getLine(i).length):new s(n,0,i+1,0)},this.selectLine=function(){this.setSelectionRange(this.getLineRange())},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.moveCursorLeft=function(){var e,t=this.lead.getPosition();if(e=this.session.getFoldAt(t.row,t.column,-1))this.moveCursorTo(e.start.row,e.start.column);else if(0===t.column)t.row>0&&this.moveCursorTo(t.row-1,this.doc.getLine(t.row-1).length);else{var i=this.session.getTabSize();this.session.isTabStop(t)&&this.doc.getLine(t.row).slice(t.column-i,t.column).split(" ").length-1==i?this.moveCursorBy(0,-i):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var e,t=this.lead.getPosition();if(e=this.session.getFoldAt(t.row,t.column,1))this.moveCursorTo(e.end.row,e.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row0&&(t.column=n)}}this.moveCursorTo(t.row,t.column)},this.moveCursorFileEnd=function(){var e=this.doc.getLength()-1,t=this.doc.getLine(e).length;this.moveCursorTo(e,t)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorLongWordRight=function(){var e,t=this.lead.row,i=this.lead.column,n=this.doc.getLine(t),r=n.substring(i);this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var o=this.session.getFoldAt(t,i,1);return o?void this.moveCursorTo(o.end.row,o.end.column):((e=this.session.nonTokenRe.exec(r))&&(i+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,r=n.substring(i)),i>=n.length?(this.moveCursorTo(t,n.length),this.moveCursorRight(),void(t=i?(this.moveCursorTo(t,0),this.moveCursorLeft(),void(t>0&&this.moveCursorWordLeft())):((o=this.session.tokenRe.exec(s))&&(i-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0),void this.moveCursorTo(t,i))},this.$shortWordEndIndex=function(e){var t,i,n=0,r=/\s/,o=this.session.tokenRe;if(o.lastIndex=0,t=this.session.tokenRe.exec(e))n=this.session.tokenRe.lastIndex;else{for(;(i=e[n])&&r.test(i);)n++;if(1>n)for(o.lastIndex=0;(i=e[n])&&!o.test(i);)if(o.lastIndex=0,n++,r.test(i)){if(n>2){n--;break}for(;(i=e[n])&&r.test(i);)n++;if(n>2)break}}return o.lastIndex=0,n},this.moveCursorShortWordRight=function(){var e=this.lead.row,t=this.lead.column,i=this.doc.getLine(e),n=i.substring(t),r=this.session.getFoldAt(e,t,1);if(r)return this.moveCursorTo(r.end.row,r.end.column);if(t==i.length){var o=this.doc.getLength();do e++,n=this.doc.getLine(e);while(o>e&&/^\s*$/.test(n));/^\s+/.test(n)||(n=""),t=0}var s=this.$shortWordEndIndex(n);this.moveCursorTo(e,t+s)},this.moveCursorShortWordLeft=function(){var e,t=this.lead.row,i=this.lead.column;if(e=this.session.getFoldAt(t,i,-1))return this.moveCursorTo(e.start.row,e.start.column);var n=this.session.getLine(t).substring(0,i);if(0===i){do t--,n=this.doc.getLine(t);while(t>0&&/^\s*$/.test(n));i=n.length,/\s+$/.test(n)||(n="")}var o=r.stringReverse(n),s=this.$shortWordEndIndex(o);return this.moveCursorTo(t,i-s)},this.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},this.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},this.moveCursorBy=function(e,t){var i=this.session.documentToScreenPosition(this.lead.row,this.lead.column);0===t&&(this.$desiredColumn?i.column=this.$desiredColumn:this.$desiredColumn=i.column);var n=this.session.screenToDocumentPosition(i.row+e,i.column);0!==e&&0===t&&n.row===this.lead.row&&n.column===this.lead.column&&this.session.lineWidgets&&this.session.lineWidgets[n.row]&&(n.row>0||e>0)&&n.row++,this.moveCursorTo(n.row,n.column+t,0===t)},this.moveCursorToPosition=function(e){this.moveCursorTo(e.row,e.column)},this.moveCursorTo=function(e,t,i){var n=this.session.getFoldAt(e,t,1);n&&(e=n.start.row,t=n.start.column),this.$keepDesiredColumnOnChange=!0,this.lead.setPosition(e,t),this.$keepDesiredColumnOnChange=!1,i||(this.$desiredColumn=null)},this.moveCursorToScreen=function(e,t,i){var n=this.session.screenToDocumentPosition(e,t);this.moveCursorTo(n.row,n.column,i)},this.detach=function(){this.lead.detach(),this.anchor.detach(),this.session=this.doc=null},this.fromOrientedRange=function(e){this.setSelectionRange(e,e.cursor==e.start),this.$desiredColumn=e.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(e){var t=this.getRange();return e?(e.start.column=t.start.column,e.start.row=t.start.row,e.end.column=t.end.column,e.end.row=t.end.row):e=t,e.cursor=this.isBackwards()?e.start:e.end,e.desiredColumn=this.$desiredColumn,e},this.getRangeOfMovements=function(e){var t=this.getCursor();try{e.call(null,this);var i=this.getCursor();return s.fromPoints(t,i)}catch(n){return s.fromPoints(t,t)}finally{this.moveCursorToPosition(t)}},this.toJSON=function(){if(this.rangeCount)var e=this.ranges.map(function(e){var t=e.clone();return t.isBackwards=e.cursor==e.start,t});else{var e=this.getRange();e.isBackwards=this.isBackwards()}return e},this.fromJSON=function(e){if(void 0==e.start){if(this.rangeList){this.toSingleRange(e[0]);for(var t=e.length;t--;){var i=s.fromPoints(e[t].start,e[t].end);e[t].isBackwards&&(i.cursor=i.start),this.addRange(i,!0)}return}e=e[0]}this.rangeList&&this.toSingleRange(e),this.setSelectionRange(e,e.isBackwards)},this.isEqual=function(e){if((e.length||this.rangeCount)&&e.length!=this.rangeCount)return!1;if(!e.length||!this.ranges)return this.getRange().isEqual(e);for(var t=this.ranges.length;t--;)if(!this.ranges[t].isEqual(e[t]))return!1;return!0}}).call(a.prototype),t.Selection=a}),ace.define("ace/tokenizer",["require","exports","module","ace/config"],function(e,t,i){"use strict";var n=e("./config"),r=2e3,o=function(e){this.states=e,this.regExps={},this.matchMappings={};for(var t in this.states){for(var i=this.states[t],n=[],r=0,o=this.matchMappings[t]={defaultToken:"text"},s="g",a=[],l=0;l1?c.onMatch=this.$applyToken:c.onMatch=c.token),d>1&&(/\\\d/.test(c.regex)?h=c.regex.replace(/\\([0-9]+)/g,function(e,t){return"\\"+(parseInt(t,10)+r+1)}):(d=1,h=this.removeCapturingGroups(c.regex)),c.splitRegex||"string"==typeof c.token||a.push(c)),o[r]=l,r+=d,n.push(h),c.onMatch||(c.onMatch=null)}}n.length||(o[0]=0,n.push("$")),a.forEach(function(e){e.splitRegex=this.createSplitterRegexp(e.regex,s)},this),this.regExps[t]=new RegExp("("+n.join(")|(")+")|($)",s)}};(function(){this.$setMaxTokenCount=function(e){r=0|e},this.$applyToken=function(e){var t=this.splitRegex.exec(e).slice(1),i=this.token.apply(this,t);if("string"==typeof i)return[{type:i,value:e}];for(var n=[],r=0,o=i.length;o>r;r++)t[r]&&(n[n.length]={type:i[r],value:t[r]});return n},this.$arrayTokens=function(e){if(!e)return[];var t=this.splitRegex.exec(e);if(!t)return"text";for(var i=[],n=this.tokenArray,r=0,o=n.length;o>r;r++)t[r+1]&&(i[i.length]={type:n[r],value:t[r+1]});return i},this.removeCapturingGroups=function(e){var t=e.replace(/\[(?:\\.|[^\]])*?\]|\\.|\(\?[:=!]|(\()/g,function(e,t){return t?"(?:":e});return t},this.createSplitterRegexp=function(e,t){if(-1!=e.indexOf("(?=")){var i=0,n=!1,r={};e.replace(/(\\.)|(\((?:\?[=!])?)|(\))|([\[\]])/g,function(e,t,o,s,a,l){return n?n="]"!=a:a?n=!0:s?(i==r.stack&&(r.end=l+1,r.stack=-1),i--):o&&(i++,1!=o.length&&(r.stack=i,r.start=l)),e}),null!=r.end&&/^\)*$/.test(e.substr(r.end))&&(e=e.substring(0,r.start)+e.substr(r.end))}return"^"!=e.charAt(0)&&(e="^"+e),"$"!=e.charAt(e.length-1)&&(e+="$"),new RegExp(e,(t||"").replace("g",""))},this.getLineTokens=function(e,t){if(t&&"string"!=typeof t){var i=t.slice(0);t=i[0],"#tmp"===t&&(i.shift(),t=i.shift())}else var i=[];var n=t||"start",o=this.states[n];o||(n="start",o=this.states[n]);var s=this.matchMappings[n],a=this.regExps[n]; -a.lastIndex=0;for(var l,c=[],h=0,d=0,u={type:null,value:""};l=a.exec(e);){var f=s.defaultToken,p=null,g=l[0],m=a.lastIndex;if(m-g.length>h){var v=e.substring(h,m-g.length);u.type==f?u.value+=v:(u.type&&c.push(u),u={type:f,value:v})}for(var w=0;wr){for(d>2*e.length&&this.reportError("infinite loop with in ace tokenizer",{startState:t,line:e});h1&&i[0]!==n&&i.unshift("#tmp",n),{tokens:c,state:i.length?i:n}},this.reportError=n.reportError}).call(o.prototype),t.Tokenizer=o}),ace.define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"],function(e,t,i){"use strict";var n=e("../lib/lang"),r=function(){this.$rules={start:[{token:"empty_line",regex:"^$"},{defaultToken:"text"}]}};(function(){this.addRules=function(e,t){if(t)for(var i in e){for(var n=e[i],r=0;r=this.$rowTokens.length;){if(this.$row+=1,e||(e=this.$session.getLength()),this.$row>=e)return this.$row=e-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var e=this.$rowTokens,t=this.$tokenIndex,i=e[t].start;if(void 0!==i)return i;for(i=0;t>0;)t-=1,i+=e[t].value.length;return i},this.getCurrentTokenPosition=function(){return{row:this.$row,column:this.getCurrentTokenColumn()}}}).call(n.prototype),t.TokenIterator=n}),ace.define("ace/mode/text",["require","exports","module","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/behaviour","ace/unicode","ace/lib/lang","ace/token_iterator","ace/range"],function(e,t,i){"use strict";var n=e("../tokenizer").Tokenizer,r=e("./text_highlight_rules").TextHighlightRules,o=e("./behaviour").Behaviour,s=e("../unicode"),a=e("../lib/lang"),l=e("../token_iterator").TokenIterator,c=e("../range").Range,h=function(){this.HighlightRules=r,this.$behaviour=new o};(function(){this.tokenRe=new RegExp("^["+s.packages.L+s.packages.Mn+s.packages.Mc+s.packages.Nd+s.packages.Pc+"\\$_]+","g"), -this.nonTokenRe=new RegExp("^(?:[^"+s.packages.L+s.packages.Mn+s.packages.Mc+s.packages.Nd+s.packages.Pc+"\\$_]|\\s])+","g"),this.getTokenizer=function(){return this.$tokenizer||(this.$highlightRules=this.$highlightRules||new this.HighlightRules,this.$tokenizer=new n(this.$highlightRules.getRules())),this.$tokenizer},this.lineCommentStart="",this.blockComment="",this.toggleCommentLines=function(e,t,i,n){function r(e){for(var t=i;n>=t;t++)e(o.getLine(t),t)}var o=t.doc,s=!0,l=!0,c=1/0,h=t.getTabSize(),d=!1;if(this.lineCommentStart){if(Array.isArray(this.lineCommentStart))var u=this.lineCommentStart.map(a.escapeRegExp).join("|"),f=this.lineCommentStart[0];else var u=a.escapeRegExp(this.lineCommentStart),f=this.lineCommentStart;u=new RegExp("^(\\s*)(?:"+u+") ?"),d=t.getUseSoftTabs();var p=function(e,t){var i=e.match(u);if(i){var n=i[1].length,r=i[0].length;w(e,n,r)||" "!=i[0][r-1]||r--,o.removeInLine(t,n,r)}},g=f+" ",m=function(e,t){(!s||/\S/.test(e))&&(w(e,c,c)?o.insertInLine({row:t,column:c},g):o.insertInLine({row:t,column:c},f))},v=function(e,t){return u.test(e)},w=function(e,t,i){for(var n=0;t--&&" "==e.charAt(t);)n++;if(n%h!=0)return!1;for(var n=0;" "==e.charAt(i++);)n++;return h>2?n%h!=h-1:n%h==0}}else{if(!this.blockComment)return!1;var f=this.blockComment.start,A=this.blockComment.end,u=new RegExp("^(\\s*)(?:"+a.escapeRegExp(f)+")"),y=new RegExp("(?:"+a.escapeRegExp(A)+")\\s*$"),m=function(e,t){v(e,t)||(!s||/\S/.test(e))&&(o.insertInLine({row:t,column:e.length},A),o.insertInLine({row:t,column:c},f))},p=function(e,t){var i;(i=e.match(y))&&o.removeInLine(t,e.length-i[0].length,e.length),(i=e.match(u))&&o.removeInLine(t,i[1].length,i[0].length)},v=function(e,i){if(u.test(e))return!0;for(var n=t.getTokens(i),r=0;ri&&(c=i),l&&!v(e,t)&&(l=!1)):C>e.length&&(C=e.length)}),c==1/0&&(c=C,s=!1,l=!1),d&&c%h!=0&&(c=Math.floor(c/h)*h),r(l?p:m)},this.toggleBlockComment=function(e,t,i,n){var r=this.blockComment;if(r){!r.start&&r[0]&&(r=r[0]);var o,s,a=new l(t,n.row,n.column),h=a.getCurrentToken(),d=(t.selection,t.selection.toOrientedRange());if(h&&/comment/.test(h.type)){for(var u,f;h&&/comment/.test(h.type);){var p=h.value.indexOf(r.start);if(-1!=p){var g=a.getCurrentTokenRow(),m=a.getCurrentTokenColumn()+p;u=new c(g,m,g,m+r.start.length);break}h=a.stepBackward()}for(var a=new l(t,n.row,n.column),h=a.getCurrentToken();h&&/comment/.test(h.type);){var p=h.value.indexOf(r.end);if(-1!=p){var g=a.getCurrentTokenRow(),m=a.getCurrentTokenColumn()+p;f=new c(g,m,g,m+r.end.length);break}h=a.stepForward()}f&&t.remove(f),u&&(t.remove(u),o=u.start.row,s=-r.start.length)}else s=r.start.length,o=i.start.row,t.insert(i.end,r.end),t.insert(i.start,r.start);d.start.row==o&&(d.start.column+=s),d.end.row==o&&(d.end.column+=s),t.selection.fromOrientedRange(d)}},this.getNextLineIndent=function(e,t,i){return this.$getIndent(t)},this.checkOutdent=function(e,t,i){return!1},this.autoOutdent=function(e,t,i){},this.$getIndent=function(e){return e.match(/^\s*/)[0]},this.createWorker=function(e){return null},this.createModeDelegates=function(e){this.$embeds=[],this.$modes={};for(var t in e)e[t]&&(this.$embeds.push(t),this.$modes[t]=new e[t]);for(var i=["toggleBlockComment","toggleCommentLines","getNextLineIndent","checkOutdent","autoOutdent","transformAction","getCompletions"],t=0;to;o++)if("string"==typeof r[o].token)/keyword|support|storage/.test(r[o].token)&&i.push(r[o].regex);else if("object"==typeof r[o].token)for(var a=0,l=r[o].token.length;l>a;a++)if(/keyword|support|storage/.test(r[o].token[a])){var n=r[o].regex.match(/\(.+?\)/g)[a];i.push(n.substr(1,n.length-2))}this.completionKeywords=i}return e?i.concat(this.$keywordList||[]):this.$keywordList},this.$createKeywordList=function(){return this.$highlightRules||this.getTokenizer(),this.$keywordList=this.$highlightRules.$keywordList||[]},this.getCompletions=function(e,t,i,n){var r=this.$keywordList||this.$createKeywordList();return r.map(function(e){return{name:e,value:e,score:0,meta:"keyword"}})},this.$id="ace/mode/text"}).call(h.prototype),t.Mode=h}),ace.define("ace/apply_delta",["require","exports","module"],function(e,t,i){"use strict";t.applyDelta=function(e,t,i){var n=t.start.row,r=t.start.column,o=e[n]||"";switch(t.action){case"insert":var s=t.lines;if(1===s.length)e[n]=o.substring(0,r)+t.lines[0]+o.substring(r);else{var a=[n,1].concat(t.lines);e.splice.apply(e,a),e[n]=o.substring(0,r)+e[n],e[n+t.lines.length-1]+=o.substring(r)}break;case"remove":var l=t.end.column,c=t.end.row;n===c?e[n]=o.substring(0,r)+o.substring(l):e.splice(n,c-n+1,o.substring(0,r)+e[c].substring(l))}}}),ace.define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("./lib/oop"),r=e("./lib/event_emitter").EventEmitter,o=t.Anchor=function(e,t,i){this.$onChange=this.onChange.bind(this),this.attach(e),"undefined"==typeof i?this.setPosition(t.row,t.column):this.setPosition(t,i)};(function(){function e(e,t,i){var n=i?e.column<=t.column:e.columnthis.row)){var i=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(i.row,i.column,!0)}},this.setPosition=function(e,t,i){var n;if(n=i?{row:e,column:t}:this.$clipPositionToDocument(e,t),this.row!=n.row||this.column!=n.column){var r={row:this.row,column:this.column};this.row=n.row,this.column=n.column,this._signal("change",{old:r,value:n})}},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on("change",this.$onChange)},this.$clipPositionToDocument=function(e,t){var i={};return e>=this.document.getLength()?(i.row=Math.max(0,this.document.getLength()-1),i.column=this.document.getLine(i.row).length):0>e?(i.row=0,i.column=0):(i.row=e,i.column=Math.min(this.document.getLine(i.row).length,Math.max(0,t))),0>t&&(i.column=0),i}}).call(o.prototype)}),ace.define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"],function(e,t,i){"use strict";var n=e("./lib/oop"),r=e("./apply_delta").applyDelta,o=e("./lib/event_emitter").EventEmitter,s=e("./range").Range,a=e("./anchor").Anchor,l=function(e){this.$lines=[""],0===e.length?this.$lines=[""]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){n.implement(this,o),this.setValue=function(e){var t=this.getLength()-1;this.remove(new s(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new a(this,e,t)},0==="aaa".split(/a/).length?this.$split=function(e){return e.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(e){return e.split(/\r\n|\r|\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\r\n|\r|\n)/m);this.$autoNewLine=t?t[1]:"\n",this._signal("changeNewLineMode")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";default:return this.$autoNewLine||"\n"}},this.$autoNewLine="",this.$newLineMode="auto",this.setNewLineMode=function(e){this.$newLineMode!==e&&(this.$newLineMode=e,this._signal("changeNewLineMode"))},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return"\r\n"==e||"\r"==e||"\n"==e},this.getLine=function(e){return this.$lines[e]||""},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||"").substring(e.start.column);var i=t.length-1;e.end.row-e.start.row==i&&(t[i]=t[i].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."),this.insertMergedLines(e,["",""])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var i=this.clippedPos(e.row,e.column),n=this.pos(e.row,e.column+t.length);return this.applyDelta({start:i,end:n,action:"insert",lines:[t]},!0),this.clonePos(n)},this.clippedPos=function(e,t){var i=this.getLength();void 0===e?e=i:0>e?e=0:e>=i&&(e=i-1,t=void 0);var n=this.getLine(e);return void 0==t&&(t=n.length),t=Math.min(Math.max(t,0),n.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var i=0;e0,n=t=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:"remove",lines:["",""]})},this.replace=function(e,t){if(e instanceof s||(e=s.fromPoints(e.start,e.end)),0===t.length&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var i;return i=t?this.insert(e.start,t):e.start},this.applyDeltas=function(e){for(var t=0;t=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var i="insert"==e.action;(i?e.lines.length<=1&&!e.lines[0]:!s.comparePoints(e.start,e.end))||(i&&e.lines.length>2e4&&this.$splitAndapplyLargeDelta(e,2e4),r(this.$lines,e,t),this._signal("change",e))},this.$splitAndapplyLargeDelta=function(e,t){for(var i=e.lines,n=i.length,r=e.start.row,o=e.start.column,s=0,a=0;;){s=a,a+=t-1;var l=i.slice(s,a);if(a>n){e.lines=l,e.start.row=r+s,e.start.column=o;break}l.push(""),this.applyDelta({start:this.pos(r+s,o),end:this.pos(r+a,o=0),action:e.action,lines:l},!0)}},this.revertDelta=function(e){this.applyDelta({start:this.clonePos(e.start),end:this.clonePos(e.end),action:"insert"==e.action?"remove":"insert",lines:e.lines.slice()})},this.indexToPosition=function(e,t){for(var i=this.$lines||this.getAllLines(),n=this.getNewLineCharacter().length,r=t||0,o=i.length;o>r;r++)if(e-=i[r].length+n,0>e)return{row:r,column:e+i[r].length+n};return{row:o-1,column:i[o-1].length}},this.positionToIndex=function(e,t){for(var i=this.$lines||this.getAllLines(),n=this.getNewLineCharacter().length,r=0,o=Math.min(e.row,i.length),s=t||0;o>s;++s)r+=i[s].length+n;return r+e.column}}).call(l.prototype),t.Document=l}),ace.define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("./lib/oop"),r=e("./lib/event_emitter").EventEmitter,o=function(e,t){this.running=!1,this.lines=[],this.states=[],this.currentLine=0,this.tokenizer=e;var i=this;this.$worker=function(){if(i.running){for(var e=new Date,t=i.currentLine,n=-1,r=i.doc,o=t;i.lines[t];)t++;var s=r.getLength(),a=0;for(i.running=!1;s>t;){i.$tokenizeRow(t),n=t;do t++;while(i.lines[t]);if(a++,a%5===0&&new Date-e>20){i.running=setTimeout(i.$worker,20);break}}i.currentLine=t,n>=o&&i.fireUpdateEvent(o,n)}}};(function(){n.implement(this,r),this.setTokenizer=function(e){this.tokenizer=e,this.lines=[],this.states=[],this.start(0)},this.setDocument=function(e){this.doc=e,this.lines=[],this.states=[],this.stop()},this.fireUpdateEvent=function(e,t){var i={first:e,last:t};this._signal("update",{data:i})},this.start=function(e){this.currentLine=Math.min(e||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.states.splice(this.currentLine,this.states.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.scheduleStart=function(){this.running||(this.running=setTimeout(this.$worker,700))},this.$updateOnChange=function(e){var t=e.start.row,i=e.end.row-t;if(0===i)this.lines[t]=null;else if("remove"==e.action)this.lines.splice(t,i+1,null),this.states.splice(t,i+1,null);else{var n=Array(i+1);n.unshift(t,1),this.lines.splice.apply(this.lines,n),this.states.splice.apply(this.states,n)}this.currentLine=Math.min(t,this.currentLine,this.doc.getLength()),this.stop()},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(e){return this.lines[e]||this.$tokenizeRow(e)},this.getState=function(e){return this.currentLine==e&&this.$tokenizeRow(e),this.states[e]||"start"},this.$tokenizeRow=function(e){var t=this.doc.getLine(e),i=this.states[e-1],n=this.tokenizer.getLineTokens(t,i,e);return this.states[e]+""!=n.state+""?(this.states[e]=n.state,this.lines[e+1]=null,this.currentLine>e+1&&(this.currentLine=e+1)):this.currentLine==e&&(this.currentLine=e+1),this.lines[e]=n.tokens}}).call(o.prototype),t.BackgroundTokenizer=o}),ace.define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,i){"use strict";var n=e("./lib/lang"),r=(e("./lib/oop"),e("./range").Range),o=function(e,t,i){this.setRegexp(e),this.clazz=t,this.type=i||"text"};(function(){this.MAX_RANGES=500,this.setRegexp=function(e){this.regExp+""!=e+""&&(this.regExp=e,this.cache=[])},this.update=function(e,t,i,o){if(this.regExp)for(var s=o.firstRow,a=o.lastRow,l=s;a>=l;l++){var c=this.cache[l];null==c&&(c=n.getMatchOffsets(i.getLine(l),this.regExp),c.length>this.MAX_RANGES&&(c=c.slice(0,this.MAX_RANGES)),c=c.map(function(e){return new r(l,e.offset,l,e.offset+e.length)}),this.cache[l]=c.length?c:"");for(var h=c.length;h--;)t.drawSingleLineMarker(e,c[h].toScreenRange(i),this.clazz,o)}}}).call(o.prototype),t.SearchHighlight=o}),ace.define("ace/edit_session/fold_line",["require","exports","module","ace/range"],function(e,t,i){"use strict";function n(e,t){this.foldData=e,Array.isArray(t)?this.folds=t:t=this.folds=[t];var i=t[t.length-1];this.range=new r(t[0].start.row,t[0].start.column,i.end.row,i.end.column),this.start=this.range.start,this.end=this.range.end,this.folds.forEach(function(e){e.setFoldLine(this)},this)}var r=e("../range").Range;(function(){this.shiftRow=function(e){this.start.row+=e,this.end.row+=e,this.folds.forEach(function(t){t.start.row+=e,t.end.row+=e})},this.addFold=function(e){if(e.sameRow){if(e.start.rowthis.endRow)throw new Error("Can't add a fold to this FoldLine as it has no connection");this.folds.push(e),this.folds.sort(function(e,t){return-e.range.compareEnd(t.start.row,t.start.column)}),this.range.compareEnd(e.start.row,e.start.column)>0?(this.end.row=e.end.row,this.end.column=e.end.column):this.range.compareStart(e.end.row,e.end.column)<0&&(this.start.row=e.start.row,this.start.column=e.start.column)}else if(e.start.row==this.end.row)this.folds.push(e),this.end.row=e.end.row,this.end.column=e.end.column;else{if(e.end.row!=this.start.row)throw new Error("Trying to add fold to FoldRow that doesn't have a matching row");this.folds.unshift(e),this.start.row=e.start.row,this.start.column=e.start.column}e.foldLine=this},this.containsRow=function(e){return e>=this.start.row&&e<=this.end.row},this.walk=function(e,t,i){var n,r,o,s=0,a=this.folds,l=!0;null==t&&(t=this.end.row,i=this.end.column);for(var c=0;ce)return{row:n.start.row,column:n.start.column+e};if(e-=n.placeholder.length,0>e)return n.start;t=n.end.column}return{row:this.end.row,column:this.end.column+e}}}).call(n.prototype),t.FoldLine=n}),ace.define("ace/range_list",["require","exports","module","ace/range"],function(e,t,i){"use strict";var n=e("./range").Range,r=n.comparePoints,o=function(){this.ranges=[]};(function(){this.comparePoints=r,this.pointIndex=function(e,t,i){for(var n=this.ranges,o=i||0;o0)){var l=r(e,s.start);return 0===a?t&&0!==l?-o-2:o:l>0||0===l&&!t?o:-o-1}}return-o-1},this.add=function(e){var t=!e.isEmpty(),i=this.pointIndex(e.start,t);0>i&&(i=-i-1);var n=this.pointIndex(e.end,t,i);return 0>n?n=-n-1:n++,this.ranges.splice(i,n-i,e)},this.addList=function(e){for(var t=[],i=e.length;i--;)t.push.call(t,this.add(e[i]));return t},this.substractPoint=function(e){var t=this.pointIndex(e);return t>=0?this.ranges.splice(t,1):void 0},this.merge=function(){var e=[],t=this.ranges;t=t.sort(function(e,t){return r(e.start,t.start)});for(var i,n=t[0],o=1;os||(0!=s||i.isEmpty()||n.isEmpty())&&(r(i.end,n.end)<0&&(i.end.row=n.end.row,i.end.column=n.end.column),t.splice(o,1),e.push(n),n=i,o--)}return this.ranges=t,e},this.contains=function(e,t){return this.pointIndex({row:e,column:t})>=0},this.containsPoint=function(e){return this.pointIndex(e)>=0},this.rangeAtPoint=function(e){var t=this.pointIndex(e);return t>=0?this.ranges[t]:void 0},this.clipRows=function(e,t){var i=this.ranges;if(i[0].start.row>t||i[i.length-1].start.rown&&(n=-n-1);var r=this.pointIndex({row:t,column:0},n);0>r&&(r=-r-1);for(var o=[],s=n;r>s;s++)o.push(i[s]);return o},this.removeAll=function(){return this.ranges.splice(0,this.ranges.length)},this.attach=function(e){this.session&&this.detach(),this.session=e,this.onChange=this.$onChange.bind(this),this.session.on("change",this.onChange)},this.detach=function(){this.session&&(this.session.removeListener("change",this.onChange),this.session=null)},this.$onChange=function(e){if("insert"==e.action)var t=e.start,i=e.end;else var i=e.start,t=e.end;for(var n=t.row,r=i.row,o=r-n,s=-t.column+i.column,a=this.ranges,l=0,c=a.length;c>l;l++){var h=a[l];if(!(h.end.rown)break;if(h.start.row==n&&h.start.column>=t.column&&(h.start.column==t.column&&this.$insertRight||(h.start.column+=s,h.start.row+=o)),h.end.row==n&&h.end.column>=t.column){if(h.end.column==t.column&&this.$insertRight)continue;h.end.column==t.column&&s>0&&c-1>l&&h.end.column>h.start.column&&h.end.column==a[l+1].start.column&&(h.end.column-=s),h.end.column+=s,h.end.row+=o}}}if(0!=o&&c>l)for(;c>l;l++){var h=a[l];h.start.row+=o,h.end.row+=o}}}).call(o.prototype),t.RangeList=o}),ace.define("ace/edit_session/fold",["require","exports","module","ace/range","ace/range_list","ace/lib/oop"],function(e,t,i){"use strict";function n(e,t){e.row-=t.row,0==e.row&&(e.column-=t.column)}function r(e,t){n(e.start,t),n(e.end,t)}function o(e,t){0==e.row&&(e.column+=t.column),e.row+=t.row}function s(e,t){o(e.start,t),o(e.end,t)}var a=(e("../range").Range,e("../range_list").RangeList),l=e("../lib/oop"),c=t.Fold=function(e,t){this.foldLine=null,this.placeholder=t,this.range=e,this.start=e.start,this.end=e.end,this.sameRow=e.start.row==e.end.row,this.subFolds=this.ranges=[]};l.inherits(c,a),function(){this.toString=function(){return'"'+this.placeholder+'" '+this.range.toString()},this.setFoldLine=function(e){this.foldLine=e,this.subFolds.forEach(function(t){t.setFoldLine(e)})},this.clone=function(){var e=this.range.clone(),t=new c(e,this.placeholder);return this.subFolds.forEach(function(e){t.subFolds.push(e.clone())}),t.collapseChildren=this.collapseChildren,t},this.addSubFold=function(e){if(!this.range.isEqual(e)){if(!this.range.containsRange(e))throw new Error("A fold can't intersect already existing fold"+e.range+this.range);r(e,this.start);for(var t=e.start.row,i=e.start.column,n=0,o=-1;n=e)return r;if(r.end.row>e)return null}return null},this.getNextFoldLine=function(e,t){var i=this.$foldData,n=0;for(t&&(n=i.indexOf(t)),-1==n&&(n=0),n;n=e)return r}return null},this.getFoldedRowCount=function(e,t){for(var i=this.$foldData,n=t-e+1,r=0;r=t){t>a&&(a>=e?n-=t-a:n=0);break}s>=e&&(n-=a>=e?s-a:s-e+1)}return n},this.$addFoldLine=function(e){return this.$foldData.push(e),this.$foldData.sort(function(e,t){return e.start.row-t.start.row}),e},this.addFold=function(e,t){var i,n=this.$foldData,r=!1;e instanceof s?i=e:(i=new s(t,e),i.collapseChildren=t.collapseChildren),this.$clipRangeToDocument(i.range);var a=i.start.row,l=i.start.column,c=i.end.row,h=i.end.column;if(!(c>a||a==c&&h-2>=l))throw new Error("The range has to be at least 2 characters width");var d=this.getFoldAt(a,l,1),u=this.getFoldAt(c,h,-1);if(d&&u==d)return d.addSubFold(i);d&&!d.range.isStart(a,l)&&this.removeFold(d),u&&!u.range.isEnd(c,h)&&this.removeFold(u);var f=this.getFoldsInRange(i.range);f.length>0&&(this.removeFolds(f),f.forEach(function(e){i.addSubFold(e)}));for(var p=0;p0&&this.foldAll(e.start.row+1,e.end.row,e.collapseChildren-1),e.subFolds=[]},this.expandFolds=function(e){e.forEach(function(e){this.expandFold(e)},this)},this.unfold=function(e,t){var i,n;if(null==e?(i=new r(0,0,this.getLength(),0),t=!0):i="number"==typeof e?new r(e,0,e,this.getLine(e).length):"row"in e?r.fromPoints(e,e):e,n=this.getFoldsInRangeList(i),t)this.removeFolds(n);else for(var o=n;o.length;)this.expandFolds(o),o=this.getFoldsInRangeList(i);return n.length?n:void 0},this.isRowFolded=function(e,t){return!!this.getFoldLine(e,t)},this.getRowFoldEnd=function(e,t){var i=this.getFoldLine(e,t);return i?i.end.row:e},this.getRowFoldStart=function(e,t){var i=this.getFoldLine(e,t);return i?i.start.row:e},this.getFoldDisplayLine=function(e,t,i,n,r){null==n&&(n=e.start.row),null==r&&(r=0),null==t&&(t=e.end.row),null==i&&(i=this.getLine(t).length);var o=this.doc,s="";return e.walk(function(e,t,i,a){if(!(n>t)){if(t==n){if(r>i)return;a=Math.max(r,a)}s+=null!=e?e:o.getLine(t).substring(a,i)}},t,i),s},this.getDisplayLine=function(e,t,i,n){var r=this.getFoldLine(e);if(r)return this.getFoldDisplayLine(r,e,t,i,n);var o;return o=this.doc.getLine(e),o.substring(n||0,t||o.length)},this.$cloneFoldData=function(){var e=[];return e=this.$foldData.map(function(t){var i=t.folds.map(function(e){return e.clone()});return new o(e,i)})},this.toggleFold=function(e){var t,i,n=this.selection,r=n.getRange();if(r.isEmpty()){var o=r.start;if(t=this.getFoldAt(o.row,o.column))return void this.expandFold(t);(i=this.findMatchingBracket(o))?1==r.comparePoint(i)?r.end=i:(r.start=i,r.start.column++,r.end.column--):(i=this.findMatchingBracket({row:o.row,column:o.column+1}))?(1==r.comparePoint(i)?r.end=i:r.start=i,r.start.column++):r=this.getCommentFoldRange(o.row,o.column)||r}else{var s=this.getFoldsInRange(r);if(e&&s.length)return void this.expandFolds(s);1==s.length&&(t=s[0])}if(t||(t=this.getFoldAt(r.start.row,r.start.column)),t&&t.range.toString()==r.toString())return void this.expandFold(t);var a="...";if(!r.isMultiLine()){if(a=this.getTextRange(r),a.length<4)return;a=a.trim().substring(0,2)+".."}this.addFold(a,r)},this.getCommentFoldRange=function(e,t,i){var n=new a(this,e,t),o=n.getCurrentToken();if(o&&/^comment|string/.test(o.type)){var s=new r,l=new RegExp(o.type.replace(/\..*/,"\\."));if(1!=i){do o=n.stepBackward();while(o&&l.test(o.type));n.stepForward()}if(s.start.row=n.getCurrentTokenRow(),s.start.column=n.getCurrentTokenColumn()+2,n=new a(this,e,t),-1!=i){do o=n.stepForward();while(o&&l.test(o.type));o=n.stepBackward()}else o=n.getCurrentToken();return s.end.row=n.getCurrentTokenRow(),s.end.column=n.getCurrentTokenColumn()+o.value.length-2,s}},this.foldAll=function(e,t,i){void 0==i&&(i=1e5);var n=this.foldWidgets;if(n){t=t||this.getLength(),e=e||0;for(var r=e;t>r;r++)if(null==n[r]&&(n[r]=this.getFoldWidget(r)),"start"==n[r]){var o=this.getFoldWidgetRange(r);if(o&&o.isMultiLine()&&o.end.row<=t&&o.start.row>=e){r=o.end.row;try{var s=this.addFold("...",o);s&&(s.collapseChildren=i)}catch(a){}}}}},this.$foldStyles={manual:1,markbegin:1,markbeginend:1},this.$foldStyle="markbegin",this.setFoldStyle=function(e){if(!this.$foldStyles[e])throw new Error("invalid fold style: "+e+"["+Object.keys(this.$foldStyles).join(", ")+"]"); -if(this.$foldStyle!=e){this.$foldStyle=e,"manual"==e&&this.unfold();var t=this.$foldMode;this.$setFolding(null),this.$setFolding(t)}},this.$setFolding=function(e){if(this.$foldMode!=e){if(this.$foldMode=e,this.off("change",this.$updateFoldWidgets),this.off("tokenizerUpdate",this.$tokenizerUpdateFoldWidgets),this._signal("changeAnnotation"),!e||"manual"==this.$foldStyle)return void(this.foldWidgets=null);this.foldWidgets=[],this.getFoldWidget=e.getFoldWidget.bind(e,this,this.$foldStyle),this.getFoldWidgetRange=e.getFoldWidgetRange.bind(e,this,this.$foldStyle),this.$updateFoldWidgets=this.updateFoldWidgets.bind(this),this.$tokenizerUpdateFoldWidgets=this.tokenizerUpdateFoldWidgets.bind(this),this.on("change",this.$updateFoldWidgets),this.on("tokenizerUpdate",this.$tokenizerUpdateFoldWidgets)}},this.getParentFoldRangeData=function(e,t){var i=this.foldWidgets;if(!i||t&&i[e])return{};for(var n,r=e-1;r>=0;){var o=i[r];if(null==o&&(o=i[r]=this.getFoldWidget(r)),"start"==o){var s=this.getFoldWidgetRange(r);if(n||(n=s),s&&s.end.row>=e)break}r--}return{range:-1!==r&&s,firstRange:n}},this.onFoldWidgetClick=function(e,t){t=t.domEvent;var i={children:t.shiftKey,all:t.ctrlKey||t.metaKey,siblings:t.altKey},n=this.$toggleFoldWidget(e,i);if(!n){var r=t.target||t.srcElement;r&&/ace_fold-widget/.test(r.className)&&(r.className+=" ace_invalid")}},this.$toggleFoldWidget=function(e,t){if(this.getFoldWidget){var i=this.getFoldWidget(e),n=this.getLine(e),r="end"===i?-1:1,o=this.getFoldAt(e,-1===r?0:n.length,r);if(o)return void(t.children||t.all?this.removeFold(o):this.expandFold(o));var s=this.getFoldWidgetRange(e,!0);if(s&&!s.isMultiLine()&&(o=this.getFoldAt(s.start.row,s.start.column,1),o&&s.isEqual(o.range)))return void this.removeFold(o);if(t.siblings){var a=this.getParentFoldRangeData(e);if(a.range)var l=a.range.start.row+1,c=a.range.end.row;this.foldAll(l,c,t.all?1e4:0)}else t.children?(c=s?s.end.row:this.getLength(),this.foldAll(e+1,c,t.all?1e4:0)):s&&(t.all&&(s.collapseChildren=1e4),this.addFold("...",s));return s}},this.toggleFoldWidget=function(e){var t=this.selection.getCursor().row;t=this.getRowFoldStart(t);var i=this.$toggleFoldWidget(t,{});if(!i){var n=this.getParentFoldRangeData(t,!0);if(i=n.range||n.firstRange){t=i.start.row;var r=this.getFoldAt(t,this.getLine(t).length,1);r?this.removeFold(r):this.addFold("...",i)}}},this.updateFoldWidgets=function(e){var t=e.start.row,i=e.end.row-t;if(0===i)this.foldWidgets[t]=null;else if("remove"==e.action)this.foldWidgets.splice(t,i+1,null);else{var n=Array(i+1);n.unshift(t,1),this.foldWidgets.splice.apply(this.foldWidgets,n)}},this.tokenizerUpdateFoldWidgets=function(e){var t=e.data;t.first!=t.last&&this.foldWidgets.length>t.first&&this.foldWidgets.splice(t.first,this.foldWidgets.length)}}var r=e("../range").Range,o=e("./fold_line").FoldLine,s=e("./fold").Fold,a=e("../token_iterator").TokenIterator;t.Folding=n}),ace.define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"],function(e,t,i){"use strict";function n(){this.findMatchingBracket=function(e,t){if(0==e.column)return null;var i=t||this.getLine(e.row).charAt(e.column-1);if(""==i)return null;var n=i.match(/([\(\[\{])|([\)\]\}])/);return n?n[1]?this.$findClosingBracket(n[1],e):this.$findOpeningBracket(n[2],e):null},this.getBracketRange=function(e){var t,i=this.getLine(e.row),n=!0,r=i.charAt(e.column-1),s=r&&r.match(/([\(\[\{])|([\)\]\}])/);if(s||(r=i.charAt(e.column),e={row:e.row,column:e.column+1},s=r&&r.match(/([\(\[\{])|([\)\]\}])/),n=!1),!s)return null;if(s[1]){var a=this.$findClosingBracket(s[1],e);if(!a)return null;t=o.fromPoints(e,a),n||(t.end.column++,t.start.column--),t.cursor=t.end}else{var a=this.$findOpeningBracket(s[2],e);if(!a)return null;t=o.fromPoints(a,e),n||(t.start.column++,t.end.column--),t.cursor=t.start}return t},this.$brackets={")":"(","(":")","]":"[","[":"]","{":"}","}":"{"},this.$findOpeningBracket=function(e,t,i){var n=this.$brackets[e],o=1,s=new r(this,t.row,t.column),a=s.getCurrentToken();if(a||(a=s.stepForward()),a){i||(i=new RegExp("(\\.?"+a.type.replace(".","\\.").replace("rparen",".paren").replace(/\b(?:end)\b/,"(?:start|begin|end)")+")+"));for(var l=t.column-s.getCurrentTokenColumn()-2,c=a.value;;){for(;l>=0;){var h=c.charAt(l);if(h==n){if(o-=1,0==o)return{row:s.getCurrentTokenRow(),column:l+s.getCurrentTokenColumn()}}else h==e&&(o+=1);l-=1}do a=s.stepBackward();while(a&&!i.test(a.type));if(null==a)break;c=a.value,l=c.length-1}return null}},this.$findClosingBracket=function(e,t,i){var n=this.$brackets[e],o=1,s=new r(this,t.row,t.column),a=s.getCurrentToken();if(a||(a=s.stepForward()),a){i||(i=new RegExp("(\\.?"+a.type.replace(".","\\.").replace("lparen",".paren").replace(/\b(?:start|begin)\b/,"(?:start|begin|end)")+")+"));for(var l=t.column-s.getCurrentTokenColumn();;){for(var c=a.value,h=c.length;h>l;){var d=c.charAt(l);if(d==n){if(o-=1,0==o)return{row:s.getCurrentTokenRow(),column:l+s.getCurrentTokenColumn()}}else d==e&&(o+=1);l+=1}do a=s.stepForward();while(a&&!i.test(a.type));if(null==a)break;l=0}return null}}}var r=e("../token_iterator").TokenIterator,o=e("../range").Range;t.BracketMatch=n}),ace.define("ace/edit_session",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/config","ace/lib/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/search_highlight","ace/edit_session/folding","ace/edit_session/bracket_match"],function(e,t,i){"use strict";var n=e("./lib/oop"),r=e("./lib/lang"),o=e("./config"),s=e("./lib/event_emitter").EventEmitter,a=e("./selection").Selection,l=e("./mode/text").Mode,c=e("./range").Range,h=e("./document").Document,d=e("./background_tokenizer").BackgroundTokenizer,u=e("./search_highlight").SearchHighlight,f=function(e,t){this.$breakpoints=[],this.$decorations=[],this.$frontMarkers={},this.$backMarkers={},this.$markerId=1,this.$undoSelect=!0,this.$foldData=[],this.$foldData.toString=function(){return this.join("\n")},this.on("changeFold",this.onChangeFold.bind(this)),this.$onChange=this.onChange.bind(this),"object"==typeof e&&e.getLine||(e=new h(e)),this.setDocument(e),this.selection=new a(this),o.resetOptions(this),this.setMode(t),o._signal("session",this)};(function(){function e(e){return 4352>e?!1:e>=4352&&4447>=e||e>=4515&&4519>=e||e>=4602&&4607>=e||e>=9001&&9002>=e||e>=11904&&11929>=e||e>=11931&&12019>=e||e>=12032&&12245>=e||e>=12272&&12283>=e||e>=12288&&12350>=e||e>=12353&&12438>=e||e>=12441&&12543>=e||e>=12549&&12589>=e||e>=12593&&12686>=e||e>=12688&&12730>=e||e>=12736&&12771>=e||e>=12784&&12830>=e||e>=12832&&12871>=e||e>=12880&&13054>=e||e>=13056&&19903>=e||e>=19968&&42124>=e||e>=42128&&42182>=e||e>=43360&&43388>=e||e>=44032&&55203>=e||e>=55216&&55238>=e||e>=55243&&55291>=e||e>=63744&&64255>=e||e>=65040&&65049>=e||e>=65072&&65106>=e||e>=65108&&65126>=e||e>=65128&&65131>=e||e>=65281&&65376>=e||e>=65504&&65510>=e}n.implement(this,s),this.setDocument=function(e){this.doc&&this.doc.removeListener("change",this.$onChange),this.doc=e,e.on("change",this.$onChange),this.bgTokenizer&&this.bgTokenizer.setDocument(this.getDocument()),this.resetCaches()},this.getDocument=function(){return this.doc},this.$resetRowCache=function(e){if(!e)return this.$docRowCache=[],void(this.$screenRowCache=[]);var t=this.$docRowCache.length,i=this.$getRowCacheIndex(this.$docRowCache,e)+1;t>i&&(this.$docRowCache.splice(i,t),this.$screenRowCache.splice(i,t))},this.$getRowCacheIndex=function(e,t){for(var i=0,n=e.length-1;n>=i;){var r=i+n>>1,o=e[r];if(t>o)i=r+1;else{if(!(o>t))return r;n=r-1}}return i-1},this.resetCaches=function(){this.$modified=!0,this.$wrapData=[],this.$rowLengthCache=[],this.$resetRowCache(0),this.bgTokenizer&&this.bgTokenizer.start(0)},this.onChangeFold=function(e){var t=e.data;this.$resetRowCache(t.start.row)},this.onChange=function(e){this.$modified=!0,this.$resetRowCache(e.start.row);var t=this.$updateInternalDataOnChange(e);this.$fromUndo||!this.$undoManager||e.ignore||(this.$deltasDoc.push(e),t&&0!=t.length&&this.$deltasFold.push({action:"removeFolds",folds:t}),this.$informUndoManager.schedule()),this.bgTokenizer&&this.bgTokenizer.$updateOnChange(e),this._signal("change",e)},this.setValue=function(e){this.doc.setValue(e),this.selection.moveTo(0,0),this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.setUndoManager(this.$undoManager),this.getUndoManager().reset()},this.getValue=this.toString=function(){return this.doc.getValue()},this.getSelection=function(){return this.selection},this.getState=function(e){return this.bgTokenizer.getState(e)},this.getTokens=function(e){return this.bgTokenizer.getTokens(e)},this.getTokenAt=function(e,t){var i,n=this.bgTokenizer.getTokens(e),r=0;if(null==t)o=n.length-1,r=this.getLine(e).length;else for(var o=0;o=t));o++);return(i=n[o])?(i.index=o,i.start=r-i.value.length,i):null},this.setUndoManager=function(e){if(this.$undoManager=e,this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel(),e){var t=this;this.$syncInformUndoManager=function(){t.$informUndoManager.cancel(),t.$deltasFold.length&&(t.$deltas.push({group:"fold",deltas:t.$deltasFold}),t.$deltasFold=[]),t.$deltasDoc.length&&(t.$deltas.push({group:"doc",deltas:t.$deltasDoc}),t.$deltasDoc=[]),t.$deltas.length>0&&e.execute({action:"aceupdate",args:[t.$deltas,t],merge:t.mergeUndoDeltas}),t.mergeUndoDeltas=!1,t.$deltas=[]},this.$informUndoManager=r.delayedCall(this.$syncInformUndoManager)}},this.markUndoGroup=function(){this.$syncInformUndoManager&&this.$syncInformUndoManager()},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?r.stringRepeat(" ",this.getTabSize()):" "},this.setUseSoftTabs=function(e){this.setOption("useSoftTabs",e)},this.getUseSoftTabs=function(){return this.$useSoftTabs&&!this.$mode.$indentWithTabs},this.setTabSize=function(e){this.setOption("tabSize",e)},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(e){return this.$useSoftTabs&&e.column%this.$tabSize===0},this.$overwrite=!1,this.setOverwrite=function(e){this.setOption("overwrite",e)},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.addGutterDecoration=function(e,t){this.$decorations[e]||(this.$decorations[e]=""),this.$decorations[e]+=" "+t,this._signal("changeBreakpoint",{})},this.removeGutterDecoration=function(e,t){this.$decorations[e]=(this.$decorations[e]||"").replace(" "+t,""),this._signal("changeBreakpoint",{})},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(e){this.$breakpoints=[];for(var t=0;t0&&(n=!!i.charAt(t-1).match(this.tokenRe)),n||(n=!!i.charAt(t).match(this.tokenRe)),n)var r=this.tokenRe;else if(/^\s+$/.test(i.slice(t-1,t+1)))var r=/\s/;else var r=this.nonTokenRe;var o=t;if(o>0){do o--;while(o>=0&&i.charAt(o).match(r));o++}for(var s=t;se&&(e=t.screenWidth)}),this.lineWidgetWidth=e},this.$computeWidth=function(e){if(this.$modified||e){if(this.$modified=!1,this.$useWrapMode)return this.screenWidth=this.$wrapLimit;for(var t=this.doc.getAllLines(),i=this.$rowLengthCache,n=0,r=0,o=this.$foldData[r],s=o?o.start.row:1/0,a=t.length,l=0;a>l;l++){if(l>s){if(l=o.end.row+1,l>=a)break;o=this.$foldData[r++],s=o?o.start.row:1/0}null==i[l]&&(i[l]=this.$getStringScreenWidth(t[l])[0]),i[l]>n&&(n=i[l])}this.screenWidth=n}},this.getLine=function(e){return this.doc.getLine(e)},this.getLines=function(e,t){return this.doc.getLines(e,t)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(e){return this.doc.getTextRange(e||this.selection.getRange())},this.insert=function(e,t){return this.doc.insert(e,t)},this.remove=function(e){return this.doc.remove(e)},this.removeFullLines=function(e,t){return this.doc.removeFullLines(e,t)},this.undoChanges=function(e,t){if(e.length){this.$fromUndo=!0;for(var i=null,n=e.length-1;-1!=n;n--){var r=e[n];"doc"==r.group?(this.doc.revertDeltas(r.deltas),i=this.$getUndoSelection(r.deltas,!0,i)):r.deltas.forEach(function(e){this.addFolds(e.folds)},this)}return this.$fromUndo=!1,i&&this.$undoSelect&&!t&&this.selection.setSelectionRange(i),i}},this.redoChanges=function(e,t){if(e.length){this.$fromUndo=!0;for(var i=null,n=0;ne.end.column&&(o.start.column+=a),o.end.row==e.end.row&&o.end.column>e.end.column&&(o.end.column+=a)),s&&o.start.row>=e.end.row&&(o.start.row+=s,o.end.row+=s)}if(o.end=this.insert(o.start,n),r.length){var l=e.start,h=o.start,s=h.row-l.row,a=h.column-l.column;this.addFolds(r.map(function(e){return e=e.clone(),e.start.row==l.row&&(e.start.column+=a),e.end.row==l.row&&(e.end.column+=a),e.start.row+=s,e.end.row+=s,e}))}return o},this.indentRows=function(e,t,i){i=i.replace(/\t/g,this.getTabString());for(var n=e;t>=n;n++)this.doc.insertInLine({row:n,column:0},i)},this.outdentRows=function(e){for(var t=e.collapseRows(),i=new c(0,0,0,0),n=this.getTabSize(),r=t.start.row;r<=t.end.row;++r){var o=this.getLine(r);i.start.row=r,i.end.row=r;for(var s=0;n>s&&" "==o.charAt(s);++s);n>s&&" "==o.charAt(s)?(i.start.column=s,i.end.column=s+1):(i.start.column=0,i.end.column=s),this.remove(i)}},this.$moveLines=function(e,t,i){if(e=this.getRowFoldStart(e),t=this.getRowFoldEnd(t),0>i){var n=this.getRowFoldStart(e+i);if(0>n)return 0;var r=n-e}else if(i>0){var n=this.getRowFoldEnd(t+i);if(n>this.doc.getLength()-1)return 0;var r=n-t}else{e=this.$clipRowToDocument(e),t=this.$clipRowToDocument(t);var r=t-e+1}var o=new c(e,0,t,Number.MAX_VALUE),s=this.getFoldsInRange(o).map(function(e){return e=e.clone(),e.start.row+=r,e.end.row+=r,e}),a=0==i?this.doc.getLines(e,t):this.doc.removeFullLines(e,t);return this.doc.insertFullLines(e+r,a),s.length&&this.addFolds(s),r},this.moveLinesUp=function(e,t){return this.$moveLines(e,t,-1)},this.moveLinesDown=function(e,t){return this.$moveLines(e,t,1)},this.duplicateLines=function(e,t){return this.$moveLines(e,t,0)},this.$clipRowToDocument=function(e){return Math.max(0,Math.min(e,this.doc.getLength()-1))},this.$clipColumnToRow=function(e,t){return 0>t?0:Math.min(this.doc.getLine(e).length,t)},this.$clipPositionToDocument=function(e,t){if(t=Math.max(0,t),0>e)e=0,t=0;else{var i=this.doc.getLength();e>=i?(e=i-1,t=this.doc.getLine(i-1).length):t=Math.min(this.doc.getLine(e).length,t)}return{row:e,column:t}},this.$clipRangeToDocument=function(e){e.start.row<0?(e.start.row=0,e.start.column=0):e.start.column=this.$clipColumnToRow(e.start.row,e.start.column);var t=this.doc.getLength()-1;return e.end.row>t?(e.end.row=t,e.end.column=this.doc.getLine(t).length):e.end.column=this.$clipColumnToRow(e.end.row,e.end.column),e},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(e){if(e!=this.$useWrapMode){if(this.$useWrapMode=e,this.$modified=!0,this.$resetRowCache(0),e){var t=this.getLength();this.$wrapData=Array(t),this.$updateWrapData(0,t-1)}this._signal("changeWrapMode")}},this.getUseWrapMode=function(){return this.$useWrapMode},this.setWrapLimitRange=function(e,t){(this.$wrapLimitRange.min!==e||this.$wrapLimitRange.max!==t)&&(this.$wrapLimitRange={min:e,max:t},this.$modified=!0,this.$useWrapMode&&this._signal("changeWrapMode"))},this.adjustWrapLimit=function(e,t){var i=this.$wrapLimitRange;i.max<0&&(i={min:t,max:t});var n=this.$constrainWrapLimit(e,i.min,i.max);return n!=this.$wrapLimit&&n>1?(this.$wrapLimit=n,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._signal("changeWrapLimit")),!0):!1},this.$constrainWrapLimit=function(e,t,i){return t&&(e=Math.max(t,e)),i&&(e=Math.min(i,e)),e},this.getWrapLimit=function(){return this.$wrapLimit},this.setWrapLimit=function(e){this.setWrapLimitRange(e,e)},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(e){var t=this.$useWrapMode,i=e.action,n=e.start,r=e.end,o=n.row,s=r.row,a=s-o,l=null;if(this.$updating=!0,0!=a)if("remove"===i){this[t?"$wrapData":"$rowLengthCache"].splice(o,a);var c=this.$foldData;l=this.getFoldsInRange(e),this.removeFolds(l);var h=this.getFoldLine(r.row),d=0;if(h){h.addRemoveChars(r.row,r.column,n.column-r.column),h.shiftRow(-a);var u=this.getFoldLine(o);u&&u!==h&&(u.merge(h),h=u),d=c.indexOf(h)+1}for(d;d=r.row&&h.shiftRow(-a)}s=o}else{var f=Array(a);f.unshift(o,0);var p=t?this.$wrapData:this.$rowLengthCache;p.splice.apply(p,f);var c=this.$foldData,h=this.getFoldLine(o),d=0;if(h){var g=h.range.compareInside(n.row,n.column);0==g?(h=h.split(n.row,n.column),h&&(h.shiftRow(a),h.addRemoveChars(s,0,r.column-n.column))):-1==g&&(h.addRemoveChars(o,0,r.column-n.column),h.shiftRow(a)),d=c.indexOf(h)+1}for(d;d=o&&h.shiftRow(a)}}else{a=Math.abs(e.start.column-e.end.column),"remove"===i&&(l=this.getFoldsInRange(e),this.removeFolds(l),a=-a);var h=this.getFoldLine(o);h&&h.addRemoveChars(o,n.column,a)}return t&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),this.$updating=!1,t?this.$updateWrapData(o,s):this.$updateRowLengthCache(o,s),l},this.$updateRowLengthCache=function(e,t,i){this.$rowLengthCache[e]=null,this.$rowLengthCache[t]=null},this.$updateWrapData=function(e,t){var i,n,r=this.doc.getAllLines(),o=this.getTabSize(),s=this.$wrapData,l=this.$wrapLimit,c=e;for(t=Math.min(t,r.length-1);t>=c;)n=this.getFoldLine(c,n),n?(i=[],n.walk(function(e,t,n,o){var s;if(null!=e){s=this.$getDisplayTokens(e,i.length),s[0]=a;for(var l=1;lt-A;){var y=c+t-A;if(e[y-1]>=p&&e[y]>=p)o(y);else if(e[y]!=a&&e[y]!=h){for(var C=Math.max(y-(t-(t>>2)),c-1);y>C&&e[y]C&&e[y]C&&e[y]==f;)y--}else for(;y>C&&e[y]C?o(++y):(y=c+t,e[y]==i&&y--,o(y-A))}else{for(y;y!=c-1&&e[y]!=a;y--);if(y>c){o(y);continue}for(y=c+t;yc;c++)s.push(m)}else 32==l?s.push(p):l>39&&48>l||l>57&&64>l?s.push(f):l>=4352&&e(l)?s.push(t,i):s.push(t)}return s},this.$getStringScreenWidth=function(t,i,n){if(0==i)return[0,0];null==i&&(i=1/0),n=n||0;var r,o;for(o=0;o=4352&&e(r)?2:1,!(n>i));o++);return[n,o]},this.lineWidgets=null,this.getRowLength=function(e){if(this.lineWidgets)var t=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0;else t=0;return this.$useWrapMode&&this.$wrapData[e]?this.$wrapData[e].length+1+t:1+t},this.getRowLineCount=function(e){return this.$useWrapMode&&this.$wrapData[e]?this.$wrapData[e].length+1:1},this.getRowWrapIndent=function(e){if(this.$useWrapMode){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE),i=this.$wrapData[t.row];return i.length&&i[0]e)return{row:0,column:0};var i,n,r=0,o=0,s=0,a=0,l=this.$screenRowCache,c=this.$getRowCacheIndex(l,e),h=l.length;if(h&&c>=0)var s=l[c],r=this.$docRowCache[c],d=e>l[h-1];else var d=!h;for(var u=this.getLength()-1,f=this.getNextFoldLine(r),p=f?f.start.row:1/0;e>=s&&(a=this.getRowLength(r),!(s+a>e||r>=u));)s+=a,r++,r>p&&(r=f.end.row+1,f=this.getNextFoldLine(r,f),p=f?f.start.row:1/0),d&&(this.$docRowCache.push(r),this.$screenRowCache.push(s));if(f&&f.start.row<=r)i=this.getFoldDisplayLine(f),r=f.start.row;else{if(e>=s+a||r>u)return{row:u,column:this.getLine(u).length};i=this.getLine(r),f=null}var g=0;if(this.$useWrapMode){var m=this.$wrapData[r];if(m){var v=Math.floor(e-s);n=m[v],v>0&&m.length&&(g=m.indent,o=m[v-1]||m[m.length-1],i=i.substring(o))}}return o+=this.$getStringScreenWidth(i,t-g)[1],this.$useWrapMode&&o>=n&&(o=n-1),f?f.idxToPosition(o):{row:r,column:o}},this.documentToScreenPosition=function(e,t){if("undefined"==typeof t)var i=this.$clipPositionToDocument(e.row,e.column);else i=this.$clipPositionToDocument(e,t);e=i.row,t=i.column;var n=0,r=null,o=null;o=this.getFoldAt(e,t,1),o&&(e=o.start.row,t=o.start.column);var s,a=0,l=this.$docRowCache,c=this.$getRowCacheIndex(l,e),h=l.length;if(h&&c>=0)var a=l[c],n=this.$screenRowCache[c],d=e>l[h-1];else var d=!h;for(var u=this.getNextFoldLine(a),f=u?u.start.row:1/0;e>a;){if(a>=f){if(s=u.end.row+1,s>e)break;u=this.getNextFoldLine(s,u),f=u?u.start.row:1/0}else s=a+1;n+=this.getRowLength(a),a=s,d&&(this.$docRowCache.push(a),this.$screenRowCache.push(n))}var p="";u&&a>=f?(p=this.getFoldDisplayLine(u,e,t),r=u.start.row):(p=this.getLine(e).substring(0,t),r=e);var g=0;if(this.$useWrapMode){var m=this.$wrapData[r];if(m){for(var v=0;p.length>=m[v];)n++,v++;p=p.substring(m[v-1]||0,p.length),g=v>0?m.indent:0}}return{row:n,column:g+this.$getStringScreenWidth(p)[0]}},this.documentToScreenColumn=function(e,t){return this.documentToScreenPosition(e,t).column},this.documentToScreenRow=function(e,t){return this.documentToScreenPosition(e,t).row},this.getScreenLength=function(){var e=0,t=null;if(this.$useWrapMode)for(var i=this.$wrapData.length,n=0,r=0,t=this.$foldData[r++],o=t?t.start.row:1/0;i>n;){var s=this.$wrapData[n];e+=s?s.length+1:1,n++,n>o&&(n=t.end.row+1,t=this.$foldData[r++],o=t?t.start.row:1/0)}else{e=this.getLength();for(var a=this.$foldData,r=0;ri));o++);return[n,o]})},this.destroy=function(){this.bgTokenizer&&(this.bgTokenizer.setDocument(null),this.bgTokenizer=null),this.$stopWorker()}}).call(f.prototype),e("./edit_session/folding").Folding.call(f.prototype),e("./edit_session/bracket_match").BracketMatch.call(f.prototype),o.defineOptions(f.prototype,"session",{wrap:{set:function(e){if(e&&"off"!=e?"free"==e?e=!0:"printMargin"==e?e=-1:"string"==typeof e&&(e=parseInt(e,10)||!1):e=!1,this.$wrap!=e)if(this.$wrap=e,e){var t="number"==typeof e?e:null;this.setWrapLimitRange(t,t),this.setUseWrapMode(!0)}else this.setUseWrapMode(!1)},get:function(){return this.getUseWrapMode()?-1==this.$wrap?"printMargin":this.getWrapLimitRange().min?this.$wrap:"free":"off"},handlesSet:!0},wrapMethod:{set:function(e){e="auto"==e?"text"!=this.$mode.type:"text"!=e,e!=this.$wrapAsCode&&(this.$wrapAsCode=e,this.$useWrapMode&&(this.$modified=!0,this.$resetRowCache(0),this.$updateWrapData(0,this.getLength()-1)))},initialValue:"auto"},indentedSoftWrap:{initialValue:!0},firstLineNumber:{set:function(){this._signal("changeBreakpoint")},initialValue:1},useWorker:{set:function(e){this.$useWorker=e,this.$stopWorker(),e&&this.$startWorker()},initialValue:!0},useSoftTabs:{initialValue:!0},tabSize:{set:function(e){isNaN(e)||this.$tabSize===e||(this.$modified=!0,this.$rowLengthCache=[],this.$tabSize=e,this._signal("changeTabSize"))},initialValue:4,handlesSet:!0},overwrite:{set:function(e){this._signal("changeOverwrite")},initialValue:!1},newLineMode:{set:function(e){this.doc.setNewLineMode(e)},get:function(){return this.doc.getNewLineMode()},handlesSet:!0},mode:{set:function(e){this.setMode(e)},get:function(){return this.$modeId}}}),t.EditSession=f}),ace.define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,i){"use strict";var n=e("./lib/lang"),r=e("./lib/oop"),o=e("./range").Range,s=function(){this.$options={}};(function(){this.set=function(e){return r.mixin(this.$options,e),this},this.getOptions=function(){return n.copyObject(this.$options)},this.setOptions=function(e){this.$options=e},this.find=function(e){var t=this.$options,i=this.$matchIterator(e,t);if(!i)return!1;var n=null;return i.forEach(function(e,i,r){if(e.start)n=e;else{var s=e.offset+(r||0);if(n=new o(i,s,i,s+e.length),!e.length&&t.start&&t.start.start&&0!=t.skipCurrent&&n.isEqual(t.start))return n=null,!1}return!0}),n},this.findAll=function(e){ -var t=this.$options;if(!t.needle)return[];this.$assembleRegExp(t);var i=t.range,r=i?e.getLines(i.start.row,i.end.row):e.doc.getAllLines(),s=[],a=t.re;if(t.$isMultiLine){var l,c=a.length,h=r.length-c;e:for(var d=a.offset||0;h>=d;d++){for(var u=0;c>u;u++)if(-1==r[d+u].search(a[u]))continue e;var f=r[d],p=r[d+c-1],g=f.length-f.match(a[0])[0].length,m=p.match(a[c-1])[0].length;l&&l.end.row===d&&l.end.column>g||(s.push(l=new o(d,g,d+c-1,m)),c>2&&(d=d+c-2))}}else for(var v=0;vv&&s[v].start.columnv&&s[u].end.column>C&&s[u].end.row==i.end.row;)u--;for(s=s.slice(v,u+1),v=0,u=s.length;u>v;v++)s[v].start.row+=i.start.row,s[v].end.row+=i.start.row}return s},this.replace=function(e,t){var i=this.$options,n=this.$assembleRegExp(i);if(i.$isMultiLine)return t;if(n){var r=n.exec(e);if(!r||r[0].length!=e.length)return null;if(t=e.replace(n,t),i.preserveCase){t=t.split("");for(var o=Math.min(e.length,e.length);o--;){var s=e[o];s&&s.toLowerCase()!=s?t[o]=t[o].toUpperCase():t[o]=t[o].toLowerCase()}t=t.join("")}return t}},this.$matchIterator=function(e,t){var i=this.$assembleRegExp(t);if(!i)return!1;var r;if(t.$isMultiLine)var s=i.length,a=function(t,n,a){var l=t.search(i[0]);if(-1!=l){for(var c=1;s>c;c++)if(t=e.getLine(n+c),-1==t.search(i[c]))return;var h=t.match(i[s-1])[0].length,d=new o(n,l,n+s-1,h);return 1==i.offset?(d.start.row--,d.start.column=Number.MAX_VALUE):a&&(d.start.column+=a),r(d)?!0:void 0}};else if(t.backwards)var a=function(e,t,o){for(var s=n.getMatchOffsets(e,i),a=s.length-1;a>=0;a--)if(r(s[a],t,o))return!0};else var a=function(e,t,o){for(var s=n.getMatchOffsets(e,i),a=0;a=s;n--)if(i(e.getLine(n),n))return;if(0!=t.wrap)for(n=a,s=o.row;n>=s;n--)if(i(e.getLine(n),n))return}}:function(i){var n=o.row,r=e.getLine(n).substr(o.column);if(!i(r,n,o.column)){for(n+=1;a>=n;n++)if(i(e.getLine(n),n))return;if(0!=t.wrap)for(n=s,a=o.row;a>=n;n++)if(i(e.getLine(n),n))return}};return{forEach:l}}}).call(s.prototype),t.Search=s}),ace.define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys","ace/lib/useragent"],function(e,t,i){"use strict";function n(e,t){this.platform=t||(s.isMac?"mac":"win"),this.commands={},this.commandKeyBinding={},this.addCommands(e),this.$singleCommand=!0}function r(e,t){n.call(this,e,t),this.$singleCommand=!1}var o=e("../lib/keys"),s=e("../lib/useragent"),a=o.KEY_MODS;r.prototype=n.prototype,function(){function e(e){return"object"==typeof e&&e.bindKey&&e.bindKey.position||0}this.addCommand=function(e){this.commands[e.name]&&this.removeCommand(e),this.commands[e.name]=e,e.bindKey&&this._buildKeyHash(e)},this.removeCommand=function(e,t){var i=e&&("string"==typeof e?e:e.name);e=this.commands[i],t||delete this.commands[i];var n=this.commandKeyBinding;for(var r in n){var o=n[r];if(o==e)delete n[r];else if(Array.isArray(o)){var s=o.indexOf(e);-1!=s&&(o.splice(s,1),1==o.length&&(n[r]=o[0]))}}},this.bindKey=function(e,t,i){return"object"==typeof e&&(void 0==i&&(i=e.position),e=e[this.platform]),e?"function"==typeof t?this.addCommand({exec:t,bindKey:e,name:t.name||e}):void e.split("|").forEach(function(e){var n="";if(-1!=e.indexOf(" ")){var r=e.split(/\s+/);e=r.pop(),r.forEach(function(e){var t=this.parseKeys(e),i=a[t.hashId]+t.key;n+=(n?" ":"")+i,this._addCommandToBinding(n,"chainKeys")},this),n+=" "}var o=this.parseKeys(e),s=a[o.hashId]+o.key;this._addCommandToBinding(n+s,t,i)},this):void 0},this._addCommandToBinding=function(t,i,n){var r,o=this.commandKeyBinding;if(i)if(!o[t]||this.$singleCommand)o[t]=i;else{Array.isArray(o[t])?-1!=(r=o[t].indexOf(i))&&o[t].splice(r,1):o[t]=[o[t]],"number"!=typeof n&&(n=n||i.isDefault?-100:e(i));var s=o[t];for(r=0;rn)break}s.splice(r,0,i)}else delete o[t]},this.addCommands=function(e){e&&Object.keys(e).forEach(function(t){var i=e[t];if(i){if("string"==typeof i)return this.bindKey(i,t);"function"==typeof i&&(i={exec:i}),"object"==typeof i&&(i.name||(i.name=t),this.addCommand(i))}},this)},this.removeCommands=function(e){Object.keys(e).forEach(function(t){this.removeCommand(e[t])},this)},this.bindKeys=function(e){Object.keys(e).forEach(function(t){this.bindKey(t,e[t])},this)},this._buildKeyHash=function(e){this.bindKey(e.bindKey,e)},this.parseKeys=function(e){var t=e.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(e){return e}),i=t.pop(),n=o[i];if(o.FUNCTION_KEYS[n])i=o.FUNCTION_KEYS[n].toLowerCase();else{if(!t.length)return{key:i,hashId:-1};if(1==t.length&&"shift"==t[0])return{key:i.toUpperCase(),hashId:-1}}for(var r=0,s=t.length;s--;){var a=o.KEY_MODS[t[s]];if(null==a)return"undefined"!=typeof console&&console.error("invalid modifier "+t[s]+" in "+e),!1;r|=a}return{key:i,hashId:r}},this.findKeyCommand=function(e,t){var i=a[e]+t;return this.commandKeyBinding[i]},this.handleKeyboard=function(e,t,i,n){if(!(0>n)){var r=a[t]+i,o=this.commandKeyBinding[r];return e.$keyChain&&(e.$keyChain+=" "+r,o=this.commandKeyBinding[e.$keyChain]||o),!o||"chainKeys"!=o&&"chainKeys"!=o[o.length-1]?(e.$keyChain&&(t&&4!=t||1!=i.length?(-1==t||n>0)&&(e.$keyChain=""):e.$keyChain=e.$keyChain.slice(0,-r.length-1)),{command:o}):(e.$keyChain=e.$keyChain||r,{command:"null"})}},this.getStatusText=function(e,t){return t.$keyChain||""}}.call(n.prototype),t.HashHandler=n,t.MultiHashHandler=r}),ace.define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("../lib/oop"),r=e("../keyboard/hash_handler").MultiHashHandler,o=e("../lib/event_emitter").EventEmitter,s=function(e,t){r.call(this,t,e),this.byName=this.commands,this.setDefaultHandler("exec",function(e){return e.command.exec(e.editor,e.args||{})})};n.inherits(s,r),function(){n.implement(this,o),this.exec=function(e,t,i){if(Array.isArray(e)){for(var n=e.length;n--;)if(this.exec(e[n],t,i))return!0;return!1}if("string"==typeof e&&(e=this.commands[e]),!e)return!1;if(t&&t.$readOnly&&!e.readOnly)return!1;var r={editor:t,command:e,args:i};return r.returnValue=this._emit("exec",r),this._signal("afterExec",r),r.returnValue===!1?!1:!0},this.toggleRecording=function(e){return this.$inReplay?void 0:(e&&e._emit("changeStatus"),this.recording?(this.macro.pop(),this.removeEventListener("exec",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(e){this.macro.push([e.command,e.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on("exec",this.$addCommandToMacro),this.recording=!0))},this.replay=function(e){if(!this.$inReplay&&this.macro){if(this.recording)return this.toggleRecording(e);try{this.$inReplay=!0,this.macro.forEach(function(t){"string"==typeof t?this.exec(t,e):this.exec(t[0],e,t[1])},this)}finally{this.$inReplay=!1}}},this.trimMacro=function(e){return e.map(function(e){return"string"!=typeof e[0]&&(e[0]=e[0].name),e[1]||(e=e[0]),e})}}.call(s.prototype),t.CommandManager=s}),ace.define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config","ace/range"],function(e,t,i){"use strict";function n(e,t){return{win:e,mac:t}}var r=e("../lib/lang"),o=e("../config"),s=e("../range").Range;t.commands=[{name:"showSettingsMenu",bindKey:n("Ctrl-,","Command-,"),exec:function(e){o.loadModule("ace/ext/settings_menu",function(t){t.init(e),e.showSettingsMenu()})},readOnly:!0},{name:"goToNextError",bindKey:n("Alt-E","Ctrl-E"),exec:function(e){o.loadModule("ace/ext/error_marker",function(t){t.showErrorMarker(e,1)})},scrollIntoView:"animate",readOnly:!0},{name:"goToPreviousError",bindKey:n("Alt-Shift-E","Ctrl-Shift-E"),exec:function(e){o.loadModule("ace/ext/error_marker",function(t){t.showErrorMarker(e,-1)})},scrollIntoView:"animate",readOnly:!0},{name:"selectall",bindKey:n("Ctrl-A","Command-A"),exec:function(e){e.selectAll()},readOnly:!0},{name:"centerselection",bindKey:n(null,"Ctrl-L"),exec:function(e){e.centerSelection()},readOnly:!0},{name:"gotoline",bindKey:n("Ctrl-L","Command-L"),exec:function(e){var t=parseInt(prompt("Enter line number:"),10);isNaN(t)||e.gotoLine(t)},readOnly:!0},{name:"fold",bindKey:n("Alt-L|Ctrl-F1","Command-Alt-L|Command-F1"),exec:function(e){e.session.toggleFold(!1)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"unfold",bindKey:n("Alt-Shift-L|Ctrl-Shift-F1","Command-Alt-Shift-L|Command-Shift-F1"),exec:function(e){e.session.toggleFold(!0)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"toggleFoldWidget",bindKey:n("F2","F2"),exec:function(e){e.session.toggleFoldWidget()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"toggleParentFoldWidget",bindKey:n("Alt-F2","Alt-F2"),exec:function(e){e.session.toggleFoldWidget(!0)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"foldall",bindKey:n(null,"Ctrl-Command-Option-0"),exec:function(e){e.session.foldAll()},scrollIntoView:"center",readOnly:!0},{name:"foldOther",bindKey:n("Alt-0","Command-Option-0"),exec:function(e){e.session.foldAll(),e.session.unfold(e.selection.getAllRanges())},scrollIntoView:"center",readOnly:!0},{name:"unfoldall",bindKey:n("Alt-Shift-0","Command-Option-Shift-0"),exec:function(e){e.session.unfold()},scrollIntoView:"center",readOnly:!0},{name:"findnext",bindKey:n("Ctrl-K","Command-G"),exec:function(e){e.findNext()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"findprevious",bindKey:n("Ctrl-Shift-K","Command-Shift-G"),exec:function(e){e.findPrevious()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"selectOrFindNext",bindKey:n("Alt-K","Ctrl-G"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findNext()},readOnly:!0},{name:"selectOrFindPrevious",bindKey:n("Alt-Shift-K","Ctrl-Shift-G"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findPrevious()},readOnly:!0},{name:"find",bindKey:n("Ctrl-F","Command-F"),exec:function(e){o.loadModule("ace/ext/searchbox",function(t){t.Search(e)})},readOnly:!0},{name:"overwrite",bindKey:"Insert",exec:function(e){e.toggleOverwrite()},readOnly:!0},{name:"selecttostart",bindKey:n("Ctrl-Shift-Home","Command-Shift-Up"),exec:function(e){e.getSelection().selectFileStart()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"gotostart",bindKey:n("Ctrl-Home","Command-Home|Command-Up"),exec:function(e){e.navigateFileStart()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"selectup",bindKey:n("Shift-Up","Shift-Up"),exec:function(e){e.getSelection().selectUp()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"golineup",bindKey:n("Up","Up|Ctrl-P"),exec:function(e,t){e.navigateUp(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttoend",bindKey:n("Ctrl-Shift-End","Command-Shift-Down"),exec:function(e){e.getSelection().selectFileEnd()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"gotoend",bindKey:n("Ctrl-End","Command-End|Command-Down"),exec:function(e){e.navigateFileEnd()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"selectdown",bindKey:n("Shift-Down","Shift-Down"),exec:function(e){e.getSelection().selectDown()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"golinedown",bindKey:n("Down","Down|Ctrl-N"),exec:function(e,t){e.navigateDown(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectwordleft",bindKey:n("Ctrl-Shift-Left","Option-Shift-Left"),exec:function(e){e.getSelection().selectWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotowordleft",bindKey:n("Ctrl-Left","Option-Left"),exec:function(e){e.navigateWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttolinestart",bindKey:n("Alt-Shift-Left","Command-Shift-Left"),exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotolinestart",bindKey:n("Alt-Left|Home","Command-Left|Home|Ctrl-A"),exec:function(e){e.navigateLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectleft",bindKey:n("Shift-Left","Shift-Left"),exec:function(e){e.getSelection().selectLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotoleft",bindKey:n("Left","Left|Ctrl-B"),exec:function(e,t){e.navigateLeft(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectwordright",bindKey:n("Ctrl-Shift-Right","Option-Shift-Right"),exec:function(e){e.getSelection().selectWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotowordright",bindKey:n("Ctrl-Right","Option-Right"),exec:function(e){e.navigateWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttolineend",bindKey:n("Alt-Shift-Right","Command-Shift-Right"),exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotolineend",bindKey:n("Alt-Right|End","Command-Right|End|Ctrl-E"),exec:function(e){e.navigateLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectright",bindKey:n("Shift-Right","Shift-Right"),exec:function(e){e.getSelection().selectRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotoright",bindKey:n("Right","Right|Ctrl-F"),exec:function(e,t){e.navigateRight(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectpagedown",bindKey:"Shift-PageDown",exec:function(e){e.selectPageDown()},readOnly:!0},{name:"pagedown",bindKey:n(null,"Option-PageDown"),exec:function(e){e.scrollPageDown()},readOnly:!0},{name:"gotopagedown",bindKey:n("PageDown","PageDown|Ctrl-V"),exec:function(e){e.gotoPageDown()},readOnly:!0},{name:"selectpageup",bindKey:"Shift-PageUp",exec:function(e){e.selectPageUp()},readOnly:!0},{name:"pageup",bindKey:n(null,"Option-PageUp"),exec:function(e){e.scrollPageUp()},readOnly:!0},{name:"gotopageup",bindKey:"PageUp",exec:function(e){e.gotoPageUp()},readOnly:!0},{name:"scrollup",bindKey:n("Ctrl-Up",null),exec:function(e){e.renderer.scrollBy(0,-2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"scrolldown",bindKey:n("Ctrl-Down",null),exec:function(e){e.renderer.scrollBy(0,2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"selectlinestart",bindKey:"Shift-Home",exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectlineend",bindKey:"Shift-End",exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"togglerecording",bindKey:n("Ctrl-Alt-E","Command-Option-E"),exec:function(e){e.commands.toggleRecording(e)},readOnly:!0},{name:"replaymacro",bindKey:n("Ctrl-Shift-E","Command-Shift-E"),exec:function(e){e.commands.replay(e)},readOnly:!0},{name:"jumptomatching",bindKey:n("Ctrl-P","Ctrl-P"),exec:function(e){e.jumpToMatching()},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"selecttomatching",bindKey:n("Ctrl-Shift-P","Ctrl-Shift-P"),exec:function(e){e.jumpToMatching(!0)},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"expandToMatching",bindKey:n("Ctrl-Shift-M","Ctrl-Shift-M"),exec:function(e){e.jumpToMatching(!0,!0)},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"passKeysToBrowser",bindKey:n(null,null),exec:function(){},passEvent:!0,readOnly:!0},{name:"copy",exec:function(e){},readOnly:!0},{name:"cut",exec:function(e){var t=e.getSelectionRange();e._emit("cut",t),e.selection.isEmpty()||(e.session.remove(t),e.clearSelection())},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"paste",exec:function(e,t){e.$handlePaste(t)},scrollIntoView:"cursor"},{name:"removeline",bindKey:n("Ctrl-D","Command-D"),exec:function(e){e.removeLines()},scrollIntoView:"cursor",multiSelectAction:"forEachLine"},{name:"duplicateSelection",bindKey:n("Ctrl-Shift-D","Command-Shift-D"),exec:function(e){e.duplicateSelection()},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"sortlines",bindKey:n("Ctrl-Alt-S","Command-Alt-S"),exec:function(e){e.sortLines()},scrollIntoView:"selection",multiSelectAction:"forEachLine"},{name:"togglecomment",bindKey:n("Ctrl-/","Command-/"),exec:function(e){e.toggleCommentLines()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"toggleBlockComment",bindKey:n("Ctrl-Shift-/","Command-Shift-/"),exec:function(e){e.toggleBlockComment()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"modifyNumberUp",bindKey:n("Ctrl-Shift-Up","Alt-Shift-Up"),exec:function(e){e.modifyNumber(1)},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"modifyNumberDown",bindKey:n("Ctrl-Shift-Down","Alt-Shift-Down"),exec:function(e){e.modifyNumber(-1)},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"replace",bindKey:n("Ctrl-H","Command-Option-F"),exec:function(e){o.loadModule("ace/ext/searchbox",function(t){t.Search(e,!0)})}},{name:"undo",bindKey:n("Ctrl-Z","Command-Z"),exec:function(e){e.undo()}},{name:"redo",bindKey:n("Ctrl-Shift-Z|Ctrl-Y","Command-Shift-Z|Command-Y"),exec:function(e){e.redo()}},{name:"copylinesup",bindKey:n("Alt-Shift-Up","Command-Option-Up"),exec:function(e){e.copyLinesUp()},scrollIntoView:"cursor"},{name:"movelinesup",bindKey:n("Alt-Up","Option-Up"),exec:function(e){e.moveLinesUp()},scrollIntoView:"cursor"},{name:"copylinesdown",bindKey:n("Alt-Shift-Down","Command-Option-Down"),exec:function(e){e.copyLinesDown()},scrollIntoView:"cursor"},{name:"movelinesdown",bindKey:n("Alt-Down","Option-Down"),exec:function(e){e.moveLinesDown()},scrollIntoView:"cursor"},{name:"del",bindKey:n("Delete","Delete|Ctrl-D|Shift-Delete"),exec:function(e){e.remove("right")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"backspace",bindKey:n("Shift-Backspace|Backspace","Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H"),exec:function(e){e.remove("left")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"cut_or_delete",bindKey:n("Shift-Delete",null),exec:function(e){return e.selection.isEmpty()?void e.remove("left"):!1},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolinestart",bindKey:n("Alt-Backspace","Command-Backspace"),exec:function(e){e.removeToLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolineend",bindKey:n("Alt-Delete","Ctrl-K"),exec:function(e){e.removeToLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removewordleft",bindKey:n("Ctrl-Backspace","Alt-Backspace|Ctrl-Alt-Backspace"),exec:function(e){e.removeWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removewordright",bindKey:n("Ctrl-Delete","Alt-Delete"),exec:function(e){e.removeWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"outdent",bindKey:n("Shift-Tab","Shift-Tab"),exec:function(e){e.blockOutdent()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"indent",bindKey:n("Tab","Tab"),exec:function(e){e.indent()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"blockoutdent",bindKey:n("Ctrl-[","Ctrl-["),exec:function(e){e.blockOutdent()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"blockindent",bindKey:n("Ctrl-]","Ctrl-]"),exec:function(e){e.blockIndent()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"insertstring",exec:function(e,t){e.insert(t)},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"inserttext",exec:function(e,t){e.insert(r.stringRepeat(t.text||"",t.times||1))},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"splitline",bindKey:n(null,"Ctrl-O"),exec:function(e){e.splitLine()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"transposeletters",bindKey:n("Ctrl-T","Ctrl-T"),exec:function(e){e.transposeLetters()},multiSelectAction:function(e){e.transposeSelections(1)},scrollIntoView:"cursor"},{name:"touppercase",bindKey:n("Ctrl-U","Ctrl-U"),exec:function(e){e.toUpperCase()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"tolowercase",bindKey:n("Ctrl-Shift-U","Ctrl-Shift-U"),exec:function(e){e.toLowerCase()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"expandtoline",bindKey:n("Ctrl-Shift-L","Command-Shift-L"),exec:function(e){var t=e.selection.getRange();t.start.column=t.end.column=0,t.end.row++,e.selection.setRange(t,!1)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"joinlines",bindKey:n(null,null),exec:function(e){for(var t=e.selection.isBackwards(),i=t?e.selection.getSelectionLead():e.selection.getSelectionAnchor(),n=t?e.selection.getSelectionAnchor():e.selection.getSelectionLead(),o=e.session.doc.getLine(i.row).length,a=e.session.doc.getTextRange(e.selection.getRange()),l=a.replace(/\n\s*/," ").length,c=e.session.doc.getLine(i.row),h=i.row+1;h<=n.row+1;h++){var d=r.stringTrimLeft(r.stringTrimRight(e.session.doc.getLine(h)));0!==d.length&&(d=" "+d),c+=d}n.row+10?(e.selection.moveCursorTo(i.row,i.column),e.selection.selectTo(i.row,i.column+l)):(o=e.session.doc.getLine(i.row).length>o?o+1:o,e.selection.moveCursorTo(i.row,o))},multiSelectAction:"forEach",readOnly:!0},{name:"invertSelection",bindKey:n(null,null),exec:function(e){var t=e.session.doc.getLength()-1,i=e.session.doc.getLine(t).length,n=e.selection.rangeList.ranges,r=[];n.length<1&&(n=[e.selection.getRange()]);for(var o=0;o0&&this.$blockScrolling--;var i=t&&t.scrollIntoView;if(i){switch(i){case"center-animate":i="animate";case"center":this.renderer.scrollCursorIntoView(null,.5);break;case"animate":case"cursor":this.renderer.scrollCursorIntoView();break;case"selectionPart":var n=this.selection.getRange(),r=this.renderer.layerConfig;(n.start.row>=r.lastRow||n.end.row<=r.firstRow)&&this.renderer.scrollSelectionIntoView(this.selection.anchor,this.selection.lead)}"animate"==i&&this.renderer.animateScrolling(this.curOp.scrollTop)}this.prevOp=this.curOp,this.curOp=null}},this.$mergeableCommands=["backspace","del","insertstring"],this.$historyTracker=function(e){if(this.$mergeUndoDeltas){var t=this.prevOp,i=this.$mergeableCommands,n=t.command&&e.command.name==t.command.name;if("insertstring"==e.command.name){var r=e.args;void 0===this.mergeNextCommand&&(this.mergeNextCommand=!0),n=n&&this.mergeNextCommand&&(!/\s/.test(r)||/\s/.test(t.args)),this.mergeNextCommand=!0}else n=n&&-1!==i.indexOf(e.command.name);"always"!=this.$mergeUndoDeltas&&Date.now()-this.sequenceStartTime>2e3&&(n=!1),n?this.session.mergeUndoDeltas=!0:-1!==i.indexOf(e.command.name)&&(this.sequenceStartTime=Date.now())}},this.setKeyboardHandler=function(e,t){if(e&&"string"==typeof e){this.$keybindingId=e;var i=this;v.loadModule(["keybinding",e],function(n){i.$keybindingId==e&&i.keyBinding.setKeyboardHandler(n&&n.handler),t&&t()})}else this.$keybindingId=null,this.keyBinding.setKeyboardHandler(e),t&&t()},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(e){if(this.session!=e){this.curOp&&this.endOperation(),this.curOp={};var t=this.session;if(t){this.session.removeEventListener("change",this.$onDocumentChange),this.session.removeEventListener("changeMode",this.$onChangeMode),this.session.removeEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.session.removeEventListener("changeTabSize",this.$onChangeTabSize),this.session.removeEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.session.removeEventListener("changeWrapMode",this.$onChangeWrapMode),this.session.removeEventListener("onChangeFold",this.$onChangeFold),this.session.removeEventListener("changeFrontMarker",this.$onChangeFrontMarker),this.session.removeEventListener("changeBackMarker",this.$onChangeBackMarker),this.session.removeEventListener("changeBreakpoint",this.$onChangeBreakpoint),this.session.removeEventListener("changeAnnotation",this.$onChangeAnnotation),this.session.removeEventListener("changeOverwrite",this.$onCursorChange),this.session.removeEventListener("changeScrollTop",this.$onScrollTopChange),this.session.removeEventListener("changeScrollLeft",this.$onScrollLeftChange);var i=this.session.getSelection();i.removeEventListener("changeCursor",this.$onCursorChange),i.removeEventListener("changeSelection",this.$onSelectionChange)}this.session=e,e?(this.$onDocumentChange=this.onDocumentChange.bind(this),e.addEventListener("change",this.$onDocumentChange),this.renderer.setSession(e),this.$onChangeMode=this.onChangeMode.bind(this),e.addEventListener("changeMode",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),e.addEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.onChangeTabSize.bind(this.renderer),e.addEventListener("changeTabSize",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),e.addEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),e.addEventListener("changeWrapMode",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),e.addEventListener("changeFold",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.addEventListener("changeFrontMarker",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.addEventListener("changeBackMarker",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.addEventListener("changeBreakpoint",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.addEventListener("changeAnnotation",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.addEventListener("changeOverwrite",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.addEventListener("changeScrollTop",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.addEventListener("changeScrollLeft",this.$onScrollLeftChange),this.selection=e.getSelection(),this.selection.addEventListener("changeCursor",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.addEventListener("changeSelection",this.$onSelectionChange),this.onChangeMode(),this.$blockScrolling+=1,this.onCursorChange(),this.$blockScrolling-=1,this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull()):(this.selection=null,this.renderer.setSession(e)),this._signal("changeSession",{session:e,oldSession:t}),this.curOp=null,t&&t._signal("changeEditor",{oldEditor:this}),e&&e._signal("changeEditor",{editor:this})}},this.getSession=function(){return this.session},this.setValue=function(e,t){return this.session.doc.setValue(e),t?1==t?this.navigateFileEnd():-1==t&&this.navigateFileStart():this.selectAll(),e},this.getValue=function(){return this.session.getValue()},this.getSelection=function(){ -return this.selection},this.resize=function(e){this.renderer.onResize(e)},this.setTheme=function(e,t){this.renderer.setTheme(e,t)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(e){this.renderer.setStyle(e)},this.unsetStyle=function(e){this.renderer.unsetStyle(e)},this.getFontSize=function(){return this.getOption("fontSize")||r.computedStyle(this.container,"fontSize")},this.setFontSize=function(e){this.setOption("fontSize",e)},this.$highlightBrackets=function(){if(this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null),!this.$highlightPending){var e=this;this.$highlightPending=!0,setTimeout(function(){e.$highlightPending=!1;var t=e.session;if(t&&t.bgTokenizer){var i=t.findMatchingBracket(e.getCursorPosition());if(i)var n=new f(i.row,i.column,i.row,i.column+1);else if(t.$mode.getMatching)var n=t.$mode.getMatching(e.session);n&&(t.$bracketHighlight=t.addMarker(n,"ace_bracket","text"))}},50)}},this.$highlightTags=function(){if(!this.$highlightTagPending){var e=this;this.$highlightTagPending=!0,setTimeout(function(){e.$highlightTagPending=!1;var t=e.session;if(t&&t.bgTokenizer){var i=e.getCursorPosition(),n=new w(e.session,i.row,i.column),r=n.getCurrentToken();if(!r||!/\b(?:tag-open|tag-name)/.test(r.type))return t.removeMarker(t.$tagHighlight),void(t.$tagHighlight=null);if(-1==r.type.indexOf("tag-open")||(r=n.stepForward())){var o=r.value,s=0,a=n.stepBackward();if("<"==a.value){do a=r,r=n.stepForward(),r&&r.value===o&&-1!==r.type.indexOf("tag-name")&&("<"===a.value?s++:"=0)}else{do r=a,a=n.stepBackward(),r&&r.value===o&&-1!==r.type.indexOf("tag-name")&&("<"===a.value?s++:"=s);n.stepForward()}if(!r)return t.removeMarker(t.$tagHighlight),void(t.$tagHighlight=null);var l=n.getCurrentTokenRow(),c=n.getCurrentTokenColumn(),h=new f(l,c,l,c+r.value.length);t.$tagHighlight&&0!==h.compareRange(t.$backMarkers[t.$tagHighlight].range)&&(t.removeMarker(t.$tagHighlight),t.$tagHighlight=null),h&&!t.$tagHighlight&&(t.$tagHighlight=t.addMarker(h,"ace_bracket","text"))}}},50)}},this.focus=function(){var e=this;setTimeout(function(){e.textInput.focus()}),this.textInput.focus()},this.isFocused=function(){return this.textInput.isFocused()},this.blur=function(){this.textInput.blur()},this.onFocus=function(e){this.$isFocused||(this.$isFocused=!0,this.renderer.showCursor(),this.renderer.visualizeFocus(),this._emit("focus",e))},this.onBlur=function(e){this.$isFocused&&(this.$isFocused=!1,this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._emit("blur",e))},this.$cursorChange=function(){this.renderer.updateCursor()},this.onDocumentChange=function(e){var t=this.session.$useWrapMode,i=e.start.row==e.end.row?e.end.row:1/0;this.renderer.updateLines(e.start.row,i,t),this._signal("change",e),this.$cursorChange(),this.$updateHighlightActiveLine()},this.onTokenizerUpdate=function(e){var t=e.data;this.renderer.updateLines(t.first,t.last)},this.onScrollTopChange=function(){this.renderer.scrollToY(this.session.getScrollTop())},this.onScrollLeftChange=function(){this.renderer.scrollToX(this.session.getScrollLeft())},this.onCursorChange=function(){this.$cursorChange(),this.$blockScrolling||(v.warn("Automatically scrolling cursor into view after selection change","this will be disabled in the next version","set editor.$blockScrolling = Infinity to disable this message"),this.renderer.scrollCursorIntoView()),this.$highlightBrackets(),this.$highlightTags(),this.$updateHighlightActiveLine(),this._signal("changeSelection")},this.$updateHighlightActiveLine=function(){var e,t=this.getSession();if(this.$highlightActiveLine&&("line"==this.$selectionStyle&&this.selection.isMultiLine()||(e=this.getCursorPosition()),!this.renderer.$maxLines||1!==this.session.getLength()||this.renderer.$minLines>1||(e=!1)),t.$highlightLineMarker&&!e)t.removeMarker(t.$highlightLineMarker.id),t.$highlightLineMarker=null;else if(!t.$highlightLineMarker&&e){var i=new f(e.row,e.column,e.row,1/0);i.id=t.addMarker(i,"ace_active-line","screenLine"),t.$highlightLineMarker=i}else e&&(t.$highlightLineMarker.start.row=e.row,t.$highlightLineMarker.end.row=e.row,t.$highlightLineMarker.start.column=e.column,t._signal("changeBackMarker"))},this.onSelectionChange=function(e){var t=this.session;if(t.$selectionMarker&&t.removeMarker(t.$selectionMarker),t.$selectionMarker=null,this.selection.isEmpty())this.$updateHighlightActiveLine();else{var i=this.selection.getRange(),n=this.getSelectionStyle();t.$selectionMarker=t.addMarker(i,"ace_selection",n)}var r=this.$highlightSelectedWord&&this.$getSelectionHighLightRegexp();this.session.highlight(r),this._signal("changeSelection")},this.$getSelectionHighLightRegexp=function(){var e=this.session,t=this.getSelectionRange();if(!t.isEmpty()&&!t.isMultiLine()){var i=t.start.column-1,n=t.end.column+1,r=e.getLine(t.start.row),o=r.length,s=r.substring(Math.max(i,0),Math.min(n,o));if(!(i>=0&&/^[\w\d]/.test(s)||o>=n&&/[\w\d]$/.test(s))&&(s=r.substring(t.start.column,t.end.column),/^[\w\d]+$/.test(s))){var a=this.$search.$assembleRegExp({wholeWord:!0,caseSensitive:!0,needle:s});return a}}},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.updateBreakpoints()},this.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},this.onChangeMode=function(e){this.renderer.updateText(),this._emit("changeMode",e)},this.onChangeWrapLimit=function(){this.renderer.updateFull()},this.onChangeWrapMode=function(){this.renderer.onResize(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getSelectedText=function(){return this.session.getTextRange(this.getSelectionRange())},this.getCopyText=function(){var e=this.getSelectedText();return this._signal("copy",e),e},this.onCopy=function(){this.commands.exec("copy",this)},this.onCut=function(){this.commands.exec("cut",this)},this.onPaste=function(e,t){var i={text:e,event:t};this.commands.exec("paste",this,i)},this.$handlePaste=function(e){"string"==typeof e&&(e={text:e}),this._signal("paste",e);var t=e.text;if(!this.inMultiSelectMode||this.inVirtualSelectionMode)this.insert(t);else{var i=t.split(/\r\n|\r|\n/),n=this.selection.rangeList.ranges;if(i.length>n.length||i.length<2||!i[1])return this.commands.exec("insertstring",this,t);for(var r=n.length;r--;){var o=n[r];o.isEmpty()||this.session.remove(o),this.session.insert(o.start,i[r])}}},this.execCommand=function(e,t){return this.commands.exec(e,this,t)},this.insert=function(e,t){var i=this.session,n=i.getMode(),r=this.getCursorPosition();if(this.getBehavioursEnabled()&&!t){var o=n.transformAction(i.getState(r.row),"insertion",this,i,e);o&&(e!==o.text&&(this.session.mergeUndoDeltas=!1,this.$mergeNextCommand=!1),e=o.text)}if(" "==e&&(e=this.session.getTabString()),this.selection.isEmpty()){if(this.session.getOverwrite()){var s=new f.fromPoints(r,r);s.end.column+=e.length,this.session.remove(s)}}else{var s=this.getSelectionRange();r=this.session.remove(s),this.clearSelection()}if("\n"==e||"\r\n"==e){var a=i.getLine(r.row);if(r.column>a.search(/\S|$/)){var l=a.substr(r.column).search(/\S|$/);i.doc.removeInLine(r.row,r.column,r.column+l)}}this.clearSelection();var c=r.column,h=i.getState(r.row),a=i.getLine(r.row),d=n.checkOutdent(h,a,e);i.insert(r,e);if(o&&o.selection&&this.selection.setSelectionRange(2==o.selection.length?new f(r.row,c+o.selection[0],r.row,c+o.selection[1]):new f(r.row+o.selection[0],o.selection[1],r.row+o.selection[2],o.selection[3])),i.getDocument().isNewLine(e)){var u=n.getNextLineIndent(h,a.slice(0,r.column),i.getTabString());i.insert({row:r.row+1,column:0},u)}d&&n.autoOutdent(h,i,r.row)},this.onTextInput=function(e){this.keyBinding.onTextInput(e)},this.onCommandKey=function(e,t,i){this.keyBinding.onCommandKey(e,t,i)},this.setOverwrite=function(e){this.session.setOverwrite(e)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(e){this.setOption("scrollSpeed",e)},this.getScrollSpeed=function(){return this.getOption("scrollSpeed")},this.setDragDelay=function(e){this.setOption("dragDelay",e)},this.getDragDelay=function(){return this.getOption("dragDelay")},this.setSelectionStyle=function(e){this.setOption("selectionStyle",e)},this.getSelectionStyle=function(){return this.getOption("selectionStyle")},this.setHighlightActiveLine=function(e){this.setOption("highlightActiveLine",e)},this.getHighlightActiveLine=function(){return this.getOption("highlightActiveLine")},this.setHighlightGutterLine=function(e){this.setOption("highlightGutterLine",e)},this.getHighlightGutterLine=function(){return this.getOption("highlightGutterLine")},this.setHighlightSelectedWord=function(e){this.setOption("highlightSelectedWord",e)},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(e){this.renderer.setAnimatedScroll(e)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(e){this.renderer.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setDisplayIndentGuides=function(e){this.renderer.setDisplayIndentGuides(e)},this.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},this.setShowPrintMargin=function(e){this.renderer.setShowPrintMargin(e)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(e){this.renderer.setPrintMarginColumn(e)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.setReadOnly=function(e){this.setOption("readOnly",e)},this.getReadOnly=function(){return this.getOption("readOnly")},this.setBehavioursEnabled=function(e){this.setOption("behavioursEnabled",e)},this.getBehavioursEnabled=function(){return this.getOption("behavioursEnabled")},this.setWrapBehavioursEnabled=function(e){this.setOption("wrapBehavioursEnabled",e)},this.getWrapBehavioursEnabled=function(){return this.getOption("wrapBehavioursEnabled")},this.setShowFoldWidgets=function(e){this.setOption("showFoldWidgets",e)},this.getShowFoldWidgets=function(){return this.getOption("showFoldWidgets")},this.setFadeFoldWidgets=function(e){this.setOption("fadeFoldWidgets",e)},this.getFadeFoldWidgets=function(){return this.getOption("fadeFoldWidgets")},this.remove=function(e){this.selection.isEmpty()&&("left"==e?this.selection.selectLeft():this.selection.selectRight());var t=this.getSelectionRange();if(this.getBehavioursEnabled()){var i=this.session,n=i.getState(t.start.row),r=i.getMode().transformAction(n,"deletion",this,i,t);if(0===t.end.column){var o=i.getTextRange(t);if("\n"==o[o.length-1]){var s=i.getLine(t.end.row);/^\s+$/.test(s)&&(t.end.column=s.length)}}r&&(t=r)}this.session.remove(t),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var e=this.getSelectionRange();e.start.column==e.end.column&&e.start.row==e.end.row&&(e.end.column=0,e.end.row++),this.session.remove(e),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var e=this.getCursorPosition();this.insert("\n"),this.moveCursorToPosition(e)},this.transposeLetters=function(){if(this.selection.isEmpty()){var e=this.getCursorPosition(),t=e.column;if(0!==t){var i,n,r=this.session.getLine(e.row);tt.toLowerCase()?1:0});for(var n=new f(0,0,0,0),r=e.first;r<=e.last;r++){var o=t.getLine(r);n.start.row=r,n.end.row=r,n.end.column=o.length,t.replace(n,i[r-e.first])}},this.toggleCommentLines=function(){var e=this.session.getState(this.getCursorPosition().row),t=this.$getSelectedRows();this.session.getMode().toggleCommentLines(e,this.session,t.first,t.last)},this.toggleBlockComment=function(){var e=this.getCursorPosition(),t=this.session.getState(e.row),i=this.getSelectionRange();this.session.getMode().toggleBlockComment(t,this.session,i,e)},this.getNumberAt=function(e,t){var i=/[\-]?[0-9]+(?:\.[0-9]+)?/g;i.lastIndex=0;for(var n=this.session.getLine(e);i.lastIndex=t){var o={value:r[0],start:r.index,end:r.index+r[0].length};return o}}return null},this.modifyNumber=function(e){var t=this.selection.getCursor().row,i=this.selection.getCursor().column,n=new f(t,i-1,t,i),r=this.session.getTextRange(n);if(!isNaN(parseFloat(r))&&isFinite(r)){var o=this.getNumberAt(t,i);if(o){var s=o.value.indexOf(".")>=0?o.start+o.value.indexOf(".")+1:o.end,a=o.start+o.value.length-s,l=parseFloat(o.value);l*=Math.pow(10,a),e*=s!==o.end&&s>i?Math.pow(10,o.end-i-1):Math.pow(10,o.end-i),l+=e,l/=Math.pow(10,a);var c=l.toFixed(a),h=new f(t,o.start,t,o.end);this.session.replace(h,c),this.moveCursorTo(t,Math.max(o.start+1,i+c.length-o.value.length))}}},this.removeLines=function(){var e=this.$getSelectedRows();this.session.removeFullLines(e.first,e.last),this.clearSelection()},this.duplicateSelection=function(){var e=this.selection,t=this.session,i=e.getRange(),n=e.isBackwards();if(i.isEmpty()){var r=i.start.row;t.duplicateLines(r,r)}else{var o=n?i.start:i.end,s=t.insert(o,t.getTextRange(i),!1);i.start=o,i.end=s,e.setSelectionRange(i,n)}},this.moveLinesDown=function(){this.$moveLines(1,!1)},this.moveLinesUp=function(){this.$moveLines(-1,!1)},this.moveText=function(e,t,i){return this.session.moveText(e,t,i)},this.copyLinesUp=function(){this.$moveLines(-1,!0)},this.copyLinesDown=function(){this.$moveLines(1,!0)},this.$moveLines=function(e,t){var i,n,r=this.selection;if(!r.inMultiSelectMode||this.inVirtualSelectionMode){var o=r.toOrientedRange();i=this.$getSelectedRows(o),n=this.session.$moveLines(i.first,i.last,t?0:e),t&&-1==e&&(n=0),o.moveBy(n,0),r.fromOrientedRange(o)}else{var s=r.rangeList.ranges;r.rangeList.detach(this.session),this.inVirtualSelectionMode=!0;for(var a=0,l=0,c=s.length,h=0;c>h;h++){var d=h;s[h].moveBy(a,0),i=this.$getSelectedRows(s[h]);for(var u=i.first,f=i.last;++hf+1)break;f=p.last}for(h--,a=this.session.$moveLines(u,f,t?0:e),t&&-1==e&&(d=h+1);h>=d;)s[d].moveBy(a,0),d++;t||(a=0),l+=a}r.fromOrientedRange(r.ranges[0]),r.rangeList.attach(this.session),this.inVirtualSelectionMode=!1}},this.$getSelectedRows=function(e){return e=(e||this.getSelectionRange()).collapseRows(),{first:this.session.getRowFoldStart(e.start.row),last:this.session.getRowFoldEnd(e.end.row)}},this.onCompositionStart=function(e){this.renderer.showComposition(this.getCursorPosition())},this.onCompositionUpdate=function(e){this.renderer.setCompositionText(e)},this.onCompositionEnd=function(){this.renderer.hideComposition()},this.getFirstVisibleRow=function(){return this.renderer.getFirstVisibleRow()},this.getLastVisibleRow=function(){return this.renderer.getLastVisibleRow()},this.isRowVisible=function(e){return e>=this.getFirstVisibleRow()&&e<=this.getLastVisibleRow()},this.isRowFullyVisible=function(e){return e>=this.renderer.getFirstFullyVisibleRow()&&e<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$moveByPage=function(e,t){var i=this.renderer,n=this.renderer.layerConfig,r=e*Math.floor(n.height/n.lineHeight);this.$blockScrolling++,t===!0?this.selection.$moveSelection(function(){this.moveCursorBy(r,0)}):t===!1&&(this.selection.moveCursorBy(r,0),this.selection.clearSelection()),this.$blockScrolling--;var o=i.scrollTop;i.scrollBy(0,r*n.lineHeight),null!=t&&i.scrollCursorIntoView(null,.5),i.animateScrolling(o)},this.selectPageDown=function(){this.$moveByPage(1,!0)},this.selectPageUp=function(){this.$moveByPage(-1,!0)},this.gotoPageDown=function(){this.$moveByPage(1,!1)},this.gotoPageUp=function(){this.$moveByPage(-1,!1)},this.scrollPageDown=function(){this.$moveByPage(1)},this.scrollPageUp=function(){this.$moveByPage(-1)},this.scrollToRow=function(e){this.renderer.scrollToRow(e)},this.scrollToLine=function(e,t,i,n){this.renderer.scrollToLine(e,t,i,n)},this.centerSelection=function(){var e=this.getSelectionRange(),t={row:Math.floor(e.start.row+(e.end.row-e.start.row)/2),column:Math.floor(e.start.column+(e.end.column-e.start.column)/2)};this.renderer.alignCursor(t,.5)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.$blockScrolling+=1,this.selection.selectAll(),this.$blockScrolling-=1},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(e,t){this.selection.moveCursorTo(e,t)},this.moveCursorToPosition=function(e){this.selection.moveCursorToPosition(e)},this.jumpToMatching=function(e,t){var i=this.getCursorPosition(),n=new w(this.session,i.row,i.column),r=n.getCurrentToken(),o=r||n.stepForward();if(o){var s,a,l=!1,c={},h=i.column-o.start,d={")":"(","(":"(","]":"[","[":"[","{":"{","}":"{"};do{if(o.value.match(/[{}()\[\]]/g)){for(;h=0;--o)this.$tryReplace(i[o],e)&&n++;return this.selection.setSelectionRange(r),this.$blockScrolling-=1,n},this.$tryReplace=function(e,t){var i=this.session.getTextRange(e);return t=this.$search.replace(i,t),null!==t?(e.end=this.session.replace(e,t),e):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(e,t,i){t||(t={}),"string"==typeof e||e instanceof RegExp?t.needle=e:"object"==typeof e&&n.mixin(t,e);var r=this.selection.getRange();null==t.needle&&(e=this.session.getTextRange(r)||this.$search.$options.needle,e||(r=this.session.getWordRange(r.start.row,r.start.column),e=this.session.getTextRange(r)),this.$search.set({needle:e})),this.$search.set(t),t.start||this.$search.set({start:r});var o=this.$search.find(this.session);return t.preventScroll?o:o?(this.revealRange(o,i),o):(t.backwards?r.start=r.end:r.end=r.start,void this.selection.setRange(r))},this.findNext=function(e,t){this.find({skipCurrent:!0,backwards:!1},e,t)},this.findPrevious=function(e,t){this.find(e,{skipCurrent:!0,backwards:!0},t)},this.revealRange=function(e,t){this.$blockScrolling+=1,this.session.unfold(e),this.selection.setSelectionRange(e),this.$blockScrolling-=1;var i=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(e.start,e.end,.5),t!==!1&&this.renderer.animateScrolling(i)},this.undo=function(){this.$blockScrolling++,this.session.getUndoManager().undo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.redo=function(){this.$blockScrolling++,this.session.getUndoManager().redo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.destroy=function(){this.renderer.destroy(),this._signal("destroy",this),this.session&&this.session.destroy()},this.setAutoScrollEditorIntoView=function(e){if(e){var t,i=this,n=!1;this.$scrollAnchor||(this.$scrollAnchor=document.createElement("div"));var r=this.$scrollAnchor;r.style.cssText="position:absolute",this.container.insertBefore(r,this.container.firstChild);var o=this.on("changeSelection",function(){n=!0}),s=this.renderer.on("beforeRender",function(){n&&(t=i.renderer.container.getBoundingClientRect())}),a=this.renderer.on("afterRender",function(){if(n&&t&&(i.isFocused()||i.searchBox&&i.searchBox.isFocused())){var e=i.renderer,o=e.$cursorLayer.$pixelPos,s=e.layerConfig,a=o.top-s.offset;n=o.top>=0&&a+t.top<0?!0:o.topwindow.innerHeight?!1:null,null!=n&&(r.style.top=a+"px",r.style.left=o.left+"px",r.style.height=s.lineHeight+"px",r.scrollIntoView(n)),n=t=null}});this.setAutoScrollEditorIntoView=function(e){e||(delete this.setAutoScrollEditorIntoView,this.removeEventListener("changeSelection",o),this.renderer.removeEventListener("afterRender",a),this.renderer.removeEventListener("beforeRender",s))}}},this.$resetCursorStyle=function(){var e=this.$cursorStyle||"ace",t=this.renderer.$cursorLayer;t&&(t.setSmoothBlinking(/smooth/.test(e)),t.isBlinking=!this.$readOnly&&"wide"!=e,r.setCssClass(t.element,"ace_slim-cursors",/slim/.test(e)))}}).call(A.prototype),v.defineOptions(A.prototype,"editor",{selectionStyle:{set:function(e){this.onSelectionChange(),this._signal("changeSelectionStyle",{data:e})},initialValue:"line"},highlightActiveLine:{set:function(){this.$updateHighlightActiveLine()},initialValue:!0},highlightSelectedWord:{set:function(e){this.$onSelectionChange()},initialValue:!0},readOnly:{set:function(e){this.$resetCursorStyle()},initialValue:!1},cursorStyle:{set:function(e){this.$resetCursorStyle()},values:["ace","slim","smooth","wide"],initialValue:"ace"},mergeUndoDeltas:{values:[!1,!0,"always"],initialValue:!0},behavioursEnabled:{initialValue:!0},wrapBehavioursEnabled:{initialValue:!0},autoScrollEditorIntoView:{set:function(e){this.setAutoScrollEditorIntoView(e)}},hScrollBarAlwaysVisible:"renderer",vScrollBarAlwaysVisible:"renderer",highlightGutterLine:"renderer",animatedScroll:"renderer",showInvisibles:"renderer",showPrintMargin:"renderer",printMarginColumn:"renderer",printMargin:"renderer",fadeFoldWidgets:"renderer",showFoldWidgets:"renderer",showLineNumbers:"renderer",showGutter:"renderer",displayIndentGuides:"renderer",fontSize:"renderer",fontFamily:"renderer",maxLines:"renderer",minLines:"renderer",scrollPastEnd:"renderer",fixedWidthGutter:"renderer",theme:"renderer",scrollSpeed:"$mouseHandler",dragDelay:"$mouseHandler",dragEnabled:"$mouseHandler",focusTimout:"$mouseHandler",tooltipFollowsMouse:"$mouseHandler",firstLineNumber:"session",overwrite:"session",newLineMode:"session",useWorker:"session",useSoftTabs:"session",tabSize:"session",wrap:"session",indentedSoftWrap:"session",foldStyle:"session",mode:"session"}),t.Editor=A}),ace.define("ace/undomanager",["require","exports","module"],function(e,t,i){"use strict";var n=function(){this.reset()};(function(){function e(e){return{action:e.action,start:e.start,end:e.end,lines:1==e.lines.length?null:e.lines,text:1==e.lines.length?e.lines[0]:null}}function t(e){return{action:e.action,start:e.start,end:e.end,lines:e.lines||[e.text]}}function i(e,t){for(var i=new Array(e.length),n=0;n0},this.hasRedo=function(){return this.$redoStack.length>0},this.markClean=function(){this.dirtyCounter=0},this.isClean=function(){return 0===this.dirtyCounter},this.$serializeDeltas=function(t){return i(t,e)},this.$deserializeDeltas=function(e){return i(e,t)}}).call(n.prototype),t.UndoManager=n}),ace.define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("../lib/dom"),r=e("../lib/oop"),o=e("../lib/lang"),s=e("../lib/event_emitter").EventEmitter,a=function(e){this.element=n.createElement("div"),this.element.className="ace_layer ace_gutter-layer",e.appendChild(this.element),this.setShowFoldWidgets(this.$showFoldWidgets),this.gutterWidth=0,this.$annotations=[],this.$updateAnnotations=this.$updateAnnotations.bind(this),this.$cells=[]};(function(){r.implement(this,s),this.setSession=function(e){this.session&&this.session.removeEventListener("change",this.$updateAnnotations),this.session=e,e&&e.on("change",this.$updateAnnotations)},this.addGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.addGutterDecoration"),this.session.addGutterDecoration(e,t)},this.removeGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.removeGutterDecoration"),this.session.removeGutterDecoration(e,t)},this.setAnnotations=function(e){this.$annotations=[];for(var t=0;ts&&(g=o.end.row+1,o=t.getNextFoldLine(g,o),s=o?o.start.row:1/0),g>r){for(;this.$cells.length>p+1;)f=this.$cells.pop(),this.element.removeChild(f.element);break}f=this.$cells[++p],f||(f={element:null,textNode:null,foldWidget:null},f.element=n.createElement("div"),f.textNode=document.createTextNode(""),f.element.appendChild(f.textNode),this.element.appendChild(f.element),this.$cells[p]=f); -var m="ace_gutter-cell ";l[g]&&(m+=l[g]),c[g]&&(m+=c[g]),this.$annotations[g]&&(m+=this.$annotations[g].className),f.element.className!=m&&(f.element.className=m);var v=t.getRowLength(g)*e.lineHeight+"px";if(v!=f.element.style.height&&(f.element.style.height=v),a){var w=a[g];null==w&&(w=a[g]=t.getFoldWidget(g))}if(w){f.foldWidget||(f.foldWidget=n.createElement("span"),f.element.appendChild(f.foldWidget));var m="ace_fold-widget ace_"+w;m+="start"==w&&g==s&&gi.right-t.right?"foldWidgets":void 0}}).call(a.prototype),t.Gutter=a}),ace.define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"],function(e,t,i){"use strict";var n=e("../range").Range,r=e("../lib/dom"),o=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_marker-layer",e.appendChild(this.element)};(function(){function e(e,t,i,n){return(e?1:0)|(t?2:0)|(i?4:0)|(n?8:0)}this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setMarkers=function(e){this.markers=e},this.update=function(e){var e=e||this.config;if(e){this.config=e;var t=[];for(var i in this.markers){var n=this.markers[i];if(n.range){var r=n.range.clipRows(e.firstRow,e.lastRow);if(!r.isEmpty())if(r=r.toScreenRange(this.session),n.renderer){var o=this.$getTop(r.start.row,e),s=this.$padding+r.start.column*e.characterWidth;n.renderer(t,r,s,o,e)}else"fullLine"==n.type?this.drawFullLineMarker(t,r,n.clazz,e):"screenLine"==n.type?this.drawScreenLineMarker(t,r,n.clazz,e):r.isMultiLine()?"text"==n.type?this.drawTextMarker(t,r,n.clazz,e):this.drawMultiLineMarker(t,r,n.clazz,e):this.drawSingleLineMarker(t,r,n.clazz+" ace_start ace_br15",e)}else n.update(t,this,this.session,e)}this.element.innerHTML=t.join("")}},this.$getTop=function(e,t){return(e-t.firstRowScreen)*t.lineHeight},this.drawTextMarker=function(t,i,r,o,s){for(var a=this.session,l=i.start.row,c=i.end.row,h=l,d=0,u=0,f=a.getScreenLastRowColumn(h),p=new n(h,i.start.column,h,u);c>=h;h++)p.start.row=p.end.row=h,p.start.column=h==l?i.start.column:a.getRowWrapIndent(h),p.end.column=f,d=u,u=f,f=c>h+1?a.getScreenLastRowColumn(h+1):h==c?0:i.end.column,this.drawSingleLineMarker(t,p,r+(h==l?" ace_start":"")+" ace_br"+e(h==l||h==l+1&&i.start.column,u>d,u>f,h==c),o,h==c?0:1,s)},this.drawMultiLineMarker=function(e,t,i,n,r){var o=this.$padding,s=n.lineHeight,a=this.$getTop(t.start.row,n),l=o+t.start.column*n.characterWidth;r=r||"",e.push("
"),a=this.$getTop(t.end.row,n);var c=t.end.column*n.characterWidth;if(e.push("
"),s=(t.end.row-t.start.row-1)*n.lineHeight,!(0>=s)){a=this.$getTop(t.start.row+1,n);var h=(t.start.column?1:0)|(t.end.column?0:8);e.push("
")}},this.drawSingleLineMarker=function(e,t,i,n,r,o){var s=n.lineHeight,a=(t.end.column+(r||0)-t.start.column)*n.characterWidth,l=this.$getTop(t.start.row,n),c=this.$padding+t.start.column*n.characterWidth;e.push("
")},this.drawFullLineMarker=function(e,t,i,n,r){var o=this.$getTop(t.start.row,n),s=n.lineHeight;t.start.row!=t.end.row&&(s+=this.$getTop(t.end.row,n)-o),e.push("
")},this.drawScreenLineMarker=function(e,t,i,n,r){var o=this.$getTop(t.start.row,n),s=n.lineHeight;e.push("
")}}).call(o.prototype),t.Marker=o}),ace.define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("../lib/oop"),r=e("../lib/dom"),o=e("../lib/lang"),s=(e("../lib/useragent"),e("../lib/event_emitter").EventEmitter),a=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_text-layer",e.appendChild(this.element),this.$updateEolChar=this.$updateEolChar.bind(this)};(function(){n.implement(this,s),this.EOF_CHAR="¶",this.EOL_CHAR_LF="¬",this.EOL_CHAR_CRLF="¤",this.EOL_CHAR=this.EOL_CHAR_LF,this.TAB_CHAR="—",this.SPACE_CHAR="·",this.$padding=0,this.$updateEolChar=function(){var e="\n"==this.session.doc.getNewLineCharacter()?this.EOL_CHAR_LF:this.EOL_CHAR_CRLF;return this.EOL_CHAR!=e?(this.EOL_CHAR=e,!0):void 0},this.setPadding=function(e){this.$padding=e,this.element.style.padding="0 "+e+"px"},this.getLineHeight=function(){return this.$fontMetrics.$characterSize.height||0},this.getCharacterWidth=function(){return this.$fontMetrics.$characterSize.width||0},this.$setFontMetrics=function(e){this.$fontMetrics=e,this.$fontMetrics.on("changeCharacterSize",function(e){this._signal("changeCharacterSize",e)}.bind(this)),this.$pollSizeChanges()},this.checkForSizeChanges=function(){this.$fontMetrics.checkForSizeChanges()},this.$pollSizeChanges=function(){return this.$pollSizeChangesTimer=this.$fontMetrics.$pollSizeChanges()},this.setSession=function(e){this.session=e,e&&this.$computeTabString()},this.showInvisibles=!1,this.setShowInvisibles=function(e){return this.showInvisibles==e?!1:(this.showInvisibles=e,this.$computeTabString(),!0)},this.displayIndentGuides=!0,this.setDisplayIndentGuides=function(e){return this.displayIndentGuides==e?!1:(this.displayIndentGuides=e,this.$computeTabString(),!0)},this.$tabStrings=[],this.onChangeTabSize=this.$computeTabString=function(){var e=this.session.getTabSize();this.tabSize=e;for(var t=this.$tabStrings=[0],i=1;e+1>i;i++)t.push(this.showInvisibles?""+o.stringRepeat(this.TAB_CHAR,i)+"":o.stringRepeat(" ",i));if(this.displayIndentGuides){this.$indentGuideRe=/\s\S| \t|\t |\s$/;var n="ace_indent-guide",r="",s="";if(this.showInvisibles){n+=" ace_invisible",r=" ace_invisible_space",s=" ace_invisible_tab";var a=o.stringRepeat(this.SPACE_CHAR,this.tabSize),l=o.stringRepeat(this.TAB_CHAR,this.tabSize)}else var a=o.stringRepeat(" ",this.tabSize),l=a;this.$tabStrings[" "]=""+a+"",this.$tabStrings[" "]=""+l+""}},this.updateLines=function(e,t,i){(this.config.lastRow!=e.lastRow||this.config.firstRow!=e.firstRow)&&this.scrollLines(e),this.config=e;for(var n=Math.max(t,e.firstRow),r=Math.min(i,e.lastRow),o=this.element.childNodes,s=0,a=e.firstRow;n>a;a++){var l=this.session.getFoldLine(a);if(l){if(l.containsRow(n)){n=l.start.row;break}a=l.end.row}s++}for(var a=n,l=this.session.getNextFoldLine(a),c=l?l.start.row:1/0;;){if(a>c&&(a=l.end.row+1,l=this.session.getNextFoldLine(a,l),c=l?l.start.row:1/0),a>r)break;var h=o[s++];if(h){var d=[];this.$renderLine(d,a,!this.$useLineGroups(),a==c?l:!1),h.style.height=e.lineHeight*this.session.getRowLength(a)+"px",h.innerHTML=d.join("")}a++}},this.scrollLines=function(e){var t=this.config;if(this.config=e,!t||t.lastRow0;n--)i.removeChild(i.firstChild);if(t.lastRow>e.lastRow)for(var n=this.session.getFoldedRowCount(e.lastRow+1,t.lastRow);n>0;n--)i.removeChild(i.lastChild);if(e.firstRowt.lastRow){var r=this.$renderLinesFragment(e,t.lastRow+1,e.lastRow);i.appendChild(r)}},this.$renderLinesFragment=function(e,t,i){for(var n=this.element.ownerDocument.createDocumentFragment(),o=t,s=this.session.getNextFoldLine(o),a=s?s.start.row:1/0;;){if(o>a&&(o=s.end.row+1,s=this.session.getNextFoldLine(o,s),a=s?s.start.row:1/0),o>i)break;var l=r.createElement("div"),c=[];if(this.$renderLine(c,o,!1,o==a?s:!1),l.innerHTML=c.join(""),this.$useLineGroups())l.className="ace_line_group",n.appendChild(l),l.style.height=e.lineHeight*this.session.getRowLength(o)+"px";else for(;l.firstChild;)n.appendChild(l.firstChild);o++}return n},this.update=function(e){this.config=e;for(var t=[],i=e.firstRow,n=e.lastRow,r=i,o=this.session.getNextFoldLine(r),s=o?o.start.row:1/0;;){if(r>s&&(r=o.end.row+1,o=this.session.getNextFoldLine(r,o),s=o?o.start.row:1/0),r>n)break;this.$useLineGroups()&&t.push("
"),this.$renderLine(t,r,!1,r==s?o:!1),this.$useLineGroups()&&t.push("
"),r++}this.element.innerHTML=t.join("")},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(e,t,i,n){var r=this,s=/\t|&|<|>|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF\uFFF9-\uFFFC])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g,a=function(e,i,n,s,a){if(i)return r.showInvisibles?""+o.stringRepeat(r.SPACE_CHAR,e.length)+"":e;if("&"==e)return"&";if("<"==e)return"<";if(">"==e)return">";if(" "==e){var l=r.session.getScreenTabSize(t+s);return t+=l-1,r.$tabStrings[l]}if(" "==e){var c=r.showInvisibles?"ace_cjk ace_invisible ace_invisible_space":"ace_cjk",h=r.showInvisibles?r.SPACE_CHAR:"";return t+=1,""+h+""}return n?""+r.SPACE_CHAR+"":(t+=1,""+e+"")},l=n.replace(s,a);if(this.$textToken[i.type])e.push(l);else{var c="ace_"+i.type.replace(/\./g," ace_"),h="";"fold"==i.type&&(h=" style='width:"+i.value.length*this.config.characterWidth+"px;' "),e.push("",l,"")}return t+n.length},this.renderIndentGuide=function(e,t,i){var n=t.search(this.$indentGuideRe);return 0>=n||n>=i?t:" "==t[0]?(n-=n%this.tabSize,e.push(o.stringRepeat(this.$tabStrings[" "],n/this.tabSize)),t.substr(n)):" "==t[0]?(e.push(o.stringRepeat(this.$tabStrings[" "],n)),t.substr(n)):t},this.$renderWrappedLine=function(e,t,i,n){for(var r=0,s=0,a=i[0],l=0,c=0;c=a;)l=this.$renderToken(e,l,h,d.substring(0,a-r)),d=d.substring(a-r),r=a,n||e.push("","
"),e.push(o.stringRepeat(" ",i.indent)),s++,l=0,a=i[s]||Number.MAX_VALUE;0!=d.length&&(r+=d.length,l=this.$renderToken(e,l,h,d))}}},this.$renderSimpleLine=function(e,t){var i=0,n=t[0],r=n.value;this.displayIndentGuides&&(r=this.renderIndentGuide(e,r)),r&&(i=this.$renderToken(e,i,n,r));for(var o=1;o"),r.length){var o=this.session.getRowSplitData(t);o&&o.length?this.$renderWrappedLine(e,r,o,i):this.$renderSimpleLine(e,r)}this.showInvisibles&&(n&&(t=n.end.row),e.push("",t==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,"")),i||e.push("
")},this.$getFoldLineTokens=function(e,t){function i(e,t,i){for(var n=0,o=0;o+e[n].value.lengthi-t&&(s=s.substring(0,i-t)),r.push({type:e[n].type,value:s}),o=t+s.length,n+=1}for(;i>o&&ni?{type:e[n].type,value:s.substring(0,i-o)}:e[n]),o+=s.length,n+=1}}var n=this.session,r=[],o=n.getTokens(e);return t.walk(function(e,t,s,a,l){null!=e?r.push({type:"fold",value:e}):(l&&(o=n.getTokens(t)),o.length&&i(o,a,s))},t.end.row,this.session.getLine(t.end.row).length),r},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}}).call(a.prototype),t.Text=a}),ace.define("ace/layer/cursor",["require","exports","module","ace/lib/dom"],function(e,t,i){"use strict";var n,r=e("../lib/dom"),o=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_cursor-layer",e.appendChild(this.element),void 0===n&&(n=!("opacity"in this.element.style)),this.isVisible=!1,this.isBlinking=!0,this.blinkInterval=1e3,this.smoothBlinking=!1,this.cursors=[],this.cursor=this.addCursor(),r.addCssClass(this.element,"ace_hidden-cursors"),this.$updateCursors=(n?this.$updateVisibility:this.$updateOpacity).bind(this)};(function(){this.$updateVisibility=function(e){for(var t=this.cursors,i=t.length;i--;)t[i].style.visibility=e?"":"hidden"},this.$updateOpacity=function(e){for(var t=this.cursors,i=t.length;i--;)t[i].style.opacity=e?"":"0"},this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setBlinking=function(e){e!=this.isBlinking&&(this.isBlinking=e,this.restartTimer())},this.setBlinkInterval=function(e){e!=this.blinkInterval&&(this.blinkInterval=e,this.restartTimer())},this.setSmoothBlinking=function(e){e==this.smoothBlinking||n||(this.smoothBlinking=e,r.setCssClass(this.element,"ace_smooth-blinking",e),this.$updateCursors(!0),this.$updateCursors=this.$updateOpacity.bind(this),this.restartTimer())},this.addCursor=function(){var e=r.createElement("div");return e.className="ace_cursor",this.element.appendChild(e),this.cursors.push(e),e},this.removeCursor=function(){if(this.cursors.length>1){var e=this.cursors.pop();return e.parentNode.removeChild(e),e}},this.hideCursor=function(){this.isVisible=!1,r.addCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.showCursor=function(){this.isVisible=!0,r.removeCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.restartTimer=function(){var e=this.$updateCursors;if(clearInterval(this.intervalId),clearTimeout(this.timeoutId),this.smoothBlinking&&r.removeCssClass(this.element,"ace_smooth-blinking"),e(!0),this.isBlinking&&this.blinkInterval&&this.isVisible){this.smoothBlinking&&setTimeout(function(){r.addCssClass(this.element,"ace_smooth-blinking")}.bind(this));var t=function(){this.timeoutId=setTimeout(function(){e(!1)},.6*this.blinkInterval)}.bind(this);this.intervalId=setInterval(function(){e(!0),t()},this.blinkInterval),t()}},this.getPixelPosition=function(e,t){if(!this.config||!this.session)return{left:0,top:0};e||(e=this.session.selection.getCursor());var i=this.session.documentToScreenPosition(e),n=this.$padding+i.column*this.config.characterWidth,r=(i.row-(t?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:n,top:r}},this.update=function(e){this.config=e;var t=this.session.$selectionMarkers,i=0,n=0;(void 0===t||0===t.length)&&(t=[{cursor:null}]);for(var i=0,r=t.length;r>i;i++){var o=this.getPixelPosition(t[i].cursor,!0);if(!((o.top>e.height+e.offset||o.top<0)&&i>1)){var s=(this.cursors[n++]||this.addCursor()).style;this.drawCursor?this.drawCursor(s,o,e,t[i],this.session):(s.left=o.left+"px",s.top=o.top+"px",s.width=e.characterWidth+"px",s.height=e.lineHeight+"px")}}for(;this.cursors.length>n;)this.removeCursor();var a=this.session.getOverwrite();this.$setOverwrite(a),this.$pixelPos=o,this.restartTimer()},this.drawCursor=null,this.$setOverwrite=function(e){e!=this.overwrite&&(this.overwrite=e,e?r.addCssClass(this.element,"ace_overwrite-cursors"):r.removeCssClass(this.element,"ace_overwrite-cursors"))},this.destroy=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId)}}).call(o.prototype),t.Cursor=o}),ace.define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("./lib/oop"),r=e("./lib/dom"),o=e("./lib/event"),s=e("./lib/event_emitter").EventEmitter,a=function(e){this.element=r.createElement("div"),this.element.className="ace_scrollbar ace_scrollbar"+this.classSuffix,this.inner=r.createElement("div"),this.inner.className="ace_scrollbar-inner",this.element.appendChild(this.inner),e.appendChild(this.element),this.setVisible(!1),this.skipEvent=!1,o.addListener(this.element,"scroll",this.onScroll.bind(this)),o.addListener(this.element,"mousedown",o.preventDefault)};(function(){n.implement(this,s),this.setVisible=function(e){this.element.style.display=e?"":"none",this.isVisible=e}}).call(a.prototype);var l=function(e,t){a.call(this,e),this.scrollTop=0,t.$scrollbarWidth=this.width=r.scrollbarWidth(e.ownerDocument),this.inner.style.width=this.element.style.width=(this.width||15)+5+"px"};n.inherits(l,a),function(){this.classSuffix="-v",this.onScroll=function(){this.skipEvent||(this.scrollTop=this.element.scrollTop,this._emit("scroll",{data:this.scrollTop})),this.skipEvent=!1},this.getWidth=function(){return this.isVisible?this.width:0},this.setHeight=function(e){this.element.style.height=e+"px"},this.setInnerHeight=function(e){this.inner.style.height=e+"px"},this.setScrollHeight=function(e){this.inner.style.height=e+"px"},this.setScrollTop=function(e){this.scrollTop!=e&&(this.skipEvent=!0,this.scrollTop=this.element.scrollTop=e)}}.call(l.prototype);var c=function(e,t){a.call(this,e),this.scrollLeft=0,this.height=t.$scrollbarWidth,this.inner.style.height=this.element.style.height=(this.height||15)+5+"px"};n.inherits(c,a),function(){this.classSuffix="-h",this.onScroll=function(){this.skipEvent||(this.scrollLeft=this.element.scrollLeft,this._emit("scroll",{data:this.scrollLeft})),this.skipEvent=!1},this.getHeight=function(){return this.isVisible?this.height:0},this.setWidth=function(e){this.element.style.width=e+"px"},this.setInnerWidth=function(e){this.inner.style.width=e+"px"},this.setScrollWidth=function(e){this.inner.style.width=e+"px"},this.setScrollLeft=function(e){this.scrollLeft!=e&&(this.skipEvent=!0,this.scrollLeft=this.element.scrollLeft=e)}}.call(c.prototype),t.ScrollBar=l,t.ScrollBarV=l,t.ScrollBarH=c,t.VScrollBar=l,t.HScrollBar=c}),ace.define("ace/renderloop",["require","exports","module","ace/lib/event"],function(e,t,i){"use strict";var n=e("./lib/event"),r=function(e,t){this.onRender=e,this.pending=!1,this.changes=0,this.window=t||window};(function(){this.schedule=function(e){if(this.changes=this.changes|e,!this.pending&&this.changes){this.pending=!0;var t=this;n.nextFrame(function(){t.pending=!1;for(var e;e=t.changes;)t.changes=0,t.onRender(e)},this.window)}}}).call(r.prototype),t.RenderLoop=r}),ace.define("ace/layer/font_metrics",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(e,t,i){var n=e("../lib/oop"),r=e("../lib/dom"),o=e("../lib/lang"),s=e("../lib/useragent"),a=e("../lib/event_emitter").EventEmitter,l=0,c=t.FontMetrics=function(e,t){this.el=r.createElement("div"),this.$setMeasureNodeStyles(this.el.style,!0),this.$main=r.createElement("div"),this.$setMeasureNodeStyles(this.$main.style),this.$measureNode=r.createElement("div"),this.$setMeasureNodeStyles(this.$measureNode.style),this.el.appendChild(this.$main),this.el.appendChild(this.$measureNode),e.appendChild(this.el),l||this.$testFractionalRect(),this.$measureNode.innerHTML=o.stringRepeat("X",l),this.$characterSize={width:0,height:0},this.checkForSizeChanges()};(function(){n.implement(this,a),this.$characterSize={width:0,height:0},this.$testFractionalRect=function(){var e=r.createElement("div");this.$setMeasureNodeStyles(e.style),e.style.width="0.2px",document.documentElement.appendChild(e);var t=e.getBoundingClientRect().width;l=t>0&&1>t?50:100,e.parentNode.removeChild(e)},this.$setMeasureNodeStyles=function(e,t){e.width=e.height="auto",e.left=e.top="0px",e.visibility="hidden",e.position="absolute",e.whiteSpace="pre",s.isIE<8?e["font-family"]="inherit":e.font="inherit",e.overflow=t?"hidden":"visible"},this.checkForSizeChanges=function(){var e=this.$measureSizes();if(e&&(this.$characterSize.width!==e.width||this.$characterSize.height!==e.height)){this.$measureNode.style.fontWeight="bold";var t=this.$measureSizes();this.$measureNode.style.fontWeight="",this.$characterSize=e,this.charSizes=Object.create(null),this.allowBoldFonts=t&&t.width===e.width&&t.height===e.height,this._emit("changeCharacterSize",{data:e})}},this.$pollSizeChanges=function(){if(this.$pollSizeChangesTimer)return this.$pollSizeChangesTimer;var e=this;return this.$pollSizeChangesTimer=setInterval(function(){e.checkForSizeChanges()},500)},this.setPolling=function(e){e?this.$pollSizeChanges():this.$pollSizeChangesTimer&&(clearInterval(this.$pollSizeChangesTimer),this.$pollSizeChangesTimer=0)},this.$measureSizes=function(){if(50===l){var e=null;try{e=this.$measureNode.getBoundingClientRect()}catch(t){e={width:0,height:0}}var i={height:e.height,width:e.width/l}}else var i={height:this.$measureNode.clientHeight,width:this.$measureNode.clientWidth/l};return 0===i.width||0===i.height?null:i},this.$measureCharWidth=function(e){this.$main.innerHTML=o.stringRepeat(e,l);var t=this.$main.getBoundingClientRect();return t.width/l},this.getCharacterWidth=function(e){var t=this.charSizes[e];return void 0===t&&(t=this.charSizes[e]=this.$measureCharWidth(e)/this.$characterSize.width),t},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.el&&this.el.parentNode&&this.el.parentNode.removeChild(this.el)}}).call(c.prototype)}),ace.define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/config","ace/lib/useragent","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/scrollbar","ace/renderloop","ace/layer/font_metrics","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("./lib/oop"),r=e("./lib/dom"),o=e("./config"),s=e("./lib/useragent"),a=e("./layer/gutter").Gutter,l=e("./layer/marker").Marker,c=e("./layer/text").Text,h=e("./layer/cursor").Cursor,d=e("./scrollbar").HScrollBar,u=e("./scrollbar").VScrollBar,f=e("./renderloop").RenderLoop,p=e("./layer/font_metrics").FontMetrics,g=e("./lib/event_emitter").EventEmitter,m='.ace_editor { position: relative; overflow: hidden; font: 12px/normal \'Monaco\', \'Menlo\', \'Ubuntu Mono\', \'Consolas\', \'source-code-pro\', monospace; direction: ltr; } .ace_scroller { position: absolute; overflow: hidden; top: 0; bottom: 0; background-color: inherit; -ms-user-select: none; -moz-user-select: none; -webkit-user-select: none; user-select: none; cursor: text; } .ace_content { position: absolute; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; min-width: 100%; } .ace_dragging .ace_scroller:before{ position: absolute; top: 0; left: 0; right: 0; bottom: 0; content: \'\'; background: rgba(250, 250, 250, 0.01); z-index: 1000; } .ace_dragging.ace_dark .ace_scroller:before{ background: rgba(0, 0, 0, 0.01); } .ace_selecting, .ace_selecting * { cursor: text !important; } .ace_gutter { position: absolute; overflow : hidden; width: auto; top: 0; bottom: 0; left: 0; cursor: default; z-index: 4; -ms-user-select: none; -moz-user-select: none; -webkit-user-select: none; user-select: none; } .ace_gutter-active-line { position: absolute; left: 0; right: 0; } .ace_scroller.ace_scroll-left { box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset; } .ace_gutter-cell { padding-left: 19px; padding-right: 6px; background-repeat: no-repeat; } .ace_gutter-cell.ace_error { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg=="); background-repeat: no-repeat; background-position: 2px center; } .ace_gutter-cell.ace_warning { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg=="); background-position: 2px center; } .ace_gutter-cell.ace_info { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII="); background-position: 2px center; } .ace_dark .ace_gutter-cell.ace_info { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC"); } .ace_scrollbar { position: absolute; right: 0; bottom: 0; z-index: 6; } .ace_scrollbar-inner { position: absolute; cursor: text; left: 0; top: 0; } .ace_scrollbar-v{ overflow-x: hidden; overflow-y: scroll; top: 0; } .ace_scrollbar-h { overflow-x: scroll; overflow-y: hidden; left: 0; } .ace_print-margin { position: absolute; height: 100%; } .ace_text-input { position: absolute; z-index: 0; width: 0.5em; height: 1em; opacity: 0; background: transparent; -moz-appearance: none; appearance: none; border: none; resize: none; outline: none; overflow: hidden; font: inherit; padding: 0 1px; margin: 0 -1px; text-indent: -1em; -ms-user-select: text; -moz-user-select: text; -webkit-user-select: text; user-select: text; white-space: pre!important; } .ace_text-input.ace_composition { background: inherit; color: inherit; z-index: 1000; opacity: 1; text-indent: 0; } .ace_layer { z-index: 1; position: absolute; overflow: hidden; word-wrap: normal; white-space: pre; height: 100%; width: 100%; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; pointer-events: none; } .ace_gutter-layer { position: relative; width: auto; text-align: right; pointer-events: auto; } .ace_text-layer { font: inherit !important; } .ace_cjk { display: inline-block; text-align: center; } .ace_cursor-layer { z-index: 4; } .ace_cursor { z-index: 4; position: absolute; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; border-left: 2px solid; transform: translatez(0); } .ace_slim-cursors .ace_cursor { border-left-width: 1px; } .ace_overwrite-cursors .ace_cursor { border-left-width: 0; border-bottom: 1px solid; } .ace_hidden-cursors .ace_cursor { opacity: 0.2; } .ace_smooth-blinking .ace_cursor { -webkit-transition: opacity 0.18s; transition: opacity 0.18s; } .ace_editor.ace_multiselect .ace_cursor { border-left-width: 1px; } .ace_marker-layer .ace_step, .ace_marker-layer .ace_stack { position: absolute; z-index: 3; } .ace_marker-layer .ace_selection { position: absolute; z-index: 5; } .ace_marker-layer .ace_bracket { position: absolute; z-index: 6; } .ace_marker-layer .ace_active-line { position: absolute; z-index: 2; } .ace_marker-layer .ace_selected-word { position: absolute; z-index: 4; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } .ace_line .ace_fold { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; display: inline-block; height: 11px; margin-top: -2px; vertical-align: middle; background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="), url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII="); background-repeat: no-repeat, repeat-x; background-position: center center, top left; color: transparent; border: 1px solid black; border-radius: 2px; cursor: pointer; pointer-events: auto; } .ace_dark .ace_fold { } .ace_fold:hover{ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="), url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC"); } .ace_tooltip { background-color: #FFF; background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1)); background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1)); border: 1px solid gray; border-radius: 1px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); color: black; max-width: 100%; padding: 3px 4px; position: fixed; z-index: 999999; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; cursor: default; white-space: pre; word-wrap: break-word; line-height: normal; font-style: normal; font-weight: normal; letter-spacing: normal; pointer-events: none; } .ace_folding-enabled > .ace_gutter-cell { padding-right: 13px; } .ace_fold-widget { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; margin: 0 -12px 0 1px; display: none; width: 11px; vertical-align: top; background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg=="); background-repeat: no-repeat; background-position: center; border-radius: 3px; border: 1px solid transparent; cursor: pointer; } .ace_folding-enabled .ace_fold-widget { display: inline-block; } .ace_fold-widget.ace_end { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg=="); } .ace_fold-widget.ace_closed { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA=="); } .ace_fold-widget:hover { border: 1px solid rgba(0, 0, 0, 0.3); background-color: rgba(255, 255, 255, 0.2); box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7); } .ace_fold-widget:active { border: 1px solid rgba(0, 0, 0, 0.4); background-color: rgba(0, 0, 0, 0.05); box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8); } .ace_dark .ace_fold-widget { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC"); } .ace_dark .ace_fold-widget.ace_end { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg=="); } .ace_dark .ace_fold-widget.ace_closed { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg=="); } .ace_dark .ace_fold-widget:hover { box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2); background-color: rgba(255, 255, 255, 0.1); } .ace_dark .ace_fold-widget:active { box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2); } .ace_fold-widget.ace_invalid { background-color: #FFB4B4; border-color: #DE5555; } .ace_fade-fold-widgets .ace_fold-widget { -webkit-transition: opacity 0.4s ease 0.05s; transition: opacity 0.4s ease 0.05s; opacity: 0; } .ace_fade-fold-widgets:hover .ace_fold-widget { -webkit-transition: opacity 0.05s ease 0.05s; transition: opacity 0.05s ease 0.05s; opacity:1; } .ace_underline { text-decoration: underline; } .ace_bold { font-weight: bold; } .ace_nobold .ace_bold { font-weight: normal; } .ace_italic { font-style: italic; } .ace_error-marker { background-color: rgba(255, 0, 0,0.2); position: absolute; z-index: 9; } .ace_highlight-marker { background-color: rgba(255, 255, 0,0.2); position: absolute; z-index: 8; } .ace_br1 {border-top-left-radius : 3px;} .ace_br2 {border-top-right-radius : 3px;} .ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;} .ace_br4 {border-bottom-right-radius: 3px;} .ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;} .ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;} .ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;} .ace_br8 {border-bottom-left-radius : 3px;} .ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;} .ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;} .ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;} .ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;} .ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;} .ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;} .ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;} '; -r.importCssString(m,"ace_editor.css");var v=function(e,t){var i=this;this.container=e||r.createElement("div"),this.$keepTextAreaAtCursor=!s.isOldIE,r.addCssClass(this.container,"ace_editor"),this.setTheme(t),this.$gutter=r.createElement("div"),this.$gutter.className="ace_gutter",this.container.appendChild(this.$gutter),this.scroller=r.createElement("div"),this.scroller.className="ace_scroller",this.container.appendChild(this.scroller),this.content=r.createElement("div"),this.content.className="ace_content",this.scroller.appendChild(this.content),this.$gutterLayer=new a(this.$gutter),this.$gutterLayer.on("changeGutterWidth",this.onGutterResize.bind(this)),this.$markerBack=new l(this.content);var n=this.$textLayer=new c(this.content);this.canvas=n.element,this.$markerFront=new l(this.content),this.$cursorLayer=new h(this.content),this.$horizScroll=!1,this.$vScroll=!1,this.scrollBar=this.scrollBarV=new u(this.container,this),this.scrollBarH=new d(this.container,this),this.scrollBarV.addEventListener("scroll",function(e){i.$scrollAnimation||i.session.setScrollTop(e.data-i.scrollMargin.top)}),this.scrollBarH.addEventListener("scroll",function(e){i.$scrollAnimation||i.session.setScrollLeft(e.data-i.scrollMargin.left)}),this.scrollTop=0,this.scrollLeft=0,this.cursorPos={row:0,column:0},this.$fontMetrics=new p(this.container,500),this.$textLayer.$setFontMetrics(this.$fontMetrics),this.$textLayer.addEventListener("changeCharacterSize",function(e){i.updateCharacterSize(),i.onResize(!0,i.gutterWidth,i.$size.width,i.$size.height),i._signal("changeCharacterSize",e)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0,$dirty:!0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:0,characterWidth:0,minHeight:1,maxHeight:1,offset:0,height:1,gutterOffset:1},this.scrollMargin={left:0,right:0,top:0,bottom:0,v:0,h:0},this.$loop=new f(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.updateCharacterSize(),this.setPadding(4),o.resetOptions(this),o._emit("renderer",this)};(function(){this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,this.CHANGE_H_SCROLL=1024,n.implement(this,g),this.updateCharacterSize=function(){this.$textLayer.allowBoldFonts!=this.$allowBoldFonts&&(this.$allowBoldFonts=this.$textLayer.allowBoldFonts,this.setStyle("ace_nobold",!this.$allowBoldFonts)),this.layerConfig.characterWidth=this.characterWidth=this.$textLayer.getCharacterWidth(),this.layerConfig.lineHeight=this.lineHeight=this.$textLayer.getLineHeight(),this.$updatePrintMargin()},this.setSession=function(e){this.session&&this.session.doc.off("changeNewLineMode",this.onChangeNewLineMode),this.session=e,e&&this.scrollMargin.top&&e.getScrollTop()<=0&&e.setScrollTop(-this.scrollMargin.top),this.$cursorLayer.setSession(e),this.$markerBack.setSession(e),this.$markerFront.setSession(e),this.$gutterLayer.setSession(e),this.$textLayer.setSession(e),e&&(this.$loop.schedule(this.CHANGE_FULL),this.session.$setFontMetrics(this.$fontMetrics),this.onChangeNewLineMode=this.onChangeNewLineMode.bind(this),this.onChangeNewLineMode(),this.session.doc.on("changeNewLineMode",this.onChangeNewLineMode))},this.updateLines=function(e,t,i){if(void 0===t&&(t=1/0),this.$changedLines?(this.$changedLines.firstRow>e&&(this.$changedLines.firstRow=e),this.$changedLines.lastRowthis.layerConfig.lastRow||this.$loop.schedule(this.CHANGE_LINES)},this.onChangeNewLineMode=function(){this.$loop.schedule(this.CHANGE_TEXT),this.$textLayer.$updateEolChar()},this.onChangeTabSize=function(){this.$loop.schedule(this.CHANGE_TEXT|this.CHANGE_MARKER),this.$textLayer.onChangeTabSize()},this.updateText=function(){this.$loop.schedule(this.CHANGE_TEXT)},this.updateFull=function(e){e?this.$renderChanges(this.CHANGE_FULL,!0):this.$loop.schedule(this.CHANGE_FULL)},this.updateFontSize=function(){this.$textLayer.checkForSizeChanges()},this.$changes=0,this.$updateSizeAsync=function(){this.$loop.pending?this.$size.$dirty=!0:this.onResize()},this.onResize=function(e,t,i,n){if(!(this.resizing>2)){this.resizing>0?this.resizing++:this.resizing=e?1:0;var r=this.container;n||(n=r.clientHeight||r.scrollHeight),i||(i=r.clientWidth||r.scrollWidth);var o=this.$updateCachedSize(e,t,i,n);if(!this.$size.scrollerHeight||!i&&!n)return this.resizing=0;e&&(this.$gutterLayer.$padding=null),e?this.$renderChanges(o|this.$changes,!0):this.$loop.schedule(o|this.$changes),this.resizing&&(this.resizing=0),this.scrollBarV.scrollLeft=this.scrollBarV.scrollTop=null}},this.$updateCachedSize=function(e,t,i,n){n-=this.$extraHeight||0;var r=0,o=this.$size,s={width:o.width,height:o.height,scrollerHeight:o.scrollerHeight,scrollerWidth:o.scrollerWidth};return n&&(e||o.height!=n)&&(o.height=n,r|=this.CHANGE_SIZE,o.scrollerHeight=o.height,this.$horizScroll&&(o.scrollerHeight-=this.scrollBarH.getHeight()),this.scrollBarV.element.style.bottom=this.scrollBarH.getHeight()+"px",r|=this.CHANGE_SCROLL),i&&(e||o.width!=i)&&(r|=this.CHANGE_SIZE,o.width=i,null==t&&(t=this.$showGutter?this.$gutter.offsetWidth:0),this.gutterWidth=t,this.scrollBarH.element.style.left=this.scroller.style.left=t+"px",o.scrollerWidth=Math.max(0,i-t-this.scrollBarV.getWidth()),this.scrollBarH.element.style.right=this.scroller.style.right=this.scrollBarV.getWidth()+"px",this.scroller.style.bottom=this.scrollBarH.getHeight()+"px",(this.session&&this.session.getUseWrapMode()&&this.adjustWrapLimit()||e)&&(r|=this.CHANGE_FULL)),o.$dirty=!i||!n,r&&this._signal("resize",s),r},this.onGutterResize=function(){var e=this.$showGutter?this.$gutter.offsetWidth:0;e!=this.gutterWidth&&(this.$changes|=this.$updateCachedSize(!0,e,this.$size.width,this.$size.height)),this.session.getUseWrapMode()&&this.adjustWrapLimit()?this.$loop.schedule(this.CHANGE_FULL):this.$size.$dirty?this.$loop.schedule(this.CHANGE_FULL):(this.$computeLayerConfig(),this.$loop.schedule(this.CHANGE_MARKER))},this.adjustWrapLimit=function(){var e=this.$size.scrollerWidth-2*this.$padding,t=Math.floor(e/this.characterWidth);return this.session.adjustWrapLimit(t,this.$showPrintMargin&&this.$printMarginColumn)},this.setAnimatedScroll=function(e){this.setOption("animatedScroll",e)},this.getAnimatedScroll=function(){return this.$animatedScroll},this.setShowInvisibles=function(e){this.setOption("showInvisibles",e)},this.getShowInvisibles=function(){return this.getOption("showInvisibles")},this.getDisplayIndentGuides=function(){return this.getOption("displayIndentGuides")},this.setDisplayIndentGuides=function(e){this.setOption("displayIndentGuides",e)},this.setShowPrintMargin=function(e){this.setOption("showPrintMargin",e)},this.getShowPrintMargin=function(){return this.getOption("showPrintMargin")},this.setPrintMarginColumn=function(e){this.setOption("printMarginColumn",e)},this.getPrintMarginColumn=function(){return this.getOption("printMarginColumn")},this.getShowGutter=function(){return this.getOption("showGutter")},this.setShowGutter=function(e){return this.setOption("showGutter",e)},this.getFadeFoldWidgets=function(){return this.getOption("fadeFoldWidgets")},this.setFadeFoldWidgets=function(e){this.setOption("fadeFoldWidgets",e)},this.setHighlightGutterLine=function(e){this.setOption("highlightGutterLine",e)},this.getHighlightGutterLine=function(){return this.getOption("highlightGutterLine")},this.$updateGutterLineHighlight=function(){var e=this.$cursorLayer.$pixelPos,t=this.layerConfig.lineHeight;if(this.session.getUseWrapMode()){var i=this.session.selection.getCursor();i.column=0,e=this.$cursorLayer.getPixelPosition(i,!0),t*=this.session.getRowLength(i.row)}this.$gutterLineHighlight.style.top=e.top-this.layerConfig.offset+"px",this.$gutterLineHighlight.style.height=t+"px"},this.$updatePrintMargin=function(){if(this.$showPrintMargin||this.$printMarginEl){if(!this.$printMarginEl){var e=r.createElement("div");e.className="ace_layer ace_print-margin-layer",this.$printMarginEl=r.createElement("div"),this.$printMarginEl.className="ace_print-margin",e.appendChild(this.$printMarginEl),this.content.insertBefore(e,this.content.firstChild)}var t=this.$printMarginEl.style;t.left=this.characterWidth*this.$printMarginColumn+this.$padding+"px",t.visibility=this.$showPrintMargin?"visible":"hidden",this.session&&-1==this.session.$wrap&&this.adjustWrapLimit()}},this.getContainerElement=function(){return this.container},this.getMouseEventTarget=function(){return this.scroller},this.getTextAreaContainer=function(){return this.container},this.$moveTextAreaToCursor=function(){if(this.$keepTextAreaAtCursor){var e=this.layerConfig,t=this.$cursorLayer.$pixelPos.top,i=this.$cursorLayer.$pixelPos.left;t-=e.offset;var n=this.textarea.style,r=this.lineHeight;if(0>t||t>e.height-r)return void(n.top=n.left="0");var o=this.characterWidth;if(this.$composition){var s=this.textarea.value.replace(/^\x01+/,"");o*=this.session.$getStringScreenWidth(s)[0]+2,r+=2}i-=this.scrollLeft,i>this.$size.scrollerWidth-o&&(i=this.$size.scrollerWidth-o),i+=this.gutterWidth,n.height=r+"px",n.width=o+"px",n.left=Math.min(i,this.$size.scrollerWidth-o)+"px",n.top=Math.min(t,this.$size.height-r)+"px"}},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(0===this.layerConfig.offset?0:1)},this.getLastFullyVisibleRow=function(){var e=Math.floor((this.layerConfig.height+this.layerConfig.offset)/this.layerConfig.lineHeight);return this.layerConfig.firstRow-1+e},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(e){this.$padding=e,this.$textLayer.setPadding(e),this.$cursorLayer.setPadding(e),this.$markerFront.setPadding(e),this.$markerBack.setPadding(e),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.setScrollMargin=function(e,t,i,n){var r=this.scrollMargin;r.top=0|e,r.bottom=0|t,r.right=0|n,r.left=0|i,r.v=r.top+r.bottom,r.h=r.left+r.right,r.top&&this.scrollTop<=0&&this.session&&this.session.setScrollTop(-r.top),this.updateFull()},this.getHScrollBarAlwaysVisible=function(){return this.$hScrollBarAlwaysVisible},this.setHScrollBarAlwaysVisible=function(e){this.setOption("hScrollBarAlwaysVisible",e)},this.getVScrollBarAlwaysVisible=function(){return this.$vScrollBarAlwaysVisible},this.setVScrollBarAlwaysVisible=function(e){this.setOption("vScrollBarAlwaysVisible",e)},this.$updateScrollBarV=function(){var e=this.layerConfig.maxHeight,t=this.$size.scrollerHeight;!this.$maxLines&&this.$scrollPastEnd&&(e-=(t-this.lineHeight)*this.$scrollPastEnd,this.scrollTop>e-t&&(e=this.scrollTop+t,this.scrollBarV.scrollTop=null)),this.scrollBarV.setScrollHeight(e+this.scrollMargin.v),this.scrollBarV.setScrollTop(this.scrollTop+this.scrollMargin.top)},this.$updateScrollBarH=function(){this.scrollBarH.setScrollWidth(this.layerConfig.width+2*this.$padding+this.scrollMargin.h),this.scrollBarH.setScrollLeft(this.scrollLeft+this.scrollMargin.left)},this.$frozen=!1,this.freeze=function(){this.$frozen=!0},this.unfreeze=function(){this.$frozen=!1},this.$renderChanges=function(e,t){if(this.$changes&&(e|=this.$changes,this.$changes=0),!this.session||!this.container.offsetWidth||this.$frozen||!e&&!t)return void(this.$changes|=e);if(this.$size.$dirty)return this.$changes|=e,this.onResize(!0);this.lineHeight||this.$textLayer.checkForSizeChanges(),this._signal("beforeRender");var i=this.layerConfig;if(e&this.CHANGE_FULL||e&this.CHANGE_SIZE||e&this.CHANGE_TEXT||e&this.CHANGE_LINES||e&this.CHANGE_SCROLL||e&this.CHANGE_H_SCROLL){if(e|=this.$computeLayerConfig(),i.firstRow!=this.layerConfig.firstRow&&i.firstRowScreen==this.layerConfig.firstRowScreen){var n=this.scrollTop+(i.firstRow-this.layerConfig.firstRow)*this.lineHeight;n>0&&(this.scrollTop=n,e|=this.CHANGE_SCROLL,e|=this.$computeLayerConfig())}i=this.layerConfig,this.$updateScrollBarV(),e&this.CHANGE_H_SCROLL&&this.$updateScrollBarH(),this.$gutterLayer.element.style.marginTop=-i.offset+"px",this.content.style.marginTop=-i.offset+"px",this.content.style.width=i.width+2*this.$padding+"px",this.content.style.height=i.minHeight+"px"}return e&this.CHANGE_H_SCROLL&&(this.content.style.marginLeft=-this.scrollLeft+"px",this.scroller.className=this.scrollLeft<=0?"ace_scroller":"ace_scroller ace_scroll-left"),e&this.CHANGE_FULL?(this.$textLayer.update(i),this.$showGutter&&this.$gutterLayer.update(i),this.$markerBack.update(i),this.$markerFront.update(i),this.$cursorLayer.update(i),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight(),void this._signal("afterRender")):e&this.CHANGE_SCROLL?(e&this.CHANGE_TEXT||e&this.CHANGE_LINES?this.$textLayer.update(i):this.$textLayer.scrollLines(i),this.$showGutter&&this.$gutterLayer.update(i),this.$markerBack.update(i),this.$markerFront.update(i),this.$cursorLayer.update(i),this.$highlightGutterLine&&this.$updateGutterLineHighlight(),this.$moveTextAreaToCursor(),void this._signal("afterRender")):(e&this.CHANGE_TEXT?(this.$textLayer.update(i),this.$showGutter&&this.$gutterLayer.update(i)):e&this.CHANGE_LINES?(this.$updateLines()||e&this.CHANGE_GUTTER&&this.$showGutter)&&this.$gutterLayer.update(i):(e&this.CHANGE_TEXT||e&this.CHANGE_GUTTER)&&this.$showGutter&&this.$gutterLayer.update(i),e&this.CHANGE_CURSOR&&(this.$cursorLayer.update(i),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight()),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(i),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(i),void this._signal("afterRender"))},this.$autosize=function(){var e=this.session.getScreenLength()*this.lineHeight,t=this.$maxLines*this.lineHeight,i=Math.max((this.$minLines||1)*this.lineHeight,Math.min(t,e))+this.scrollMargin.v+(this.$extraHeight||0);this.$horizScroll&&(i+=this.scrollBarH.getHeight());var n=e>t;if(i!=this.desiredHeight||this.$size.height!=this.desiredHeight||n!=this.$vScroll){n!=this.$vScroll&&(this.$vScroll=n,this.scrollBarV.setVisible(n));var r=this.container.clientWidth;this.container.style.height=i+"px",this.$updateCachedSize(!0,this.$gutterWidth,r,i),this.desiredHeight=i,this._signal("autosize")}},this.$computeLayerConfig=function(){var e=this.session,t=this.$size,i=t.height<=2*this.lineHeight,n=this.session.getScreenLength(),r=n*this.lineHeight,o=this.$getLongestLine(),s=!i&&(this.$hScrollBarAlwaysVisible||t.scrollerWidth-o-2*this.$padding<0),a=this.$horizScroll!==s;a&&(this.$horizScroll=s,this.scrollBarH.setVisible(s));var l=this.$vScroll;this.$maxLines&&this.lineHeight>1&&this.$autosize();var c=this.scrollTop%this.lineHeight,h=t.scrollerHeight+this.lineHeight,d=!this.$maxLines&&this.$scrollPastEnd?(t.scrollerHeight-this.lineHeight)*this.$scrollPastEnd:0;r+=d;var u=this.scrollMargin;this.session.setScrollTop(Math.max(-u.top,Math.min(this.scrollTop,r-t.scrollerHeight+u.bottom))),this.session.setScrollLeft(Math.max(-u.left,Math.min(this.scrollLeft,o+2*this.$padding-t.scrollerWidth+u.right)));var f=!i&&(this.$vScrollBarAlwaysVisible||t.scrollerHeight-r+d<0||this.scrollTop>u.top),p=l!==f;p&&(this.$vScroll=f,this.scrollBarV.setVisible(f));var g,m,v=Math.ceil(h/this.lineHeight)-1,w=Math.max(0,Math.round((this.scrollTop-c)/this.lineHeight)),A=w+v,y=this.lineHeight;w=e.screenToDocumentRow(w,0);var C=e.getFoldLine(w);C&&(w=C.start.row),g=e.documentToScreenRow(w,0),m=e.getRowLength(w)*y,A=Math.min(e.screenToDocumentRow(A,0),e.getLength()-1),h=t.scrollerHeight+e.getRowLength(A)*y+m,c=this.scrollTop-g*y;var E=0;return this.layerConfig.width!=o&&(E=this.CHANGE_H_SCROLL),(a||p)&&(E=this.$updateCachedSize(!0,this.gutterWidth,t.width,t.height),this._signal("scrollbarVisibilityChanged"),p&&(o=this.$getLongestLine())),this.layerConfig={width:o,padding:this.$padding,firstRow:w,firstRowScreen:g,lastRow:A,lineHeight:y,characterWidth:this.characterWidth,minHeight:h,maxHeight:r,offset:c,gutterOffset:Math.max(0,Math.ceil((c+t.height-t.scrollerHeight)/y)),height:this.$size.scrollerHeight},E},this.$updateLines=function(){var e=this.$changedLines.firstRow,t=this.$changedLines.lastRow;this.$changedLines=null;var i=this.layerConfig;return e>i.lastRow+1||to?(t&&(o-=t*this.$size.scrollerHeight),0===o&&(o=-this.scrollMargin.top),this.session.setScrollTop(o)):l+this.$size.scrollerHeight-ar?(ri;++i)r.push(o(i/this.STEPS,e,t-e));return r},this.scrollToLine=function(e,t,i,n){var r=this.$cursorLayer.getPixelPosition({row:e,column:0}),o=r.top;t&&(o-=this.$size.scrollerHeight/2);var s=this.scrollTop;this.session.setScrollTop(o),i!==!1&&this.animateScrolling(s,n)},this.animateScrolling=function(e,t){var i=this.scrollTop;if(this.$animatedScroll){var n=this;if(e!=i){if(this.$scrollAnimation){var r=this.$scrollAnimation.steps;if(r.length&&(e=r[0],e==i))return}var o=n.$calcSteps(e,i);this.$scrollAnimation={from:e,to:i,steps:o},clearInterval(this.$timer),n.session.setScrollTop(o.shift()),n.session.$scrollTop=i,this.$timer=setInterval(function(){o.length?(n.session.setScrollTop(o.shift()),n.session.$scrollTop=i):null!=i?(n.session.$scrollTop=-1,n.session.setScrollTop(i),i=null):(n.$timer=clearInterval(n.$timer),n.$scrollAnimation=null,t&&t())},10)}}},this.scrollToY=function(e){this.scrollTop!==e&&(this.$loop.schedule(this.CHANGE_SCROLL),this.scrollTop=e)},this.scrollToX=function(e){this.scrollLeft!==e&&(this.scrollLeft=e),this.$loop.schedule(this.CHANGE_H_SCROLL)},this.scrollTo=function(e,t){this.session.setScrollTop(t),this.session.setScrollLeft(t)},this.scrollBy=function(e,t){t&&this.session.setScrollTop(this.session.getScrollTop()+t),e&&this.session.setScrollLeft(this.session.getScrollLeft()+e)},this.isScrollableBy=function(e,t){return 0>t&&this.session.getScrollTop()>=1-this.scrollMargin.top?!0:t>0&&this.session.getScrollTop()+this.$size.scrollerHeight-this.layerConfig.maxHeight<-1+this.scrollMargin.bottom?!0:0>e&&this.session.getScrollLeft()>=1-this.scrollMargin.left?!0:e>0&&this.session.getScrollLeft()+this.$size.scrollerWidth-this.layerConfig.width<-1+this.scrollMargin.right?!0:void 0},this.pixelToScreenCoordinates=function(e,t){var i=this.scroller.getBoundingClientRect(),n=(e+this.scrollLeft-i.left-this.$padding)/this.characterWidth,r=Math.floor((t+this.scrollTop-i.top)/this.lineHeight),o=Math.round(n);return{row:r,column:o,side:n-o>0?1:-1}},this.screenToTextCoordinates=function(e,t){var i=this.scroller.getBoundingClientRect(),n=Math.round((e+this.scrollLeft-i.left-this.$padding)/this.characterWidth),r=(t+this.scrollTop-i.top)/this.lineHeight;return this.session.screenToDocumentPosition(r,Math.max(n,0))},this.textToScreenCoordinates=function(e,t){var i=this.scroller.getBoundingClientRect(),n=this.session.documentToScreenPosition(e,t),r=this.$padding+Math.round(n.column*this.characterWidth),o=n.row*this.lineHeight;return{pageX:i.left+r-this.scrollLeft,pageY:i.top+o-this.scrollTop}},this.visualizeFocus=function(){r.addCssClass(this.container,"ace_focus")},this.visualizeBlur=function(){r.removeCssClass(this.container,"ace_focus")},this.showComposition=function(e){this.$composition||(this.$composition={keepTextAreaAtCursor:this.$keepTextAreaAtCursor,cssText:this.textarea.style.cssText}),this.$keepTextAreaAtCursor=!0,r.addCssClass(this.textarea,"ace_composition"),this.textarea.style.cssText="",this.$moveTextAreaToCursor()},this.setCompositionText=function(e){this.$moveTextAreaToCursor()},this.hideComposition=function(){this.$composition&&(r.removeCssClass(this.textarea,"ace_composition"),this.$keepTextAreaAtCursor=this.$composition.keepTextAreaAtCursor,this.textarea.style.cssText=this.$composition.cssText,this.$composition=null)},this.setTheme=function(e,t){function i(i){if(n.$themeId!=e)return t&&t();if(i.cssClass){r.importCssString(i.cssText,i.cssClass,n.container.ownerDocument),n.theme&&r.removeCssClass(n.container,n.theme.cssClass);var o="padding"in i?i.padding:"padding"in(n.theme||{})?4:n.$padding;n.$padding&&o!=n.$padding&&n.setPadding(o),n.$theme=i.cssClass,n.theme=i,r.addCssClass(n.container,i.cssClass),r.setCssClass(n.container,"ace_dark",i.isDark),n.$size&&(n.$size.width=0,n.$updateSizeAsync()),n._dispatchEvent("themeLoaded",{theme:i}),t&&t()}}var n=this;if(this.$themeId=e,n._dispatchEvent("themeChange",{theme:e}),e&&"string"!=typeof e)i(e);else{var s=e||this.$options.theme.initialValue;o.loadModule(["theme",s],i)}},this.getTheme=function(){return this.$themeId},this.setStyle=function(e,t){r.setCssClass(this.container,e,t!==!1)},this.unsetStyle=function(e){r.removeCssClass(this.container,e)},this.setCursorStyle=function(e){this.scroller.style.cursor!=e&&(this.scroller.style.cursor=e)},this.setMouseCursor=function(e){this.scroller.style.cursor=e},this.destroy=function(){this.$textLayer.destroy(),this.$cursorLayer.destroy()}}).call(v.prototype),o.defineOptions(v.prototype,"renderer",{animatedScroll:{initialValue:!1},showInvisibles:{set:function(e){this.$textLayer.setShowInvisibles(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!1},showPrintMargin:{set:function(){this.$updatePrintMargin()},initialValue:!0},printMarginColumn:{set:function(){this.$updatePrintMargin()},initialValue:80},printMargin:{set:function(e){"number"==typeof e&&(this.$printMarginColumn=e),this.$showPrintMargin=!!e,this.$updatePrintMargin()},get:function(){return this.$showPrintMargin&&this.$printMarginColumn}},showGutter:{set:function(e){this.$gutter.style.display=e?"block":"none",this.$loop.schedule(this.CHANGE_FULL),this.onGutterResize()},initialValue:!0},fadeFoldWidgets:{set:function(e){r.setCssClass(this.$gutter,"ace_fade-fold-widgets",e)},initialValue:!1},showFoldWidgets:{set:function(e){this.$gutterLayer.setShowFoldWidgets(e)},initialValue:!0},showLineNumbers:{set:function(e){this.$gutterLayer.setShowLineNumbers(e),this.$loop.schedule(this.CHANGE_GUTTER)},initialValue:!0},displayIndentGuides:{set:function(e){this.$textLayer.setDisplayIndentGuides(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!0},highlightGutterLine:{set:function(e){return this.$gutterLineHighlight?(this.$gutterLineHighlight.style.display=e?"":"none",void(this.$cursorLayer.$pixelPos&&this.$updateGutterLineHighlight())):(this.$gutterLineHighlight=r.createElement("div"),this.$gutterLineHighlight.className="ace_gutter-active-line",void this.$gutter.appendChild(this.$gutterLineHighlight))},initialValue:!1,value:!0},hScrollBarAlwaysVisible:{set:function(e){this.$hScrollBarAlwaysVisible&&this.$horizScroll||this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},vScrollBarAlwaysVisible:{set:function(e){this.$vScrollBarAlwaysVisible&&this.$vScroll||this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},fontSize:{set:function(e){"number"==typeof e&&(e+="px"),this.container.style.fontSize=e,this.updateFontSize()},initialValue:12},fontFamily:{set:function(e){this.container.style.fontFamily=e,this.updateFontSize()}},maxLines:{set:function(e){this.updateFull()}},minLines:{set:function(e){this.updateFull()}},scrollPastEnd:{set:function(e){e=+e||0,this.$scrollPastEnd!=e&&(this.$scrollPastEnd=e,this.$loop.schedule(this.CHANGE_SCROLL))},initialValue:0,handlesSet:!0},fixedWidthGutter:{set:function(e){this.$gutterLayer.$fixedWidth=!!e,this.$loop.schedule(this.CHANGE_GUTTER)}},theme:{set:function(e){this.setTheme(e)},get:function(){return this.$themeId||this.theme},initialValue:"./theme/textmate",handlesSet:!0}}),t.VirtualRenderer=v}),ace.define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/net","ace/lib/event_emitter","ace/config"],function(e,t,n){"use strict";var r=e("../lib/oop"),o=e("../lib/net"),s=e("../lib/event_emitter").EventEmitter,a=e("../config"),l=function(t,n,r,o){if(this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.onMessage=this.onMessage.bind(this),e.nameToUrl&&!e.toUrl&&(e.toUrl=e.nameToUrl),a.get("packaged")||!e.toUrl)o=o||a.moduleUrl(n.id,"worker");else{var s=this.$normalizePath;o=o||s(e.toUrl("ace/worker/worker.js",null,"_"));var l={};t.forEach(function(t){l[t]=s(e.toUrl(t,null,"_").replace(/(\.js)?(\?.*)?$/,""))})}try{var c=n.src,h=i(59),d=new h([c],{type:"application/javascript"}),u=(window.URL||window.webkitURL).createObjectURL(d);this.$worker=new Worker(u)}catch(f){if(!(f instanceof window.DOMException))throw f;var d=this.$workerBlob(o),p=window.URL||window.webkitURL,g=p.createObjectURL(d);this.$worker=new Worker(g),p.revokeObjectURL(g)}this.$worker.postMessage({init:!0,tlns:l,module:n.id,classname:r}),this.callbackId=1,this.callbacks={},this.$worker.onmessage=this.onMessage};(function(){r.implement(this,s),this.onMessage=function(e){var t=e.data;switch(t.type){case"event":this._signal(t.name,{data:t.data});break;case"call":var i=this.callbacks[t.id];i&&(i(t.data),delete this.callbacks[t.id]);break;case"error":this.reportError(t.data);break;case"log":window.console&&console.log&&console.log.apply(console,t.data)}},this.reportError=function(e){window.console&&console.error&&console.error(e)},this.$normalizePath=function(e){return o.qualifyURL(e)},this.terminate=function(){this._signal("terminate",{}),this.deltaQueue=null,this.$worker.terminate(),this.$worker=null,this.$doc&&this.$doc.off("change",this.changeListener),this.$doc=null},this.send=function(e,t){this.$worker.postMessage({command:e,args:t})},this.call=function(e,t,i){if(i){var n=this.callbackId++;this.callbacks[n]=i,t.push(n)}this.send(e,t)},this.emit=function(e,t){try{this.$worker.postMessage({event:e,data:{data:t.data}})}catch(i){console.error(i.stack)}},this.attachToDocument=function(e){this.$doc&&this.terminate(),this.$doc=e,this.call("setValue",[e.getValue()]),e.on("change",this.changeListener)},this.changeListener=function(e){this.deltaQueue||(this.deltaQueue=[],setTimeout(this.$sendDeltaQueue,0)),"insert"==e.action?this.deltaQueue.push(e.start,e.lines):this.deltaQueue.push(e.start,e.end)},this.$sendDeltaQueue=function(){var e=this.deltaQueue;e&&(this.deltaQueue=null,e.length>50&&e.length>this.$doc.getLength()>>1?this.call("setValue",[this.$doc.getValue()]):this.emit("change",{data:e}))},this.$workerBlob=function(e){var t="importScripts('"+o.qualifyURL(e)+"');";try{return new Blob([t],{type:"application/javascript"})}catch(i){var n=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder,r=new n;return r.append(t),r.getBlob("application/javascript")}}}).call(l.prototype);var c=function(e,t,i){this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.callbackId=1,this.callbacks={},this.messageBuffer=[];var n=null,r=!1,o=Object.create(s),l=this;this.$worker={},this.$worker.terminate=function(){},this.$worker.postMessage=function(e){l.messageBuffer.push(e),n&&(r?setTimeout(c):c())},this.setEmitSync=function(e){r=e};var c=function(){var e=l.messageBuffer.shift();e.command?n[e.command].apply(n,e.args):e.event&&o._signal(e.event,e.data)};o.postMessage=function(e){l.onMessage({data:e})},o.callback=function(e,t){this.postMessage({type:"call",id:t,data:e})},o.emit=function(e,t){this.postMessage({type:"event",name:e,data:t})},a.loadModule(["worker",t],function(e){for(n=new e[i](o);l.messageBuffer.length;)c()})};c.prototype=l.prototype,t.UIWorkerClient=c,t.WorkerClient=l}),ace.define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"],function(e,t,i){"use strict";var n=e("./range").Range,r=e("./lib/event_emitter").EventEmitter,o=e("./lib/oop"),s=function(e,t,i,n,r,o){var s=this;this.length=t,this.session=e,this.doc=e.getDocument(),this.mainClass=r,this.othersClass=o,this.$onUpdate=this.onUpdate.bind(this),this.doc.on("change",this.$onUpdate),this.$others=n,this.$onCursorChange=function(){setTimeout(function(){s.onCursorChange()})},this.$pos=i;var a=e.getUndoManager().$undoStack||e.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=a.length,this.setup(),e.selection.on("changeCursor",this.$onCursorChange)};(function(){o.implement(this,r),this.setup=function(){var e=this,t=this.doc,i=this.session;this.selectionBefore=i.selection.toJSON(),i.selection.inMultiSelectMode&&i.selection.toSingleRange(),this.pos=t.createAnchor(this.$pos.row,this.$pos.column);var r=this.pos;r.$insertRight=!0,r.detach(),r.markerId=i.addMarker(new n(r.row,r.column,r.row,r.column+this.length),this.mainClass,null,!1),this.others=[],this.$others.forEach(function(i){var n=t.createAnchor(i.row,i.column);n.$insertRight=!0,n.detach(),e.others.push(n)}),i.setUndoSelect(!1)},this.showOtherMarkers=function(){if(!this.othersActive){var e=this.session,t=this;this.othersActive=!0,this.others.forEach(function(i){i.markerId=e.addMarker(new n(i.row,i.column,i.row,i.column+t.length),t.othersClass,null,!1)})}},this.hideOtherMarkers=function(){if(this.othersActive){this.othersActive=!1;for(var e=0;e=this.pos.column&&t.start.column<=this.pos.column+this.length+1,o=t.start.column-this.pos.column;if(this.updateAnchors(e),r&&(this.length+=i),r&&!this.session.$fromUndo)if("insert"===e.action)for(var s=this.others.length-1;s>=0;s--){var a=this.others[s],l={row:a.row,column:a.column+o};this.doc.insertMergedLines(l,e.lines)}else if("remove"===e.action)for(var s=this.others.length-1;s>=0;s--){var a=this.others[s],l={row:a.row,column:a.column+o};this.doc.remove(new n(l.row,l.column,l.row,l.column-i))}this.$updating=!1,this.updateMarkers()}},this.updateAnchors=function(e){this.pos.onChange(e);for(var t=this.others.length;t--;)this.others[t].onChange(e);this.updateMarkers()},this.updateMarkers=function(){if(!this.$updating){var e=this,t=this.session,i=function(i,r){t.removeMarker(i.markerId),i.markerId=t.addMarker(new n(i.row,i.column,i.row,i.column+e.length),r,null,!1)};i(this.pos,this.mainClass);for(var r=this.others.length;r--;)i(this.others[r],this.othersClass)}},this.onCursorChange=function(e){if(!this.$updating&&this.session){var t=this.session.selection.getCursor();t.row===this.pos.row&&t.column>=this.pos.column&&t.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit("cursorEnter",e)):(this.hideOtherMarkers(),this._emit("cursorLeave",e))}},this.detach=function(){this.session.removeMarker(this.pos&&this.pos.markerId),this.hideOtherMarkers(),this.doc.removeEventListener("change",this.$onUpdate),this.session.selection.removeEventListener("changeCursor",this.$onCursorChange),this.session.setUndoSelect(!0),this.session=null},this.cancel=function(){if(-1!==this.$undoStackDepth){for(var e=this.session.getUndoManager(),t=(e.$undoStack||e.$undostack).length-this.$undoStackDepth,i=0;t>i;i++)e.undo(!0);this.selectionBefore&&this.session.selection.fromJSON(this.selectionBefore)}}}).call(s.prototype),t.PlaceHolder=s}),ace.define("ace/mouse/multi_select_handler",["require","exports","module","ace/lib/event","ace/lib/useragent"],function(e,t,i){function n(e,t){return e.row==t.row&&e.column==t.column}function r(e){var t=e.domEvent,i=t.altKey,r=t.shiftKey,a=t.ctrlKey,l=e.getAccelKey(),c=e.getButton();if(a&&s.isMac&&(c=t.button),e.editor.inMultiSelectMode&&2==c)return void e.editor.textInput.onContextMenu(e.domEvent);if(!a&&!i&&!l)return void(0===c&&e.editor.inMultiSelectMode&&e.editor.exitMultiSelectMode());if(0===c){var h,d=e.editor,u=d.selection,f=d.inMultiSelectMode,p=e.getDocumentPosition(),g=u.getCursor(),m=e.inSelection()||u.isEmpty()&&n(p,g),v=e.x,w=e.y,A=function(e){v=e.clientX,w=e.clientY},y=d.session,C=d.renderer.pixelToScreenCoordinates(v,w),E=C;if(d.$mouseHandler.$enableJumpToDef)a&&i||l&&i?h=r?"block":"add":i&&d.$blockSelectEnabled&&(h="block");else if(l&&!i){if(h="add",!f&&r)return}else i&&d.$blockSelectEnabled&&(h="block");if(h&&s.isMac&&t.ctrlKey&&d.$mouseHandler.cancelContextMenu(),"add"==h){if(!f&&m)return;if(!f){var b=u.toOrientedRange();d.addSelectionMarker(b)}var F=u.rangeList.rangeAtPoint(p);d.$blockScrolling++,d.inVirtualSelectionMode=!0,r&&(F=null,b=u.ranges[0]||b,d.removeSelectionMarker(b)),d.once("mouseup",function(){var e=u.toOrientedRange();F&&e.isEmpty()&&n(F.cursor,e.cursor)?u.substractPoint(e.cursor):(r?u.substractPoint(b.cursor):b&&(d.removeSelectionMarker(b),u.addRange(b)),u.addRange(e)),d.$blockScrolling--,d.inVirtualSelectionMode=!1})}else if("block"==h){e.stop(),d.inVirtualSelectionMode=!0;var x,S=[],$=function(){var e=d.renderer.pixelToScreenCoordinates(v,w),t=y.screenToDocumentPosition(e.row,e.column);n(E,e)&&n(t,u.lead)||(E=e,d.$blockScrolling++,d.selection.moveToPosition(t),d.renderer.scrollCursorIntoView(),d.removeSelectionMarkers(S),S=u.rectangularRangeBlock(E,C),d.$mouseHandler.$clickSelection&&1==S.length&&S[0].isEmpty()&&(S[0]=d.$mouseHandler.$clickSelection.clone()),S.forEach(d.addSelectionMarker,d),d.updateSelectionMarkers(),d.$blockScrolling--)};d.$blockScrolling++,f&&!l?u.toSingleRange():!f&&l&&(x=u.toOrientedRange(),d.addSelectionMarker(x)),r?C=y.documentToScreenPosition(u.lead):u.moveToPosition(p),d.$blockScrolling--,E={row:-1,column:-1};var D=function(e){clearInterval(B),d.removeSelectionMarkers(S),S.length||(S=[u.toOrientedRange()]),d.$blockScrolling++,x&&(d.removeSelectionMarker(x),u.toSingleRange(x));for(var t=0;t1&&!this.inMultiSelectMode&&(this._signal("multiSelect"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session)),t||this.fromOrientedRange(e)}},this.toSingleRange=function(e){e=e||this.ranges[0];var t=this.rangeList.removeAll();t.length&&this.$onRemoveRange(t),e&&this.fromOrientedRange(e)},this.substractPoint=function(e){var t=this.rangeList.substractPoint(e);return t?(this.$onRemoveRange(t),t[0]):void 0},this.mergeOverlappingRanges=function(){var e=this.rangeList.merge();e.length?this.$onRemoveRange(e):this.ranges[0]&&this.fromOrientedRange(this.ranges[0])},this.$onAddRange=function(e){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(e),this._signal("addRange",{range:e})},this.$onRemoveRange=function(e){if(this.rangeCount=this.rangeList.ranges.length,1==this.rangeCount&&this.inMultiSelectMode){var t=this.rangeList.ranges.pop();e.push(t),this.rangeCount=0}for(var i=e.length;i--;){var n=this.ranges.indexOf(e[i]);this.ranges.splice(n,1)}this._signal("removeRange",{ranges:e}),0===this.rangeCount&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._signal("singleSelect"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),t=t||this.ranges[0],t&&!t.isEqual(this.getRange())&&this.fromOrientedRange(t)},this.$initRangeList=function(){this.rangeList||(this.rangeList=new a,this.ranges=[],this.rangeCount=0)},this.getAllRanges=function(){return this.rangeCount?this.rangeList.ranges.concat():[this.getRange()]},this.splitIntoLines=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],i=l.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(i,t.cursor==t.start)}else{var i=this.getRange(),n=this.isBackwards(),r=i.start.row,o=i.end.row;if(r==o){if(n)var s=i.end,a=i.start;else var s=i.start,a=i.end;return this.addRange(l.fromPoints(a,a)),void this.addRange(l.fromPoints(s,s))}var c=[],h=this.getLineRange(r,!0);h.start.column=i.start.column,c.push(h);for(var d=r+1;o>d;d++)c.push(this.getLineRange(d,!0));h=this.getLineRange(o,!0),h.end.column=i.end.column,c.push(h),c.forEach(this.addRange,this)}},this.toggleBlockSelection=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],i=l.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(i,t.cursor==t.start)}else{var n=this.session.documentToScreenPosition(this.selectionLead),r=this.session.documentToScreenPosition(this.selectionAnchor),o=this.rectangularRangeBlock(n,r);o.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(e,t,i){var n=[],o=e.columns&&(s=0),0>h&&(h=0),h==d&&(i=!0);for(var u=h;d>=u;u++){var f=l.fromPoints(this.session.screenToDocumentPosition(u,s),this.session.screenToDocumentPosition(u,a));if(f.isEmpty()){if(p&&r(f.end,p))break;var p=f.end}f.cursor=o?f.start:f.end,n.push(f)}if(c&&n.reverse(),!i){for(var g=n.length-1;n[g].isEmpty()&&g>0;)g--;if(g>0)for(var m=0;n[m].isEmpty();)m++;for(var v=g;v>=m;v--)n[v].isEmpty()&&n.splice(v,1)}return n}}.call(c.prototype);var v=e("./editor").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(e){e.cursor||(e.cursor=e.end);var t=this.getSelectionStyle();return e.marker=this.session.addMarker(e,"ace_selection",t),this.session.$selectionMarkers.push(e),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,e},this.removeSelectionMarker=function(e){if(e.marker){this.session.removeMarker(e.marker);var t=this.session.$selectionMarkers.indexOf(e);-1!=t&&this.session.$selectionMarkers.splice(t,1),this.session.selectionMarkerCount=this.session.$selectionMarkers.length}},this.removeSelectionMarkers=function(e){for(var t=this.session.$selectionMarkers,i=e.length;i--;){var n=e[i];if(n.marker){this.session.removeMarker(n.marker);var r=t.indexOf(n);-1!=r&&t.splice(r,1)}}this.session.selectionMarkerCount=t.length},this.$onAddRange=function(e){this.addSelectionMarker(e.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(e){this.removeSelectionMarkers(e.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(e){this.inMultiSelectMode||(this.inMultiSelectMode=!0,this.setStyle("ace_multiselect"),this.keyBinding.addKeyboardHandler(f.keyboardHandler),this.commands.setDefaultHandler("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers())},this.$onSingleSelect=function(e){this.session.multiSelect.inVirtualMode||(this.inMultiSelectMode=!1,this.unsetStyle("ace_multiselect"),this.keyBinding.removeKeyboardHandler(f.keyboardHandler),this.commands.removeDefaultHandler("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers(),this._emit("changeSelection"))},this.$onMultiSelectExec=function(e){var t=e.command,i=e.editor;if(i.multiSelect){if(t.multiSelectAction)"forEach"==t.multiSelectAction?n=i.forEachSelection(t,e.args):"forEachLine"==t.multiSelectAction?n=i.forEachSelection(t,e.args,!0):"single"==t.multiSelectAction?(i.exitMultiSelectMode(),n=t.exec(i,e.args||{})):n=t.multiSelectAction(i,e.args||{});else{var n=t.exec(i,e.args||{});i.multiSelect.addRange(i.multiSelect.toOrientedRange()),i.multiSelect.mergeOverlappingRanges()}return n}},this.forEachSelection=function(e,t,i){if(!this.inVirtualSelectionMode){var n,r=i&&i.keepOrder,o=1==i||i&&i.$byLines,s=this.session,a=this.selection,l=a.rangeList,h=(r?a:l).ranges;if(!h.length)return e.exec?e.exec(this,t||{}):e(this,t||{});var d=a._eventRegistry;a._eventRegistry={};var u=new c(s);this.inVirtualSelectionMode=!0;for(var f=h.length;f--;){if(o)for(;f>0&&h[f].start.row==h[f-1].end.row;)f--;u.fromOrientedRange(h[f]),u.index=f,this.selection=s.selection=u;var p=e.exec?e.exec(this,t||{}):e(this,t||{});n||void 0===p||(n=p),u.toOrientedRange(h[f])}u.detach(),this.selection=s.selection=a,this.inVirtualSelectionMode=!1,a._eventRegistry=d,a.mergeOverlappingRanges();var g=this.renderer.$scrollAnimation;return this.onCursorChange(),this.onSelectionChange(),g&&g.from==g.to&&this.renderer.animateScrolling(g.from),n}},this.exitMultiSelectMode=function(){this.inMultiSelectMode&&!this.inVirtualSelectionMode&&this.multiSelect.toSingleRange()},this.getSelectedText=function(){var e="";if(this.inMultiSelectMode&&!this.inVirtualSelectionMode){for(var t=this.multiSelect.rangeList.ranges,i=[],n=0;ne?a.unshift(a.pop()):a.push(a.shift());for(var r=n.length;r--;){var o=n[r],s=o.clone();t.replace(o,a[r]),o.start.row=s.start.row,o.start.column=s.start.column}},this.selectMore=function(e,t,i){var r=this.session,o=r.multiSelect,s=o.toOrientedRange();if(!s.isEmpty()||(s=r.getWordRange(s.start.row,s.start.column),s.cursor=-1==e?s.start:s.end,this.multiSelect.addRange(s),!i)){var a=r.getTextRange(s),l=n(r,a,e);l&&(l.cursor=-1==e?l.start:l.end,this.$blockScrolling+=1,this.session.unfold(l),this.multiSelect.addRange(l),this.$blockScrolling-=1,this.renderer.scrollCursorIntoView(null,.5)),t&&this.multiSelect.substractPoint(s.cursor)}},this.alignCursors=function(){var e=this.session,t=e.multiSelect,i=t.ranges,n=-1,r=i.filter(function(e){return e.cursor.row==n?!0:void(n=e.cursor.row)});if(i.length&&r.length!=i.length-1){r.forEach(function(e){t.substractPoint(e.cursor)});var o=0,s=1/0,a=i.map(function(t){var i=t.cursor,n=e.getLine(i.row),r=n.substr(i.column).search(/\S/g);return-1==r&&(r=0),i.column>o&&(o=i.column),s>r&&(s=r),r});i.forEach(function(t,i){var n=t.cursor,r=o-n.column,c=a[i]-s;r>c?e.insert(n,u.stringRepeat(" ",r-c)):e.remove(new l(n.row,n.column,n.row,n.column-r+c)),t.start.column=t.end.column=o,t.start.row=t.end.row=n.row,t.cursor=t.end}),t.fromOrientedRange(i[0]),this.renderer.updateCursor(),this.renderer.updateBackMarkers()}else{var c=this.selection.getRange(),h=c.start.row,d=c.end.row,f=h==d;if(f){var p,g=this.session.getLength();do p=this.session.getLine(d);while(/[=:]/.test(p)&&++d0);0>h&&(h=0),d>=g&&(d=g-1)}var m=this.session.removeFullLines(h,d);m=this.$reAlignText(m,f),this.session.insert({row:h,column:0},m.join("\n")+"\n"),f||(c.start.column=0,c.end.column=m[m.length-1].length),this.selection.setRange(c)}},this.$reAlignText=function(e,t){function i(e){return u.stringRepeat(" ",e)}function n(e){return e[2]?i(s)+e[2]+i(a-e[2].length+l)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function r(e){return e[2]?i(s+a-e[2].length)+e[2]+i(l," ")+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function o(e){return e[2]?i(s)+e[2]+i(l)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}var s,a,l,c=!0,h=!0;return e.map(function(e){var t=e.match(/(\s*)(.*?)(\s*)([=:].*)/);return t?null==s?(s=t[1].length,a=t[2].length,l=t[3].length,t):(s+a+l!=t[1].length+t[2].length+t[3].length&&(h=!1),s!=t[1].length&&(c=!1),s>t[1].length&&(s=t[1].length),at[3].length&&(l=t[3].length),t):[e]}).map(t?n:c?h?r:n:o)}}).call(v.prototype),t.onSessionChange=function(e){var t=e.session;t&&!t.multiSelect&&(t.$selectionMarkers=[],t.selection.$initRangeList(),t.multiSelect=t.selection),this.multiSelect=t&&t.multiSelect;var i=e.oldSession;i&&(i.multiSelect.off("addRange",this.$onAddRange),i.multiSelect.off("removeRange",this.$onRemoveRange),i.multiSelect.off("multiSelect",this.$onMultiSelect),i.multiSelect.off("singleSelect",this.$onSingleSelect),i.multiSelect.lead.off("change",this.$checkMultiselectChange),i.multiSelect.anchor.off("change",this.$checkMultiselectChange)),t&&(t.multiSelect.on("addRange",this.$onAddRange),t.multiSelect.on("removeRange",this.$onRemoveRange),t.multiSelect.on("multiSelect",this.$onMultiSelect),t.multiSelect.on("singleSelect",this.$onSingleSelect),t.multiSelect.lead.on("change",this.$checkMultiselectChange),t.multiSelect.anchor.on("change",this.$checkMultiselectChange)),t&&this.inMultiSelectMode!=t.selection.inMultiSelectMode&&(t.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},t.MultiSelect=o,e("./config").defineOptions(v.prototype,"editor",{enableMultiselect:{set:function(e){o(this),e?(this.on("changeSession",this.$multiselectOnSessionChange),this.on("mousedown",h)):(this.off("changeSession",this.$multiselectOnSessionChange),this.off("mousedown",h))},value:!0},enableBlockSelect:{set:function(e){this.$blockSelectEnabled=e},value:!0}})}),ace.define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(e,t,i){"use strict";var n=e("../../range").Range,r=t.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(e,t,i){var n=e.getLine(i);return this.foldingStartMarker.test(n)?"start":"markbeginend"==t&&this.foldingStopMarker&&this.foldingStopMarker.test(n)?"end":""},this.getFoldWidgetRange=function(e,t,i){return null},this.indentationBlock=function(e,t,i){var r=/\S/,o=e.getLine(t),s=o.search(r);if(-1!=s){for(var a=i||o.length,l=e.getLength(),c=t,h=t;++t=d)break;h=t}}if(h>c){var u=e.getLine(h).length;return new n(c,a,h,u)}}},this.openingBracketBlock=function(e,t,i,r,o){var s={row:i,column:r+1},a=e.$findClosingBracket(t,s,o);if(a){var l=e.foldWidgets[a.row];return null==l&&(l=e.getFoldWidget(a.row)),"start"==l&&a.row>s.row&&(a.row--,a.column=e.getLine(a.row).length),n.fromPoints(s,a)}},this.closingBracketBlock=function(e,t,i,r,o){var s={row:i,column:r},a=e.$findOpeningBracket(t,s);return a?(a.column++,s.column--,n.fromPoints(a,s)):void 0}}).call(r.prototype)}),ace.define("ace/theme/textmate",["require","exports","module","ace/lib/dom"],function(e,t,i){"use strict";t.isDark=!1,t.cssClass="ace-tm",t.cssText='.ace-tm .ace_gutter { background: #f0f0f0; color: #333; } .ace-tm .ace_print-margin { width: 1px; background: #e8e8e8; } .ace-tm .ace_fold { background-color: #6B72E6; } .ace-tm { background-color: #FFFFFF; color: black; } .ace-tm .ace_cursor { color: black; } .ace-tm .ace_invisible { color: rgb(191, 191, 191); } .ace-tm .ace_storage, .ace-tm .ace_keyword { color: blue; } .ace-tm .ace_constant { color: rgb(197, 6, 11); } .ace-tm .ace_constant.ace_buildin { color: rgb(88, 72, 246); } .ace-tm .ace_constant.ace_language { color: rgb(88, 92, 246); } .ace-tm .ace_constant.ace_library { color: rgb(6, 150, 14); } .ace-tm .ace_invalid { background-color: rgba(255, 0, 0, 0.1); color: red; } .ace-tm .ace_support.ace_function { color: rgb(60, 76, 114); } .ace-tm .ace_support.ace_constant { color: rgb(6, 150, 14); } .ace-tm .ace_support.ace_type, .ace-tm .ace_support.ace_class { color: rgb(109, 121, 222); } .ace-tm .ace_keyword.ace_operator { color: rgb(104, 118, 135); } .ace-tm .ace_string { color: rgb(3, 106, 7); } .ace-tm .ace_comment { color: rgb(76, 136, 107); } .ace-tm .ace_comment.ace_doc { color: rgb(0, 102, 255); } .ace-tm .ace_comment.ace_doc.ace_tag { color: rgb(128, 159, 191); } .ace-tm .ace_constant.ace_numeric { color: rgb(0, 0, 205); } .ace-tm .ace_variable { color: rgb(49, 132, 149); } .ace-tm .ace_xml-pe { color: rgb(104, 104, 91); } .ace-tm .ace_entity.ace_name.ace_function { color: #0000A2; } .ace-tm .ace_heading { color: rgb(12, 7, 255); } .ace-tm .ace_list { color:rgb(185, 6, 144); } .ace-tm .ace_meta.ace_tag { color:rgb(0, 22, 142); } .ace-tm .ace_string.ace_regex { color: rgb(255, 0, 0) } .ace-tm .ace_marker-layer .ace_selection { background: rgb(181, 213, 255); } .ace-tm.ace_multiselect .ace_selection.ace_start { box-shadow: 0 0 3px 0px white; } .ace-tm .ace_marker-layer .ace_step { background: rgb(252, 255, 0); } .ace-tm .ace_marker-layer .ace_stack { background: rgb(164, 229, 101); } .ace-tm .ace_marker-layer .ace_bracket { margin: -1px 0 0 -1px; border: 1px solid rgb(192, 192, 192); } .ace-tm .ace_marker-layer .ace_active-line { background: rgba(0, 0, 0, 0.07); } .ace-tm .ace_gutter-active-line { background-color : #dcdcdc; } .ace-tm .ace_marker-layer .ace_selected-word { background: rgb(250, 250, 255); border: 1px solid rgb(200, 200, 250); } .ace-tm .ace_indent-guide { background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y; } ';var n=e("../lib/dom");n.importCssString(t.cssText,t.cssClass)}),ace.define("ace/line_widgets",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/range"],function(e,t,i){"use strict";function n(e){this.session=e,this.session.widgetManager=this,this.session.getRowLength=this.getRowLength,this.session.$getWidgetScreenLength=this.$getWidgetScreenLength,this.updateOnChange=this.updateOnChange.bind(this),this.renderWidgets=this.renderWidgets.bind(this),this.measureWidgets=this.measureWidgets.bind(this),this.session._changedWidgets=[],this.$onChangeEditor=this.$onChangeEditor.bind(this),this.session.on("change",this.updateOnChange),this.session.on("changeFold",this.updateOnFold),this.session.on("changeEditor",this.$onChangeEditor)}var r=(e("./lib/oop"),e("./lib/dom"));e("./range").Range;(function(){this.getRowLength=function(e){var t;return t=this.lineWidgets?this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0:0,this.$useWrapMode&&this.$wrapData[e]?this.$wrapData[e].length+1+t:1+t},this.$getWidgetScreenLength=function(){var e=0;return this.lineWidgets.forEach(function(t){t&&t.rowCount&&!t.hidden&&(e+=t.rowCount)}),e},this.$onChangeEditor=function(e){this.attach(e.editor)},this.attach=function(e){e&&e.widgetManager&&e.widgetManager!=this&&e.widgetManager.detach(),this.editor!=e&&(this.detach(),this.editor=e,e&&(e.widgetManager=this,e.renderer.on("beforeRender",this.measureWidgets),e.renderer.on("afterRender",this.renderWidgets)))},this.detach=function(e){var t=this.editor;if(t){this.editor=null,t.widgetManager=null,t.renderer.off("beforeRender",this.measureWidgets),t.renderer.off("afterRender",this.renderWidgets);var i=this.session.lineWidgets;i&&i.forEach(function(e){e&&e.el&&e.el.parentNode&&(e._inDocument=!1,e.el.parentNode.removeChild(e.el))})}},this.updateOnFold=function(e,t){var i=t.lineWidgets;if(i&&e.action){for(var n=e.data,r=n.start.row,o=n.end.row,s="add"==e.action,a=r+1;o>a;a++)i[a]&&(i[a].hidden=s);i[o]&&(s?i[r]?i[o].hidden=s:i[r]=i[o]:(i[r]==i[o]&&(i[r]=void 0),i[o].hidden=s))}},this.updateOnChange=function(e){var t=this.session.lineWidgets;if(t){var i=e.start.row,n=e.end.row-i;if(0===n);else if("remove"==e.action){var r=t.splice(i+1,n);r.forEach(function(e){e&&this.removeLineWidget(e)},this),this.$updateRows()}else{var o=new Array(n);o.unshift(i,0),t.splice.apply(t,o),this.$updateRows()}}},this.$updateRows=function(){var e=this.session.lineWidgets;if(e){var t=!0;e.forEach(function(e,i){if(e)for(t=!1,e.row=i;e.$oldWidget;)e.$oldWidget.row=i,e=e.$oldWidget}),t&&(this.session.lineWidgets=null)}},this.addLineWidget=function(e){this.session.lineWidgets||(this.session.lineWidgets=new Array(this.session.getLength()));var t=this.session.lineWidgets[e.row];t&&(e.$oldWidget=t,t.el&&t.el.parentNode&&(t.el.parentNode.removeChild(t.el),t._inDocument=!1)),this.session.lineWidgets[e.row]=e,e.session=this.session;var i=this.editor.renderer;e.html&&!e.el&&(e.el=r.createElement("div"),e.el.innerHTML=e.html),e.el&&(r.addCssClass(e.el,"ace_lineWidgetContainer"),e.el.style.position="absolute",e.el.style.zIndex=5,i.container.appendChild(e.el),e._inDocument=!0),e.coverGutter||(e.el.style.zIndex=3),e.pixelHeight||(e.pixelHeight=e.el.offsetHeight),null==e.rowCount&&(e.rowCount=e.pixelHeight/i.layerConfig.lineHeight);var n=this.session.getFoldAt(e.row,0);if(e.$fold=n,n){var o=this.session.lineWidgets;e.row!=n.end.row||o[n.start.row]?e.hidden=!0:o[n.start.row]=e}return this.session._emit("changeFold",{data:{start:{row:e.row}}}),this.$updateRows(),this.renderWidgets(null,i),this.onWidgetChanged(e),e},this.removeLineWidget=function(e){if(e._inDocument=!1,e.session=null,e.el&&e.el.parentNode&&e.el.parentNode.removeChild(e.el),e.editor&&e.editor.destroy)try{e.editor.destroy()}catch(t){}if(this.session.lineWidgets){var i=this.session.lineWidgets[e.row];if(i==e)this.session.lineWidgets[e.row]=e.$oldWidget,e.$oldWidget&&this.onWidgetChanged(e.$oldWidget);else for(;i;){if(i.$oldWidget==e){i.$oldWidget=e.$oldWidget;break}i=i.$oldWidget}}this.session._emit("changeFold",{data:{start:{row:e.row}}}),this.$updateRows()},this.getWidgetsAtRow=function(e){for(var t=this.session.lineWidgets,i=t&&t[e],n=[];i;)n.push(i),i=i.$oldWidget;return n},this.onWidgetChanged=function(e){this.session._changedWidgets.push(e),this.editor&&this.editor.renderer.updateFull()},this.measureWidgets=function(e,t){var i=this.session._changedWidgets,n=t.layerConfig;if(i&&i.length){for(var r=1/0,o=0;oa&&(a=0)),s.rowCount!=a&&(s.rowCount=a,s.row0&&!n[r];)r--;this.firstRow=i.firstRow,this.lastRow=i.lastRow,t.$cursorLayer.config=i;for(var s=r;o>=s;s++){var a=n[s];if(a&&a.el)if(a.hidden)a.el.style.top=-100-(a.pixelHeight||0)+"px";else{a._inDocument||(a._inDocument=!0,t.container.appendChild(a.el));var l=t.$cursorLayer.getPixelPosition({row:s,column:0},!0).top;a.coverLine||(l+=i.lineHeight*this.session.getRowLineCount(a.row)),a.el.style.top=l-i.offset+"px";var c=a.coverGutter?0:t.gutterWidth;a.fixedWidth||(c-=t.scrollLeft),a.el.style.left=c+"px",a.fullWidth&&a.screenWidth&&(a.el.style.minWidth=i.width+2*i.padding+"px"),a.fixedWidth?a.el.style.right=t.scrollBar.getWidth()+"px":a.el.style.right=""}}}}}).call(n.prototype),t.LineWidgets=n}),ace.define("ace/ext/error_marker",["require","exports","module","ace/line_widgets","ace/lib/dom","ace/range"],function(e,t,i){"use strict";function n(e,t,i){for(var n=0,r=e.length-1;r>=n;){var o=n+r>>1,s=i(t,e[o]);if(s>0)n=o+1;else{if(!(0>s))return o;r=o-1}}return-(n+1)}function r(e,t,i){var r=e.getAnnotations().sort(a.comparePoints);if(r.length){var o=n(r,{row:t,column:-1},a.comparePoints);0>o&&(o=-o-1),o>=r.length?o=i>0?0:r.length-1:0===o&&0>i&&(o=r.length-1);var s=r[o];if(s&&i){if(s.row===t){do s=r[o+=i];while(s&&s.row===t);if(!s)return r.slice()}var l=[];t=s.row;do l[0>i?"unshift":"push"](s),s=r[o+=i];while(s&&s.row==t);return l.length&&l}}}var o=e("../line_widgets").LineWidgets,s=e("../lib/dom"),a=e("../range").Range; -t.showErrorMarker=function(e,t){var i=e.session;i.widgetManager||(i.widgetManager=new o(i),i.widgetManager.attach(e));var n=e.getCursorPosition(),a=n.row,l=i.widgetManager.getWidgetsAtRow(a).filter(function(e){return"errorMarker"==e.type})[0];l?l.destroy():a-=t;var c,h=r(i,a,t);if(h){var d=h[0];n.column=(d.pos&&"number"!=typeof d.column?d.pos.sc:d.column)||0,n.row=d.row,c=e.renderer.$gutterLayer.$annotations[n.row]}else{if(l)return;c={text:["Looks good!"],className:"ace_ok"}}e.session.unfold(n.row),e.selection.moveToPosition(n);var u={row:n.row,fixedWidth:!0,coverGutter:!0,el:s.createElement("div"),type:"errorMarker"},f=u.el.appendChild(s.createElement("div")),p=u.el.appendChild(s.createElement("div"));p.className="error_widget_arrow "+c.className;var g=e.renderer.$cursorLayer.getPixelPosition(n).left;p.style.left=g+e.renderer.gutterWidth-5+"px",u.el.className="error_widget_wrapper",f.className="error_widget "+c.className,f.innerHTML=c.text.join("
"),f.appendChild(s.createElement("div"));var m=function(e,t,i){return 0!==t||"esc"!==i&&"return"!==i?void 0:(u.destroy(),{command:"null"})};u.destroy=function(){e.$mouseHandler.isMousePressed||(e.keyBinding.removeKeyboardHandler(m),i.widgetManager.removeLineWidget(u),e.off("changeSelection",u.destroy),e.off("changeSession",u.destroy),e.off("mouseup",u.destroy),e.off("change",u.destroy))},e.keyBinding.addKeyboardHandler(m),e.on("changeSelection",u.destroy),e.on("changeSession",u.destroy),e.on("mouseup",u.destroy),e.on("change",u.destroy),e.session.widgetManager.addLineWidget(u),u.el.onmousedown=e.focus.bind(e),e.renderer.scrollCursorIntoView(null,.5,{bottom:u.el.offsetHeight})},s.importCssString(" .error_widget_wrapper { background: inherit; color: inherit; border:none } .error_widget { border-top: solid 2px; border-bottom: solid 2px; margin: 5px 0; padding: 10px 40px; white-space: pre-wrap; } .error_widget.ace_error, .error_widget_arrow.ace_error{ border-color: #ff5a5a } .error_widget.ace_warning, .error_widget_arrow.ace_warning{ border-color: #F1D817 } .error_widget.ace_info, .error_widget_arrow.ace_info{ border-color: #5a5a5a } .error_widget.ace_ok, .error_widget_arrow.ace_ok{ border-color: #5aaa5a } .error_widget_arrow { position: absolute; border: solid 5px; border-top-color: transparent!important; border-right-color: transparent!important; border-left-color: transparent!important; top: -5px; } ","")}),ace.define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"],function(e,t,i){"use strict";e("./lib/fixoldbrowsers");var n=e("./lib/dom"),r=e("./lib/event"),o=e("./editor").Editor,s=e("./edit_session").EditSession,a=e("./undomanager").UndoManager,l=e("./virtual_renderer").VirtualRenderer;e("./worker/worker_client"),e("./keyboard/hash_handler"),e("./placeholder"),e("./multi_select"),e("./mode/folding/fold_mode"),e("./theme/textmate"),e("./ext/error_marker"),t.config=e("./config"),t.acequire=e,t.edit=function(e){if("string"==typeof e){var i=e;if(e=document.getElementById(i),!e)throw new Error("ace.edit can't find div #"+i)}if(e&&e.env&&e.env.editor instanceof o)return e.env.editor;var s="";if(e&&/input|textarea/i.test(e.tagName)){var a=e;s=a.value,e=n.createElement("pre"),a.parentNode.replaceChild(e,a)}else e&&(s=n.getInnerText(e),e.innerHTML="");var c=t.createEditSession(s),h=new o(new l(e));h.setSession(c);var d={document:c,editor:h,onResize:h.resize.bind(h,null)};return a&&(d.textarea=a),r.addListener(window,"resize",d.onResize),h.on("destroy",function(){r.removeListener(window,"resize",d.onResize),d.editor.container.env=null}),h.container.env=h.env=d,h},t.createEditSession=function(e,t){var i=new s(e,t);return i.setUndoManager(new a),i},t.EditSession=s,t.UndoManager=a,t.version="1.2.2"}),function(){ace.acequire(["ace/ace"],function(e){e&&e.config.init(!0),window.ace||(window.ace=e);for(var t in e)e.hasOwnProperty(t)&&(window.ace[t]=e[t])})}(),e.exports=window.ace.acequire("ace/ace")},function(e,t,i){ace.define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,i){"use strict";var n=e("../lib/oop"),r=e("./text_highlight_rules").TextHighlightRules,o=function(){this.$rules={start:[{token:"variable",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)'},{token:"string",regex:'"',next:"string"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"invalid.illegal",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"invalid.illegal",regex:"\\/\\/.*$"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],string:[{token:"constant.language.escape",regex:/\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"},{token:"string",regex:"",next:"start"}]}};n.inherits(o,r),t.JsonHighlightRules=o}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,i){"use strict";var n=e("../range").Range,r=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var i=e.getLine(t),r=i.match(/^(\s*\})/);if(!r)return 0;var o=r[1].length,s=e.findMatchingBracket({row:t,column:o});if(!s||s.row==t)return 0;var a=this.$getIndent(e.getLine(s.row));e.replace(new n(t,0,t,o-1),a)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(r.prototype),t.MatchingBraceOutdent=r}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,i){"use strict";var n,r=e("../../lib/oop"),o=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,a=e("../../lib/lang"),l=["text","paren.rparen","punctuation.operator"],c=["text","paren.rparen","punctuation.operator","comment"],h={},d=function(e){var t=-1;return e.multiSelect&&(t=e.selection.index,h.rangeCount!=e.multiSelect.rangeCount&&(h={rangeCount:e.multiSelect.rangeCount})),h[t]?n=h[t]:void(n=h[t]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:"",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:"",maybeInsertedLineEnd:""})},u=function(e,t,i,n){var r=e.end.row-e.start.row;return{text:i+t+n,selection:[0,e.start.column+1,r,e.end.column+(r?0:1)]}},f=function(){this.add("braces","insertion",function(e,t,i,r,o){var s=i.getCursorPosition(),l=r.doc.getLine(s.row);if("{"==o){d(i);var c=i.getSelectionRange(),h=r.doc.getTextRange(c);if(""!==h&&"{"!==h&&i.getWrapBehavioursEnabled())return u(c,h,"{","}");if(f.isSaneInsertion(i,r))return/[\]\}\)]/.test(l[s.column])||i.inMultiSelectMode?(f.recordAutoInsert(i,r,"}"),{text:"{}",selection:[1,1]}):(f.recordMaybeInsert(i,r,"{"),{text:"{",selection:[1,1]})}else if("}"==o){d(i);var p=l.substring(s.column,s.column+1);if("}"==p){var g=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(null!==g&&f.isAutoInsertedClosing(s,l,o))return f.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else{if("\n"==o||"\r\n"==o){d(i);var m="";f.isMaybeInsertedClosing(s,l)&&(m=a.stringRepeat("}",n.maybeInsertedBrackets),f.clearMaybeInsertedClosing());var p=l.substring(s.column,s.column+1);if("}"===p){var v=r.findMatchingBracket({row:s.row,column:s.column+1},"}");if(!v)return null;var w=this.$getIndent(r.getLine(v.row))}else{if(!m)return void f.clearMaybeInsertedClosing();var w=this.$getIndent(l)}var A=w+r.getTabString();return{text:"\n"+A+"\n"+w+m,selection:[1,A.length,1,A.length]}}f.clearMaybeInsertedClosing()}}),this.add("braces","deletion",function(e,t,i,r,o){var s=r.doc.getTextRange(o);if(!o.isMultiLine()&&"{"==s){d(i);var a=r.doc.getLine(o.start.row),l=a.substring(o.end.column,o.end.column+1);if("}"==l)return o.end.column++,o;n.maybeInsertedBrackets--}}),this.add("parens","insertion",function(e,t,i,n,r){if("("==r){d(i);var o=i.getSelectionRange(),s=n.doc.getTextRange(o);if(""!==s&&i.getWrapBehavioursEnabled())return u(o,s,"(",")");if(f.isSaneInsertion(i,n))return f.recordAutoInsert(i,n,")"),{text:"()",selection:[1,1]}}else if(")"==r){d(i);var a=i.getCursorPosition(),l=n.doc.getLine(a.row),c=l.substring(a.column,a.column+1);if(")"==c){var h=n.$findOpeningBracket(")",{column:a.column+1,row:a.row});if(null!==h&&f.isAutoInsertedClosing(a,l,r))return f.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,i,n,r){var o=n.doc.getTextRange(r);if(!r.isMultiLine()&&"("==o){d(i);var s=n.doc.getLine(r.start.row),a=s.substring(r.start.column+1,r.start.column+2);if(")"==a)return r.end.column++,r}}),this.add("brackets","insertion",function(e,t,i,n,r){if("["==r){d(i);var o=i.getSelectionRange(),s=n.doc.getTextRange(o);if(""!==s&&i.getWrapBehavioursEnabled())return u(o,s,"[","]");if(f.isSaneInsertion(i,n))return f.recordAutoInsert(i,n,"]"),{text:"[]",selection:[1,1]}}else if("]"==r){d(i);var a=i.getCursorPosition(),l=n.doc.getLine(a.row),c=l.substring(a.column,a.column+1);if("]"==c){var h=n.$findOpeningBracket("]",{column:a.column+1,row:a.row});if(null!==h&&f.isAutoInsertedClosing(a,l,r))return f.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,i,n,r){var o=n.doc.getTextRange(r);if(!r.isMultiLine()&&"["==o){d(i);var s=n.doc.getLine(r.start.row),a=s.substring(r.start.column+1,r.start.column+2);if("]"==a)return r.end.column++,r}}),this.add("string_dquotes","insertion",function(e,t,i,n,r){if('"'==r||"'"==r){d(i);var o=r,s=i.getSelectionRange(),a=n.doc.getTextRange(s);if(""!==a&&"'"!==a&&'"'!=a&&i.getWrapBehavioursEnabled())return u(s,a,o,o);if(!a){var l=i.getCursorPosition(),c=n.doc.getLine(l.row),h=c.substring(l.column-1,l.column),f=c.substring(l.column,l.column+1),p=n.getTokenAt(l.row,l.column),g=n.getTokenAt(l.row,l.column+1);if("\\"==h&&p&&/escape/.test(p.type))return null;var m,v=p&&/string|escape/.test(p.type),w=!g||/string|escape/.test(g.type);if(f==o)m=v!==w;else{if(v&&!w)return null;if(v&&w)return null;var A=n.$mode.tokenRe;A.lastIndex=0;var y=A.test(h);A.lastIndex=0;var C=A.test(h);if(y||C)return null;if(f&&!/[\s;,.})\]\\]/.test(f))return null;m=!0}return{text:m?o+o:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,i,n,r){var o=n.doc.getTextRange(r);if(!r.isMultiLine()&&('"'==o||"'"==o)){d(i);var s=n.doc.getLine(r.start.row),a=s.substring(r.start.column+1,r.start.column+2);if(a==o)return r.end.column++,r}})};f.isSaneInsertion=function(e,t){var i=e.getCursorPosition(),n=new s(t,i.row,i.column);if(!this.$matchTokenType(n.getCurrentToken()||"text",l)){var r=new s(t,i.row,i.column+1);if(!this.$matchTokenType(r.getCurrentToken()||"text",l))return!1}return n.stepForward(),n.getCurrentTokenRow()!==i.row||this.$matchTokenType(n.getCurrentToken()||"text",c)},f.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},f.recordAutoInsert=function(e,t,i){var r=e.getCursorPosition(),o=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,o,n.autoInsertedLineEnd[0])||(n.autoInsertedBrackets=0),n.autoInsertedRow=r.row,n.autoInsertedLineEnd=i+o.substr(r.column),n.autoInsertedBrackets++},f.recordMaybeInsert=function(e,t,i){var r=e.getCursorPosition(),o=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,o)||(n.maybeInsertedBrackets=0),n.maybeInsertedRow=r.row,n.maybeInsertedLineStart=o.substr(0,r.column)+i,n.maybeInsertedLineEnd=o.substr(r.column),n.maybeInsertedBrackets++},f.isAutoInsertedClosing=function(e,t,i){return n.autoInsertedBrackets>0&&e.row===n.autoInsertedRow&&i===n.autoInsertedLineEnd[0]&&t.substr(e.column)===n.autoInsertedLineEnd},f.isMaybeInsertedClosing=function(e,t){return n.maybeInsertedBrackets>0&&e.row===n.maybeInsertedRow&&t.substr(e.column)===n.maybeInsertedLineEnd&&t.substr(0,e.column)==n.maybeInsertedLineStart},f.popAutoInsertedClosing=function(){n.autoInsertedLineEnd=n.autoInsertedLineEnd.substr(1),n.autoInsertedBrackets--},f.clearMaybeInsertedClosing=function(){n&&(n.maybeInsertedBrackets=0,n.maybeInsertedRow=-1)},r.inherits(f,o),t.CstyleBehaviour=f}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,i){"use strict";var n=e("../../lib/oop"),r=e("../../range").Range,o=e("./fold_mode").FoldMode,s=t.FoldMode=function(e){e&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+e.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+e.end)))};n.inherits(s,o),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.singleLineBlockCommentRe=/^\s*(\/\*).*\*\/\s*$/,this.tripleStarBlockCommentRe=/^\s*(\/\*\*\*).*\*\/\s*$/,this.startRegionRe=/^\s*(\/\*|\/\/)#?region\b/,this._getFoldWidgetBase=this.getFoldWidget,this.getFoldWidget=function(e,t,i){var n=e.getLine(i);if(this.singleLineBlockCommentRe.test(n)&&!this.startRegionRe.test(n)&&!this.tripleStarBlockCommentRe.test(n))return"";var r=this._getFoldWidgetBase(e,t,i);return!r&&this.startRegionRe.test(n)?"start":r},this.getFoldWidgetRange=function(e,t,i,n){var r=e.getLine(i);if(this.startRegionRe.test(r))return this.getCommentRegionBlock(e,r,i);var o=r.match(this.foldingStartMarker);if(o){var s=o.index;if(o[1])return this.openingBracketBlock(e,o[1],i,s);var a=e.getCommentFoldRange(i,s+o[0].length,1);return a&&!a.isMultiLine()&&(n?a=this.getSectionRange(e,i):"all"!=t&&(a=null)),a}if("markbegin"!==t){var o=r.match(this.foldingStopMarker);if(o){var s=o.index+o[0].length;return o[1]?this.closingBracketBlock(e,o[1],i,s):e.getCommentFoldRange(i,s,-1)}}},this.getSectionRange=function(e,t){var i=e.getLine(t),n=i.search(/\S/),o=t,s=i.length;t+=1;for(var a=t,l=e.getLength();++tc)break;var h=this.getFoldWidgetRange(e,"all",t);if(h){if(h.start.row<=o)break;if(h.isMultiLine())t=h.end.row;else if(n==c)break}a=t}}return new r(o,s,a,e.getLine(a).length)},this.getCommentRegionBlock=function(e,t,i){for(var n=t.search(/\s*$/),o=e.getLength(),s=i,a=/^\s*(?:\/\*|\/\/|--)#?(end)?region\b/,l=1;++is?new r(s,n,h,t.length):void 0}}.call(s.prototype)}),ace.define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"],function(e,t,n){"use strict";var r=e("../lib/oop"),o=e("./text").Mode,s=e("./json_highlight_rules").JsonHighlightRules,a=e("./matching_brace_outdent").MatchingBraceOutdent,l=e("./behaviour/cstyle").CstyleBehaviour,c=e("./folding/cstyle").FoldMode,h=e("../worker/worker_client").WorkerClient,d=function(){this.HighlightRules=s,this.$outdent=new a,this.$behaviour=new l,this.foldingRules=new c};r.inherits(d,o),function(){this.getNextLineIndent=function(e,t,i){var n=this.$getIndent(t);if("start"==e){var r=t.match(/^.*[\{\(\[]\s*$/);r&&(n+=i)}return n},this.checkOutdent=function(e,t,i){return this.$outdent.checkOutdent(t,i)},this.autoOutdent=function(e,t,i){this.$outdent.autoOutdent(t,i)},this.createWorker=function(e){var t=new h(["ace"],i(38),"JsonWorker");return t.attachToDocument(e.getDocument()),t.on("annotate",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t},this.$id="ace/mode/json"}.call(d.prototype),t.Mode=d})},function(e,t,i){ace.define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"],function(e,t,i){"use strict";var n=e("../lib/dom"),r=e("../lib/lang"),o=e("../lib/event"),s=" .ace_search { background-color: #ddd; border: 1px solid #cbcbcb; border-top: 0 none; max-width: 325px; overflow: hidden; margin: 0; padding: 4px; padding-right: 6px; padding-bottom: 0; position: absolute; top: 0px; z-index: 99; white-space: normal; } .ace_search.left { border-left: 0 none; border-radius: 0px 0px 5px 0px; left: 0; } .ace_search.right { border-radius: 0px 0px 0px 5px; border-right: 0 none; right: 0; } .ace_search_form, .ace_replace_form { border-radius: 3px; border: 1px solid #cbcbcb; float: left; margin-bottom: 4px; overflow: hidden; } .ace_search_form.ace_nomatch { outline: 1px solid red; } .ace_search_field { background-color: white; border-right: 1px solid #cbcbcb; border: 0 none; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; float: left; height: 22px; outline: 0; padding: 0 7px; width: 214px; margin: 0; } .ace_searchbtn, .ace_replacebtn { background: #fff; border: 0 none; border-left: 1px solid #dcdcdc; cursor: pointer; float: left; height: 22px; margin: 0; position: relative; } .ace_searchbtn:last-child, .ace_replacebtn:last-child { border-top-right-radius: 3px; border-bottom-right-radius: 3px; } .ace_searchbtn:disabled { background: none; cursor: default; } .ace_searchbtn { background-position: 50% 50%; background-repeat: no-repeat; width: 27px; } .ace_searchbtn.prev { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); } .ace_searchbtn.next { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); } .ace_searchbtn_close { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0; border-radius: 50%; border: 0 none; color: #656565; cursor: pointer; float: right; font: 16px/16px Arial; height: 14px; margin: 5px 1px 9px 5px; padding: 0; text-align: center; width: 14px; } .ace_searchbtn_close:hover { background-color: #656565; background-position: 50% 100%; color: white; } .ace_replacebtn.prev { width: 54px } .ace_replacebtn.next { width: 27px } .ace_button { margin-left: 2px; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; -o-user-select: none; -ms-user-select: none; user-select: none; overflow: hidden; opacity: 0.7; border: 1px solid rgba(100,100,100,0.23); padding: 1px; -moz-box-sizing: border-box; box-sizing: border-box; color: black; } .ace_button:hover { background-color: #eee; opacity:1; } .ace_button:active { background-color: #ddd; } .ace_button.checked { border-color: #3399ff; opacity:1; } .ace_search_options{ margin-bottom: 3px; text-align: right; -webkit-user-select: none; -moz-user-select: none; -o-user-select: none; -ms-user-select: none; user-select: none; }",a=e("../keyboard/hash_handler").HashHandler,l=e("../lib/keys");n.importCssString(s,"ace_searchbox");var c=''.replace(/>\s+/g,">"),h=function(e,t,i){var r=n.createElement("div");r.innerHTML=c,this.element=r.firstChild,this.$init(),this.setEditor(e)};(function(){this.setEditor=function(e){e.searchBox=this,e.container.appendChild(this.element),this.editor=e},this.$initElements=function(e){this.searchBox=e.querySelector(".ace_search_form"),this.replaceBox=e.querySelector(".ace_replace_form"),this.searchOptions=e.querySelector(".ace_search_options"),this.regExpOption=e.querySelector("[action=toggleRegexpMode]"),this.caseSensitiveOption=e.querySelector("[action=toggleCaseSensitive]"),this.wholeWordOption=e.querySelector("[action=toggleWholeWords]"),this.searchInput=this.searchBox.querySelector(".ace_search_field"),this.replaceInput=this.replaceBox.querySelector(".ace_search_field")},this.$init=function(){var e=this.element;this.$initElements(e);var t=this;o.addListener(e,"mousedown",function(e){setTimeout(function(){t.activeInput.focus()},0),o.stopPropagation(e)}),o.addListener(e,"click",function(e){var i=e.target||e.srcElement,n=i.getAttribute("action");n&&t[n]?t[n]():t.$searchBarKb.commands[n]&&t.$searchBarKb.commands[n].exec(t),o.stopPropagation(e)}),o.addCommandKeyListener(e,function(e,i,n){var r=l.keyCodeToString(n),s=t.$searchBarKb.findKeyCommand(i,r);s&&s.exec&&(s.exec(t),o.stopEvent(e))}),this.$onChange=r.delayedCall(function(){t.find(!1,!1)}),o.addListener(this.searchInput,"input",function(){t.$onChange.schedule(20)}),o.addListener(this.searchInput,"focus",function(){t.activeInput=t.searchInput,t.searchInput.value&&t.highlight()}),o.addListener(this.replaceInput,"focus",function(){t.activeInput=t.replaceInput,t.searchInput.value&&t.highlight()})},this.$closeSearchBarKb=new a([{bindKey:"Esc",name:"closeSearchBar",exec:function(e){e.searchBox.hide()}}]),this.$searchBarKb=new a,this.$searchBarKb.bindKeys({"Ctrl-f|Command-f":function(e){var t=e.isReplace=!e.isReplace;e.replaceBox.style.display=t?"":"none",e.searchInput.focus()},"Ctrl-H|Command-Option-F":function(e){e.replaceBox.style.display="",e.replaceInput.focus()},"Ctrl-G|Command-G":function(e){e.findNext()},"Ctrl-Shift-G|Command-Shift-G":function(e){e.findPrev()},esc:function(e){setTimeout(function(){e.hide()})},Return:function(e){e.activeInput==e.replaceInput&&e.replace(),e.findNext()},"Shift-Return":function(e){e.activeInput==e.replaceInput&&e.replace(),e.findPrev()},"Alt-Return":function(e){e.activeInput==e.replaceInput&&e.replaceAll(),e.findAll()},Tab:function(e){(e.activeInput==e.replaceInput?e.searchInput:e.replaceInput).focus()}}),this.$searchBarKb.addCommands([{name:"toggleRegexpMode",bindKey:{win:"Alt-R|Alt-/",mac:"Ctrl-Alt-R|Ctrl-Alt-/"},exec:function(e){e.regExpOption.checked=!e.regExpOption.checked,e.$syncOptions()}},{name:"toggleCaseSensitive",bindKey:{win:"Alt-C|Alt-I",mac:"Ctrl-Alt-R|Ctrl-Alt-I"},exec:function(e){e.caseSensitiveOption.checked=!e.caseSensitiveOption.checked,e.$syncOptions()}},{name:"toggleWholeWords",bindKey:{win:"Alt-B|Alt-W",mac:"Ctrl-Alt-B|Ctrl-Alt-W"},exec:function(e){e.wholeWordOption.checked=!e.wholeWordOption.checked,e.$syncOptions()}}]),this.$syncOptions=function(){n.setCssClass(this.regExpOption,"checked",this.regExpOption.checked),n.setCssClass(this.wholeWordOption,"checked",this.wholeWordOption.checked),n.setCssClass(this.caseSensitiveOption,"checked",this.caseSensitiveOption.checked),this.find(!1,!1)},this.highlight=function(e){this.editor.session.highlight(e||this.editor.$search.$options.re),this.editor.renderer.updateBackMarkers()},this.find=function(e,t,i){var r=this.editor.find(this.searchInput.value,{skipCurrent:e,backwards:t,wrap:!0,regExp:this.regExpOption.checked,caseSensitive:this.caseSensitiveOption.checked,wholeWord:this.wholeWordOption.checked,preventScroll:i}),o=!r&&this.searchInput.value;n.setCssClass(this.searchBox,"ace_nomatch",o),this.editor._emit("findSearchBox",{match:!o}),this.highlight()},this.findNext=function(){this.find(!0,!1)},this.findPrev=function(){this.find(!0,!0)},this.findAll=function(){var e=this.editor.findAll(this.searchInput.value,{regExp:this.regExpOption.checked,caseSensitive:this.caseSensitiveOption.checked,wholeWord:this.wholeWordOption.checked}),t=!e&&this.searchInput.value;n.setCssClass(this.searchBox,"ace_nomatch",t),this.editor._emit("findSearchBox",{match:!t}),this.highlight(),this.hide()},this.replace=function(){this.editor.getReadOnly()||this.editor.replace(this.replaceInput.value)},this.replaceAndFindNext=function(){this.editor.getReadOnly()||(this.editor.replace(this.replaceInput.value),this.findNext())},this.replaceAll=function(){this.editor.getReadOnly()||this.editor.replaceAll(this.replaceInput.value)},this.hide=function(){this.element.style.display="none",this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb),this.editor.focus()},this.show=function(e,t){this.element.style.display="",this.replaceBox.style.display=t?"":"none",this.isReplace=t,e&&(this.searchInput.value=e),this.find(!1,!1,!0),this.searchInput.focus(),this.searchInput.select(),this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb)},this.isFocused=function(){var e=document.activeElement;return e==this.searchInput||e==this.replaceInput}}).call(h.prototype),t.SearchBox=h,t.Search=function(e,t){var i=e.searchBox||new h(e);i.show(e.session.getTextRange(),t)}}),function(){ace.acequire(["ace/ext/searchbox"],function(){})}()},function(e,t,i){e.exports={id:"http://json-schema.org/draft-04/schema#",$schema:"http://json-schema.org/draft-04/schema#",description:"Core schema meta-schema",definitions:{schemaArray:{type:"array",minItems:1,items:{$ref:"#"}},positiveInteger:{type:"integer",minimum:0},positiveIntegerDefault0:{allOf:[{$ref:"#/definitions/positiveInteger"},{"default":0}]},simpleTypes:{"enum":["array","boolean","integer","null","number","object","string"]},stringArray:{type:"array",items:{type:"string"},minItems:1,uniqueItems:!0}},type:"object",properties:{id:{type:"string",format:"uri"},$schema:{type:"string",format:"uri"},title:{type:"string"},description:{type:"string"},"default":{},multipleOf:{type:"number",minimum:0,exclusiveMinimum:!0},maximum:{type:"number"},exclusiveMaximum:{type:"boolean","default":!1},minimum:{type:"number"},exclusiveMinimum:{type:"boolean","default":!1},maxLength:{$ref:"#/definitions/positiveInteger"},minLength:{$ref:"#/definitions/positiveIntegerDefault0"},pattern:{type:"string",format:"regex"},additionalItems:{anyOf:[{type:"boolean"},{$ref:"#"}],"default":{}},items:{anyOf:[{$ref:"#"},{$ref:"#/definitions/schemaArray"}],"default":{}},maxItems:{$ref:"#/definitions/positiveInteger"},minItems:{$ref:"#/definitions/positiveIntegerDefault0"},uniqueItems:{type:"boolean","default":!1},maxProperties:{$ref:"#/definitions/positiveInteger"},minProperties:{$ref:"#/definitions/positiveIntegerDefault0"},required:{$ref:"#/definitions/stringArray"},additionalProperties:{anyOf:[{type:"boolean"},{$ref:"#"}],"default":{}},definitions:{type:"object",additionalProperties:{$ref:"#"},"default":{}},properties:{type:"object",additionalProperties:{$ref:"#"},"default":{}},patternProperties:{type:"object",additionalProperties:{$ref:"#"},"default":{}},dependencies:{type:"object",additionalProperties:{anyOf:[{$ref:"#"},{$ref:"#/definitions/stringArray"}]}},"enum":{type:"array",minItems:1,uniqueItems:!0},type:{anyOf:[{$ref:"#/definitions/simpleTypes"},{type:"array",items:{$ref:"#/definitions/simpleTypes"},minItems:1,uniqueItems:!0}]},allOf:{$ref:"#/definitions/schemaArray"},anyOf:{$ref:"#/definitions/schemaArray"},oneOf:{$ref:"#/definitions/schemaArray"},not:{$ref:"#"}},dependencies:{exclusiveMaximum:["maximum"],exclusiveMinimum:["minimum"]},"default":{}}},function(e,t,i){"use strict";e.exports=function n(e,t){if(e===t)return!0;var i,r=Array.isArray(e),o=Array.isArray(t);if(r&&o){if(e.length!=t.length)return!1;for(i=0;ir;)i++,t=e.charCodeAt(r++),t>=55296&&56319>=t&&n>r&&(t=e.charCodeAt(r),56320==(64512&t)&&r++);return i}function h(e,t){t+="[^0-9]";var i=e.match(new RegExp(t,"g"));return i?i.length:0}function d(e,t,i){return t+="([^0-9])",i=i.replace(/\$/g,"$$$$"),e.replace(new RegExp(t,"g"),i+"$1")}function u(e){return e.replace(S,"").replace($,"").replace(D,"if (!($1))")}function f(e){var t=e.match(k);return t&&2===t.length?e.replace(B,"").replace(_,L):e}function p(e,t){for(var i in e)if(t[i])return!0}function g(e){return"'"+l(e)+"'"}function m(e,t,i,n){var r=i?"'/' + "+t+(n?"":".replace(/~/g, '~0').replace(/\\//g, '~1')"):n?"'[' + "+t+" + ']'":"'[\\'' + "+t+" + '\\']'";return A(e,r)}function v(e,t,i){var n=g(i?"/"+E(t):a(t));return A(e,n)}function w(e,t,i){var n=e.match(R);if(!n)throw new Error("Invalid relative JSON-pointer: "+e);var r=+n[1],o=n[2];if("#"==o){if(r>=t)throw new Error("Cannot access property/index "+r+" levels up, current level is "+t);return i[t-r]}if(r>t)throw new Error("Cannot access data "+r+" levels up, current level is "+t);for(var s="data"+(t-r||""),l=s,c=o.split("/"),h=0;h",b="result"+r,F=e.opts.v5&&s.$data,x=F?e.util.getData(s.$data,o,e.dataPathArr):s;if(F&&(n+=" var schema"+r+" = "+x+"; ",x="schema"+r),C){var S=e.util.getData(y.$data,o,e.dataPathArr),$="exclusive"+r,D="op"+r,k="' + "+D+" + '";n+=" var schemaExcl"+r+" = "+S+"; ",S="schemaExcl"+r,n+=" if (typeof "+S+" != 'boolean' && "+S+" !== undefined) { "+d+" = false; ";var i=A,B=B||[];B.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_exclusiveFormatLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: {} ',e.opts.messages!==!1&&(n+=" , message: '"+A+" should be boolean' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var _=n;n=B.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+_+"]; return false; ":" var err = "+_+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } ",c&&(p+="}",n+=" else { "),F&&(n+=" if ("+x+" === undefined) "+d+" = true; else if (typeof "+x+" != 'string') "+d+" = false; else { ",p+="}"),f&&(n+=" if (!"+v+") "+d+" = true; else { ",p+="}"),n+=" var "+b+" = "+v+"("+h+", ",n+=F?""+x:""+e.util.toQuotedString(s),n+=" ); if ("+b+" === undefined) "+d+" = false; var exclusive"+r+" = "+S+" === true; if ("+d+" === undefined) { "+d+" = exclusive"+r+" ? "+b+" "+E+" 0 : "+b+" "+E+"= 0; } if (!"+d+") var op"+r+" = exclusive"+r+" ? '"+E+"' : '"+E+"=';"}else{var $=y===!0,k=E;$||(k+="=");var D="'"+k+"'";F&&(n+=" if ("+x+" === undefined) "+d+" = true; else if (typeof "+x+" != 'string') "+d+" = false; else { ",p+="}"),f&&(n+=" if (!"+v+") "+d+" = true; else { ",p+="}"),n+=" var "+b+" = "+v+"("+h+", ",n+=F?""+x:""+e.util.toQuotedString(s),n+=" ); if ("+b+" === undefined) "+d+" = false; if ("+d+" === undefined) "+d+" = "+b+" "+E,$||(n+="="),n+=" 0;"}n+=""+p+"if (!"+d+") { ";var i=t,B=B||[];B.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_formatLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { limit: ',n+=F?""+x:""+e.util.toQuotedString(s),n+=" } ",e.opts.messages!==!1&&(n+=" , message: 'should be "+k+' "',n+=F?"' + "+x+" + '":""+e.util.escapeQuotes(s),n+="\"' "),e.opts.verbose&&(n+=" , schema: ",n+=F?"validate.schema"+a:""+e.util.toQuotedString(s),n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var _=n;return n=B.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+_+"]; return false; ":" var err = "+_+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="}"}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u="errs__"+r,f=e.util.copy(e),p="";f.level++;var g,m="ifPassed"+e.level;n+="var "+m+";";var v=s;if(v)for(var w,A=-1,y=v.length-1;y>A;){if(w=v[A+=1],A&&!g&&(n+=" if (!"+m+") { ",p+="}"),w["if"]&&e.util.schemaHasRules(w["if"],e.RULES.all)){n+=" var "+u+" = errors; ";var C=e.compositeRule;if(e.compositeRule=f.compositeRule=!0,f.createErrors=!1,f.schema=w["if"],f.schemaPath=a+"["+A+"].if",f.errSchemaPath=l+"/"+A+"/if",n+=" "+e.validate(f)+" ",f.createErrors=!0,e.compositeRule=f.compositeRule=C,n+=" "+m+" = valid"+f.level+"; if ("+m+") { ","boolean"==typeof w.then){if(w.then===!1){var E=E||[];E.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"switch")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { caseIndex: '+A+" } ",e.opts.messages!==!1&&(n+=" , message: 'should pass \"switch\" keyword validation' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var b=n;n=E.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+b+"]; return false; ":" var err = "+b+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; "}n+=" var valid"+f.level+" = "+w.then+"; "}else f.schema=w.then,f.schemaPath=a+"["+A+"].then",f.errSchemaPath=l+"/"+A+"/then",n+=" "+e.validate(f)+" ";n+=" } else { errors = "+u+"; if (vErrors !== null) { if ("+u+") vErrors.length = "+u+"; else vErrors = null; } } "}else if(n+=" "+m+" = true; ","boolean"==typeof w.then){if(w.then===!1){var E=E||[];E.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"switch")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { caseIndex: '+A+" } ",e.opts.messages!==!1&&(n+=" , message: 'should pass \"switch\" keyword validation' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var b=n;n=E.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+b+"]; return false; ":" var err = "+b+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; "}n+=" var valid"+f.level+" = "+w.then+"; "}else f.schema=w.then,f.schemaPath=a+"["+A+"].then",f.errSchemaPath=l+"/"+A+"/then",n+=" "+e.validate(f)+" ";g=w["continue"]}return n+=""+p+"var "+d+" = valid"+f.level+"; ",n=e.util.cleanUpCode(n)}},function(e,t,i){"use strict";e.exports=function(e,t){function i(e){for(var t=0;tv;)if(m=g[v+=1],i(m)){if(m.type&&(r+=" if ("+e.util.checkDataType(m.type,l)+") { "),e.opts.useDefaults&&!e.compositeRule)if("object"==m.type&&e.schema.properties){var A=e.schema.properties,y=Object.keys(A),C=y;if(C)for(var E,b=-1,F=C.length-1;F>b;){E=C[b+=1];var x=A[E];if(void 0!==x["default"]){var S=l+e.util.getProperty(E);r+=" if ("+S+" === undefined) "+S+" = "+e.useDefault(x["default"])+"; "}}}else if("array"==m.type&&Array.isArray(e.schema.items)){var $=e.schema.items;if($)for(var x,D=-1,k=$.length-1;k>D;)if(x=$[D+=1],void 0!==x["default"]){var S=l+"["+D+"]";r+=" if ("+S+" === undefined) "+S+" = "+e.useDefault(x["default"])+"; "}}var B=m.rules;if(B)for(var _,L=-1,R=B.length-1;R>L;)if(_=B[L+=1],n(_)){if(_.custom){var A=e.schema[_.keyword],T=e.useCustomRule(_,A,e.schema,e),P=T.code+".errors",M=e.schemaPath+"."+_.keyword,O=e.errSchemaPath+"/"+_.keyword,I="errs"+s,D="i"+s,N="ruleErr"+s,j=_.definition,W=j.inline,H=j.macro;if(W||H||(r+=""+P+" = null;"),r+="var "+I+" = errors;",W&&j.statements)r+=" "+T.validate;else if(H){var V=e.util.copy(e);V.level++,V.schema=T.validate,V.schemaPath="";var z=e.compositeRule;e.compositeRule=V.compositeRule=!0;var U=e.validate(V).replace(/validate\.schema/g,T.code);e.compositeRule=V.compositeRule=z,r+=" "+U}r+="if (! ",W?r+=j.statements?" valid"+s+" ":" ("+T.validate+") ":H?r+=" valid"+V.level+" ":(r+=" "+T.code+".call(self ",j.compile?r+=" , "+l+" ":(r+=" , validate.schema"+M+" , "+l+" ",T.validate.length>2&&(r+=" , validate.schema"+e.schemaPath+" ")),r+=" ) "),r+=") { ",c=_.keyword;var K=K||[];K.push(r),r="";var K=K||[];K.push(r),r="",e.createErrors!==!1?(r+=" { keyword: '"+(c||"custom")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+O+"\" , params: { keyword: '"+_.keyword+"' } ",e.opts.messages!==!1&&(r+=" , message: 'should pass \""+_.keyword+"\" keyword validation' "),e.opts.verbose&&(r+=" , schema: validate.schema"+M+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+l+" "),r+=" } "):r+=" {} ";var G=r;r=K.pop(),r+=!e.compositeRule&&d?" validate.errors = ["+G+"]; return false; ":" var err = "+G+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ";var q=r;r=K.pop(),W?j.errors?"full"!=j.errors&&(r+=" for (var "+D+"="+I+"; "+D+"",'"',"`"," ","\r","\n"," "],m=["{","}","|","\\","^","`"].concat(g),v=["'"].concat(m),w=["%","/","?",";","#"].concat(v),A=["/","?","#"],y=255,C=/^[a-z0-9A-Z_-]{0,63}$/,E=/^([a-z0-9A-Z_-]{0,63})(.*)$/,b={javascript:!0,"javascript:":!0},F={javascript:!0,"javascript:":!0},x={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},S=i(63);n.prototype.parse=function(e,t,i){if(!l(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var n=e;n=n.trim();var r=f.exec(n);if(r){r=r[0];var o=r.toLowerCase();this.protocol=o,n=n.substr(r.length)}if(i||r||n.match(/^\/\/[^@\/]+@[^@\/]+/)){var s="//"===n.substr(0,2);!s||r&&F[r]||(n=n.substr(2),this.slashes=!0)}if(!F[r]&&(s||r&&!x[r])){for(var a=-1,c=0;ch)&&(a=h)}var d,p;p=-1===a?n.lastIndexOf("@"):n.lastIndexOf("@",a),-1!==p&&(d=n.slice(0,p),n=n.slice(p+1),this.auth=decodeURIComponent(d)),a=-1;for(var c=0;ch)&&(a=h)}-1===a&&(a=n.length),this.host=n.slice(0,a),n=n.slice(a),this.parseHost(),this.hostname=this.hostname||"";var g="["===this.hostname[0]&&"]"===this.hostname[this.hostname.length-1];if(!g)for(var m=this.hostname.split(/\./),c=0,$=m.length;$>c;c++){var D=m[c];if(D&&!D.match(C)){for(var k="",B=0,_=D.length;_>B;B++)k+=D.charCodeAt(B)>127?"x":D[B];if(!k.match(C)){var L=m.slice(0,c),R=m.slice(c+1),T=D.match(E);T&&(L.push(T[1]),R.unshift(T[2])),R.length&&(n="/"+R.join(".")+n),this.hostname=L.join(".");break}}}if(this.hostname.length>y?this.hostname="":this.hostname=this.hostname.toLowerCase(),!g){for(var P=this.hostname.split("."),M=[],c=0;cc;c++){var j=v[c],W=encodeURIComponent(j);W===j&&(W=escape(j)),n=n.split(j).join(W)}var H=n.indexOf("#");-1!==H&&(this.hash=n.substr(H),n=n.slice(0,H));var V=n.indexOf("?");if(-1!==V?(this.search=n.substr(V),this.query=n.substr(V+1),t&&(this.query=S.parse(this.query)),n=n.slice(0,V)):t&&(this.search="",this.query={}),n&&(this.pathname=n),x[o]&&this.hostname&&!this.pathname&&(this.pathname="/"),this.pathname||this.search){var I=this.pathname||"",O=this.search||"";this.path=I+O}return this.href=this.format(),this},n.prototype.format=function(){var e=this.auth||"";e&&(e=encodeURIComponent(e),e=e.replace(/%3A/i,":"),e+="@");var t=this.protocol||"",i=this.pathname||"",n=this.hash||"",r=!1,o="";this.host?r=e+this.host:this.hostname&&(r=e+(-1===this.hostname.indexOf(":")?this.hostname:"["+this.hostname+"]"),this.port&&(r+=":"+this.port)),this.query&&c(this.query)&&Object.keys(this.query).length&&(o=S.stringify(this.query));var s=this.search||o&&"?"+o||"";return t&&":"!==t.substr(-1)&&(t+=":"),this.slashes||(!t||x[t])&&r!==!1?(r="//"+(r||""),i&&"/"!==i.charAt(0)&&(i="/"+i)):r||(r=""),n&&"#"!==n.charAt(0)&&(n="#"+n),s&&"?"!==s.charAt(0)&&(s="?"+s),i=i.replace(/[?#]/g,function(e){return encodeURIComponent(e)}),s=s.replace("#","%23"),t+r+i+s+n},n.prototype.resolve=function(e){return this.resolveObject(r(e,!1,!0)).format()},n.prototype.resolveObject=function(e){if(l(e)){var t=new n;t.parse(e,!1,!0),e=t}var i=new n;if(Object.keys(this).forEach(function(e){i[e]=this[e]},this),i.hash=e.hash,""===e.href)return i.href=i.format(),i;if(e.slashes&&!e.protocol)return Object.keys(e).forEach(function(t){"protocol"!==t&&(i[t]=e[t])}),x[i.protocol]&&i.hostname&&!i.pathname&&(i.path=i.pathname="/"),i.href=i.format(),i;if(e.protocol&&e.protocol!==i.protocol){if(!x[e.protocol])return Object.keys(e).forEach(function(t){i[t]=e[t]}),i.href=i.format(),i;if(i.protocol=e.protocol,e.host||F[e.protocol])i.pathname=e.pathname;else{for(var r=(e.pathname||"").split("/");r.length&&!(e.host=r.shift()););e.host||(e.host=""),e.hostname||(e.hostname=""),""!==r[0]&&r.unshift(""),r.length<2&&r.unshift(""),i.pathname=r.join("/")}if(i.search=e.search,i.query=e.query,i.host=e.host||"",i.auth=e.auth,i.hostname=e.hostname||e.host,i.port=e.port,i.pathname||i.search){var o=i.pathname||"",s=i.search||"";i.path=o+s}return i.slashes=i.slashes||e.slashes,i.href=i.format(),i}var a=i.pathname&&"/"===i.pathname.charAt(0),c=e.host||e.pathname&&"/"===e.pathname.charAt(0),u=c||a||i.host&&e.pathname,f=u,p=i.pathname&&i.pathname.split("/")||[],r=e.pathname&&e.pathname.split("/")||[],g=i.protocol&&!x[i.protocol];if(g&&(i.hostname="",i.port=null,i.host&&(""===p[0]?p[0]=i.host:p.unshift(i.host)),i.host="",e.protocol&&(e.hostname=null,e.port=null,e.host&&(""===r[0]?r[0]=e.host:r.unshift(e.host)),e.host=null),u=u&&(""===r[0]||""===p[0])),c)i.host=e.host||""===e.host?e.host:i.host,i.hostname=e.hostname||""===e.hostname?e.hostname:i.hostname,i.search=e.search,i.query=e.query,p=r;else if(r.length)p||(p=[]),p.pop(),p=p.concat(r),i.search=e.search,i.query=e.query;else if(!d(e.search)){if(g){i.hostname=i.host=p.shift();var m=i.host&&i.host.indexOf("@")>0?i.host.split("@"):!1;m&&(i.auth=m.shift(),i.host=i.hostname=m.shift())}return i.search=e.search,i.query=e.query,h(i.pathname)&&h(i.search)||(i.path=(i.pathname?i.pathname:"")+(i.search?i.search:"")),i.href=i.format(),i}if(!p.length)return i.pathname=null,i.search?i.path="/"+i.search:i.path=null,i.href=i.format(),i;for(var v=p.slice(-1)[0],w=(i.host||e.host)&&("."===v||".."===v)||""===v,A=0,y=p.length;y>=0;y--)v=p[y],"."==v?p.splice(y,1):".."===v?(p.splice(y,1),A++):A&&(p.splice(y,1),A--);if(!u&&!f)for(;A--;A)p.unshift("..");!u||""===p[0]||p[0]&&"/"===p[0].charAt(0)||p.unshift(""),w&&"/"!==p.join("/").substr(-1)&&p.push("");var C=""===p[0]||p[0]&&"/"===p[0].charAt(0);if(g){i.hostname=i.host=C?"":p.length?p.shift():"";var m=i.host&&i.host.indexOf("@")>0?i.host.split("@"):!1;m&&(i.auth=m.shift(),i.host=i.hostname=m.shift())}return u=u||i.host&&p.length,u&&!C&&p.unshift(""),p.length?i.pathname=p.join("/"):(i.pathname=null,i.path=null),h(i.pathname)&&h(i.search)||(i.path=(i.pathname?i.pathname:"")+(i.search?i.search:"")),i.auth=e.auth||i.auth,i.slashes=i.slashes||e.slashes,i.href=i.format(),i},n.prototype.parseHost=function(){var e=this.host,t=p.exec(e);t&&(t=t[0],":"!==t&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},function(e,t,i){e.exports.id="ace/mode/json_worker",e.exports.src='"no use strict";(function(window){function resolveModuleId(id,paths){for(var testPath=id,tail="";testPath;){var alias=paths[testPath];if("string"==typeof alias)return alias+tail;if(alias)return alias.location.replace(/\\/*$/,"/")+(tail||alias.main||alias.name);if(alias===!1)return"";var i=testPath.lastIndexOf("/");if(-1===i)break;tail=testPath.substr(i)+tail,testPath=testPath.slice(0,i)}return id}if(!(void 0!==window.window&&window.document||window.acequire&&window.define)){window.console||(window.console=function(){var msgs=Array.prototype.slice.call(arguments,0);postMessage({type:"log",data:msgs})},window.console.error=window.console.warn=window.console.log=window.console.trace=window.console),window.window=window,window.ace=window,window.onerror=function(message,file,line,col,err){postMessage({type:"error",data:{message:message,data:err.data,file:file,line:line,col:col,stack:err.stack}})},window.normalizeModule=function(parentId,moduleName){if(-1!==moduleName.indexOf("!")){var chunks=moduleName.split("!");return window.normalizeModule(parentId,chunks[0])+"!"+window.normalizeModule(parentId,chunks[1])}if("."==moduleName.charAt(0)){var base=parentId.split("/").slice(0,-1).join("/");for(moduleName=(base?base+"/":"")+moduleName;-1!==moduleName.indexOf(".")&&previous!=moduleName;){var previous=moduleName;moduleName=moduleName.replace(/^\\.\\//,"").replace(/\\/\\.\\//,"/").replace(/[^\\/]+\\/\\.\\.\\//,"")}}return moduleName},window.acequire=function acequire(parentId,id){if(id||(id=parentId,parentId=null),!id.charAt)throw Error("worker.js acequire() accepts only (parentId, id) as arguments");id=window.normalizeModule(parentId,id);var module=window.acequire.modules[id];if(module)return module.initialized||(module.initialized=!0,module.exports=module.factory().exports),module.exports;if(!window.acequire.tlns)return console.log("unable to load "+id);var path=resolveModuleId(id,window.acequire.tlns);return".js"!=path.slice(-3)&&(path+=".js"),window.acequire.id=id,window.acequire.modules[id]={},importScripts(path),window.acequire(parentId,id)},window.acequire.modules={},window.acequire.tlns={},window.define=function(id,deps,factory){if(2==arguments.length?(factory=deps,"string"!=typeof id&&(deps=id,id=window.acequire.id)):1==arguments.length&&(factory=id,deps=[],id=window.acequire.id),"function"!=typeof factory)return window.acequire.modules[id]={exports:factory,initialized:!0},void 0;deps.length||(deps=["require","exports","module"]);var req=function(childId){return window.acequire(id,childId)};window.acequire.modules[id]={exports:{},factory:function(){var module=this,returnExports=factory.apply(this,deps.map(function(dep){switch(dep){case"require":return req;case"exports":return module.exports;case"module":return module;default:return req(dep)}}));return returnExports&&(module.exports=returnExports),module}}},window.define.amd={},acequire.tlns={},window.initBaseUrls=function(topLevelNamespaces){for(var i in topLevelNamespaces)acequire.tlns[i]=topLevelNamespaces[i]},window.initSender=function(){var EventEmitter=window.acequire("ace/lib/event_emitter").EventEmitter,oop=window.acequire("ace/lib/oop"),Sender=function(){};return function(){oop.implement(this,EventEmitter),this.callback=function(data,callbackId){postMessage({type:"call",id:callbackId,data:data})},this.emit=function(name,data){postMessage({type:"event",name:name,data:data})}}.call(Sender.prototype),new Sender};var main=window.main=null,sender=window.sender=null;window.onmessage=function(e){var msg=e.data;if(msg.event&&sender)sender._signal(msg.event,msg.data);else if(msg.command)if(main[msg.command])main[msg.command].apply(main,msg.args);else{if(!window[msg.command])throw Error("Unknown command:"+msg.command);window[msg.command].apply(window,msg.args)}else if(msg.init){window.initBaseUrls(msg.tlns),acequire("ace/lib/es5-shim"),sender=window.sender=window.initSender();var clazz=acequire(msg.module)[msg.classname];main=window.main=new clazz(sender)}}}})(this),ace.define("ace/lib/oop",["require","exports","module"],function(acequire,exports){"use strict";exports.inherits=function(ctor,superCtor){ctor.super_=superCtor,ctor.prototype=Object.create(superCtor.prototype,{constructor:{value:ctor,enumerable:!1,writable:!0,configurable:!0}})},exports.mixin=function(obj,mixin){for(var key in mixin)obj[key]=mixin[key];return obj},exports.implement=function(proto,mixin){exports.mixin(proto,mixin)}}),ace.define("ace/range",["require","exports","module"],function(acequire,exports){"use strict";var comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},Range=function(startRow,startColumn,endRow,endColumn){this.start={row:startRow,column:startColumn},this.end={row:endRow,column:endColumn}};(function(){this.isEqual=function(range){return this.start.row===range.start.row&&this.end.row===range.end.row&&this.start.column===range.start.column&&this.end.column===range.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(row,column){return 0==this.compare(row,column)},this.compareRange=function(range){var cmp,end=range.end,start=range.start;return cmp=this.compare(end.row,end.column),1==cmp?(cmp=this.compare(start.row,start.column),1==cmp?2:0==cmp?1:0):-1==cmp?-2:(cmp=this.compare(start.row,start.column),-1==cmp?-1:1==cmp?42:0)},this.comparePoint=function(p){return this.compare(p.row,p.column)},this.containsRange=function(range){return 0==this.comparePoint(range.start)&&0==this.comparePoint(range.end)},this.intersects=function(range){var cmp=this.compareRange(range);return-1==cmp||0==cmp||1==cmp},this.isEnd=function(row,column){return this.end.row==row&&this.end.column==column},this.isStart=function(row,column){return this.start.row==row&&this.start.column==column},this.setStart=function(row,column){"object"==typeof row?(this.start.column=row.column,this.start.row=row.row):(this.start.row=row,this.start.column=column)},this.setEnd=function(row,column){"object"==typeof row?(this.end.column=row.column,this.end.row=row.row):(this.end.row=row,this.end.column=column)},this.inside=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)||this.isStart(row,column)?!1:!0:!1},this.insideStart=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)?!1:!0:!1},this.insideEnd=function(row,column){return 0==this.compare(row,column)?this.isStart(row,column)?!1:!0:!1},this.compare=function(row,column){return this.isMultiLine()||row!==this.start.row?this.start.row>row?-1:row>this.end.row?1:this.start.row===row?column>=this.start.column?0:-1:this.end.row===row?this.end.column>=column?0:1:0:this.start.column>column?-1:column>this.end.column?1:0},this.compareStart=function(row,column){return this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.compareEnd=function(row,column){return this.end.row==row&&this.end.column==column?1:this.compare(row,column)},this.compareInside=function(row,column){return this.end.row==row&&this.end.column==column?1:this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.clipRows=function(firstRow,lastRow){if(this.end.row>lastRow)var end={row:lastRow+1,column:0};else if(firstRow>this.end.row)var end={row:firstRow,column:0};if(this.start.row>lastRow)var start={row:lastRow+1,column:0};else if(firstRow>this.start.row)var start={row:firstRow,column:0};return Range.fromPoints(start||this.start,end||this.end)},this.extend=function(row,column){var cmp=this.compare(row,column);if(0==cmp)return this;if(-1==cmp)var start={row:row,column:column};else var end={row:row,column:column};return Range.fromPoints(start||this.start,end||this.end)},this.isEmpty=function(){return this.start.row===this.end.row&&this.start.column===this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return Range.fromPoints(this.start,this.end)},this.collapseRows=function(){return 0==this.end.column?new Range(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new Range(this.start.row,0,this.end.row,0)},this.toScreenRange=function(session){var screenPosStart=session.documentToScreenPosition(this.start),screenPosEnd=session.documentToScreenPosition(this.end);return new Range(screenPosStart.row,screenPosStart.column,screenPosEnd.row,screenPosEnd.column)},this.moveBy=function(row,column){this.start.row+=row,this.start.column+=column,this.end.row+=row,this.end.column+=column}}).call(Range.prototype),Range.fromPoints=function(start,end){return new Range(start.row,start.column,end.row,end.column)},Range.comparePoints=comparePoints,Range.comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},exports.Range=Range}),ace.define("ace/apply_delta",["require","exports","module"],function(acequire,exports){"use strict";exports.applyDelta=function(docLines,delta){var row=delta.start.row,startColumn=delta.start.column,line=docLines[row]||"";switch(delta.action){case"insert":var lines=delta.lines;if(1===lines.length)docLines[row]=line.substring(0,startColumn)+delta.lines[0]+line.substring(startColumn);else{var args=[row,1].concat(delta.lines);docLines.splice.apply(docLines,args),docLines[row]=line.substring(0,startColumn)+docLines[row],docLines[row+delta.lines.length-1]+=line.substring(startColumn)}break;case"remove":var endColumn=delta.end.column,endRow=delta.end.row;row===endRow?docLines[row]=line.substring(0,startColumn)+line.substring(endColumn):docLines.splice(row,endRow-row+1,line.substring(0,startColumn)+docLines[endRow].substring(endColumn))}}}),ace.define("ace/lib/event_emitter",["require","exports","module"],function(acequire,exports){"use strict";var EventEmitter={},stopPropagation=function(){this.propagationStopped=!0},preventDefault=function(){this.defaultPrevented=!0};EventEmitter._emit=EventEmitter._dispatchEvent=function(eventName,e){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var listeners=this._eventRegistry[eventName]||[],defaultHandler=this._defaultHandlers[eventName];if(listeners.length||defaultHandler){"object"==typeof e&&e||(e={}),e.type||(e.type=eventName),e.stopPropagation||(e.stopPropagation=stopPropagation),e.preventDefault||(e.preventDefault=preventDefault),listeners=listeners.slice();for(var i=0;listeners.length>i&&(listeners[i](e,this),!e.propagationStopped);i++);return defaultHandler&&!e.defaultPrevented?defaultHandler(e,this):void 0}},EventEmitter._signal=function(eventName,e){var listeners=(this._eventRegistry||{})[eventName];if(listeners){listeners=listeners.slice();for(var i=0;listeners.length>i;i++)listeners[i](e,this)}},EventEmitter.once=function(eventName,callback){var _self=this;callback&&this.addEventListener(eventName,function newCallback(){_self.removeEventListener(eventName,newCallback),callback.apply(null,arguments)})},EventEmitter.setDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers||(handlers=this._defaultHandlers={_disabled_:{}}),handlers[eventName]){var old=handlers[eventName],disabled=handlers._disabled_[eventName];disabled||(handlers._disabled_[eventName]=disabled=[]),disabled.push(old);var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}handlers[eventName]=callback},EventEmitter.removeDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers){var disabled=handlers._disabled_[eventName];if(handlers[eventName]==callback)handlers[eventName],disabled&&this.setDefaultHandler(eventName,disabled.pop());else if(disabled){var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}}},EventEmitter.on=EventEmitter.addEventListener=function(eventName,callback,capturing){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];return listeners||(listeners=this._eventRegistry[eventName]=[]),-1==listeners.indexOf(callback)&&listeners[capturing?"unshift":"push"](callback),callback},EventEmitter.off=EventEmitter.removeListener=EventEmitter.removeEventListener=function(eventName,callback){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];if(listeners){var index=listeners.indexOf(callback);-1!==index&&listeners.splice(index,1)}},EventEmitter.removeAllListeners=function(eventName){this._eventRegistry&&(this._eventRegistry[eventName]=[])},exports.EventEmitter=EventEmitter}),ace.define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(acequire,exports){"use strict";var oop=acequire("./lib/oop"),EventEmitter=acequire("./lib/event_emitter").EventEmitter,Anchor=exports.Anchor=function(doc,row,column){this.$onChange=this.onChange.bind(this),this.attach(doc),column===void 0?this.setPosition(row.row,row.column):this.setPosition(row,column)};(function(){function $pointsInOrder(point1,point2,equalPointsInOrder){var bColIsAfter=equalPointsInOrder?point1.column<=point2.column:point1.columnthis.row)){var point=$getTransformedPoint(delta,{row:this.row,column:this.column},this.$insertRight);this.setPosition(point.row,point.column,!0)}},this.setPosition=function(row,column,noClip){var pos;if(pos=noClip?{row:row,column:column}:this.$clipPositionToDocument(row,column),this.row!=pos.row||this.column!=pos.column){var old={row:this.row,column:this.column};this.row=pos.row,this.column=pos.column,this._signal("change",{old:old,value:pos})}},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.attach=function(doc){this.document=doc||this.document,this.document.on("change",this.$onChange)},this.$clipPositionToDocument=function(row,column){var pos={};return row>=this.document.getLength()?(pos.row=Math.max(0,this.document.getLength()-1),pos.column=this.document.getLine(pos.row).length):0>row?(pos.row=0,pos.column=0):(pos.row=row,pos.column=Math.min(this.document.getLine(pos.row).length,Math.max(0,column))),0>column&&(pos.column=0),pos}}).call(Anchor.prototype)}),ace.define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"],function(acequire,exports){"use strict";var oop=acequire("./lib/oop"),applyDelta=acequire("./apply_delta").applyDelta,EventEmitter=acequire("./lib/event_emitter").EventEmitter,Range=acequire("./range").Range,Anchor=acequire("./anchor").Anchor,Document=function(textOrLines){this.$lines=[""],0===textOrLines.length?this.$lines=[""]:Array.isArray(textOrLines)?this.insertMergedLines({row:0,column:0},textOrLines):this.insert({row:0,column:0},textOrLines)};(function(){oop.implement(this,EventEmitter),this.setValue=function(text){var len=this.getLength()-1;this.remove(new Range(0,0,len,this.getLine(len).length)),this.insert({row:0,column:0},text)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(row,column){return new Anchor(this,row,column)},this.$split=0==="aaa".split(/a/).length?function(text){return text.replace(/\\r\\n|\\r/g,"\\n").split("\\n")}:function(text){return text.split(/\\r\\n|\\r|\\n/)},this.$detectNewLine=function(text){var match=text.match(/^.*?(\\r\\n|\\r|\\n)/m);this.$autoNewLine=match?match[1]:"\\n",this._signal("changeNewLineMode")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\\r\\n";case"unix":return"\\n";default:return this.$autoNewLine||"\\n"}},this.$autoNewLine="",this.$newLineMode="auto",this.setNewLineMode=function(newLineMode){this.$newLineMode!==newLineMode&&(this.$newLineMode=newLineMode,this._signal("changeNewLineMode"))},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(text){return"\\r\\n"==text||"\\r"==text||"\\n"==text},this.getLine=function(row){return this.$lines[row]||""},this.getLines=function(firstRow,lastRow){return this.$lines.slice(firstRow,lastRow+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(range){return this.getLinesForRange(range).join(this.getNewLineCharacter())},this.getLinesForRange=function(range){var lines;if(range.start.row===range.end.row)lines=[this.getLine(range.start.row).substring(range.start.column,range.end.column)];else{lines=this.getLines(range.start.row,range.end.row),lines[0]=(lines[0]||"").substring(range.start.column);var l=lines.length-1;range.end.row-range.start.row==l&&(lines[l]=lines[l].substring(0,range.end.column))}return lines},this.insertLines=function(row,lines){return console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."),this.insertFullLines(row,lines)},this.removeLines=function(firstRow,lastRow){return console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."),this.removeFullLines(firstRow,lastRow)},this.insertNewLine=function(position){return console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead."),this.insertMergedLines(position,["",""])},this.insert=function(position,text){return 1>=this.getLength()&&this.$detectNewLine(text),this.insertMergedLines(position,this.$split(text))},this.insertInLine=function(position,text){var start=this.clippedPos(position.row,position.column),end=this.pos(position.row,position.column+text.length);return this.applyDelta({start:start,end:end,action:"insert",lines:[text]},!0),this.clonePos(end)},this.clippedPos=function(row,column){var length=this.getLength();void 0===row?row=length:0>row?row=0:row>=length&&(row=length-1,column=void 0);var line=this.getLine(row);return void 0==column&&(column=line.length),column=Math.min(Math.max(column,0),line.length),{row:row,column:column}},this.clonePos=function(pos){return{row:pos.row,column:pos.column}},this.pos=function(row,column){return{row:row,column:column}},this.$clipPosition=function(position){var length=this.getLength();return position.row>=length?(position.row=Math.max(0,length-1),position.column=this.getLine(length-1).length):(position.row=Math.max(0,position.row),position.column=Math.min(Math.max(position.column,0),this.getLine(position.row).length)),position},this.insertFullLines=function(row,lines){row=Math.min(Math.max(row,0),this.getLength());var column=0;this.getLength()>row?(lines=lines.concat([""]),column=0):(lines=[""].concat(lines),row--,column=this.$lines[row].length),this.insertMergedLines({row:row,column:column},lines)},this.insertMergedLines=function(position,lines){var start=this.clippedPos(position.row,position.column),end={row:start.row+lines.length-1,column:(1==lines.length?start.column:0)+lines[lines.length-1].length};return this.applyDelta({start:start,end:end,action:"insert",lines:lines}),this.clonePos(end)},this.remove=function(range){var start=this.clippedPos(range.start.row,range.start.column),end=this.clippedPos(range.end.row,range.end.column);return this.applyDelta({start:start,end:end,action:"remove",lines:this.getLinesForRange({start:start,end:end})}),this.clonePos(start)},this.removeInLine=function(row,startColumn,endColumn){var start=this.clippedPos(row,startColumn),end=this.clippedPos(row,endColumn);return this.applyDelta({start:start,end:end,action:"remove",lines:this.getLinesForRange({start:start,end:end})},!0),this.clonePos(start)},this.removeFullLines=function(firstRow,lastRow){firstRow=Math.min(Math.max(0,firstRow),this.getLength()-1),lastRow=Math.min(Math.max(0,lastRow),this.getLength()-1);var deleteFirstNewLine=lastRow==this.getLength()-1&&firstRow>0,deleteLastNewLine=this.getLength()-1>lastRow,startRow=deleteFirstNewLine?firstRow-1:firstRow,startCol=deleteFirstNewLine?this.getLine(startRow).length:0,endRow=deleteLastNewLine?lastRow+1:lastRow,endCol=deleteLastNewLine?0:this.getLine(endRow).length,range=new Range(startRow,startCol,endRow,endCol),deletedLines=this.$lines.slice(firstRow,lastRow+1);return this.applyDelta({start:range.start,end:range.end,action:"remove",lines:this.getLinesForRange(range)}),deletedLines},this.removeNewLine=function(row){this.getLength()-1>row&&row>=0&&this.applyDelta({start:this.pos(row,this.getLine(row).length),end:this.pos(row+1,0),action:"remove",lines:["",""]})},this.replace=function(range,text){if(range instanceof Range||(range=Range.fromPoints(range.start,range.end)),0===text.length&&range.isEmpty())return range.start;if(text==this.getTextRange(range))return range.end;this.remove(range);var end;return end=text?this.insert(range.start,text):range.start},this.applyDeltas=function(deltas){for(var i=0;deltas.length>i;i++)this.applyDelta(deltas[i])},this.revertDeltas=function(deltas){for(var i=deltas.length-1;i>=0;i--)this.revertDelta(deltas[i])},this.applyDelta=function(delta,doNotValidate){var isInsert="insert"==delta.action;(isInsert?1>=delta.lines.length&&!delta.lines[0]:!Range.comparePoints(delta.start,delta.end))||(isInsert&&delta.lines.length>2e4&&this.$splitAndapplyLargeDelta(delta,2e4),applyDelta(this.$lines,delta,doNotValidate),this._signal("change",delta))},this.$splitAndapplyLargeDelta=function(delta,MAX){for(var lines=delta.lines,l=lines.length,row=delta.start.row,column=delta.start.column,from=0,to=0;;){from=to,to+=MAX-1;var chunk=lines.slice(from,to);if(to>l){delta.lines=chunk,delta.start.row=row+from,delta.start.column=column;break}chunk.push(""),this.applyDelta({start:this.pos(row+from,column),end:this.pos(row+to,column=0),action:delta.action,lines:chunk},!0)}},this.revertDelta=function(delta){this.applyDelta({start:this.clonePos(delta.start),end:this.clonePos(delta.end),action:"insert"==delta.action?"remove":"insert",lines:delta.lines.slice()})},this.indexToPosition=function(index,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,i=startRow||0,l=lines.length;l>i;i++)if(index-=lines[i].length+newlineLength,0>index)return{row:i,column:index+lines[i].length+newlineLength};return{row:l-1,column:lines[l-1].length}},this.positionToIndex=function(pos,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,index=0,row=Math.min(pos.row,lines.length),i=startRow||0;row>i;++i)index+=lines[i].length+newlineLength;return index+pos.column}}).call(Document.prototype),exports.Document=Document}),ace.define("ace/lib/lang",["require","exports","module"],function(acequire,exports){"use strict";exports.last=function(a){return a[a.length-1]},exports.stringReverse=function(string){return string.split("").reverse().join("")},exports.stringRepeat=function(string,count){for(var result="";count>0;)1&count&&(result+=string),(count>>=1)&&(string+=string);return result};var trimBeginRegexp=/^\\s\\s*/,trimEndRegexp=/\\s\\s*$/;exports.stringTrimLeft=function(string){return string.replace(trimBeginRegexp,"")},exports.stringTrimRight=function(string){return string.replace(trimEndRegexp,"")},exports.copyObject=function(obj){var copy={};for(var key in obj)copy[key]=obj[key];return copy},exports.copyArray=function(array){for(var copy=[],i=0,l=array.length;l>i;i++)copy[i]=array[i]&&"object"==typeof array[i]?this.copyObject(array[i]):array[i];return copy},exports.deepCopy=function deepCopy(obj){if("object"!=typeof obj||!obj)return obj;var copy;if(Array.isArray(obj)){copy=[];for(var key=0;obj.length>key;key++)copy[key]=deepCopy(obj[key]);return copy}var cons=obj.constructor;if(cons===RegExp)return obj;copy=cons();for(var key in obj)copy[key]=deepCopy(obj[key]);return copy},exports.arrayToMap=function(arr){for(var map={},i=0;arr.length>i;i++)map[arr[i]]=1;return map},exports.createMap=function(props){var map=Object.create(null);for(var i in props)map[i]=props[i];return map},exports.arrayRemove=function(array,value){for(var i=0;array.length>=i;i++)value===array[i]&&array.splice(i,1)},exports.escapeRegExp=function(str){return str.replace(/([.*+?^${}()|[\\]\\/\\\\])/g,"\\\\$1")},exports.escapeHTML=function(str){return str.replace(/&/g,"&").replace(/"/g,""").replace(/\'/g,"'").replace(/i;i+=2){if(Array.isArray(data[i+1]))var d={action:"insert",start:data[i],lines:data[i+1]};else var d={action:"remove",start:data[i],end:data[i+1]};doc.applyDelta(d,!0)}return _self.$timeout?deferredUpdate.schedule(_self.$timeout):(_self.onUpdate(),void 0)})};(function(){this.$timeout=500,this.setTimeout=function(timeout){this.$timeout=timeout},this.setValue=function(value){this.doc.setValue(value),this.deferredUpdate.schedule(this.$timeout)},this.getValue=function(callbackId){this.sender.callback(this.doc.getValue(),callbackId)},this.onUpdate=function(){},this.isPending=function(){return this.deferredUpdate.isPending()}}).call(Mirror.prototype)}),ace.define("ace/mode/json/json_parse",["require","exports","module"],function(){"use strict";var at,ch,text,value,escapee={\'"\':\'"\',"\\\\":"\\\\","/":"/",b:"\\b",f:"\\f",n:"\\n",r:"\\r",t:" "},error=function(m){throw{name:"SyntaxError",message:m,at:at,text:text}},next=function(c){return c&&c!==ch&&error("Expected \'"+c+"\' instead of \'"+ch+"\'"),ch=text.charAt(at),at+=1,ch},number=function(){var number,string="";for("-"===ch&&(string="-",next("-"));ch>="0"&&"9">=ch;)string+=ch,next();if("."===ch)for(string+=".";next()&&ch>="0"&&"9">=ch;)string+=ch;if("e"===ch||"E"===ch)for(string+=ch,next(),("-"===ch||"+"===ch)&&(string+=ch,next());ch>="0"&&"9">=ch;)string+=ch,next();return number=+string,isNaN(number)?(error("Bad number"),void 0):number},string=function(){var hex,i,uffff,string="";if(\'"\'===ch)for(;next();){if(\'"\'===ch)return next(),string;if("\\\\"===ch)if(next(),"u"===ch){for(uffff=0,i=0;4>i&&(hex=parseInt(next(),16),isFinite(hex));i+=1)uffff=16*uffff+hex;string+=String.fromCharCode(uffff)}else{if("string"!=typeof escapee[ch])break;string+=escapee[ch]}else string+=ch}error("Bad string")},white=function(){for(;ch&&" ">=ch;)next()},word=function(){switch(ch){case"t":return next("t"),next("r"),next("u"),next("e"),!0;case"f":return next("f"),next("a"),next("l"),next("s"),next("e"),!1;case"n":return next("n"),next("u"),next("l"),next("l"),null}error("Unexpected \'"+ch+"\'")},array=function(){var array=[];if("["===ch){if(next("["),white(),"]"===ch)return next("]"),array;for(;ch;){if(array.push(value()),white(),"]"===ch)return next("]"),array;next(","),white()}}error("Bad array")},object=function(){var key,object={};if("{"===ch){if(next("{"),white(),"}"===ch)return next("}"),object;for(;ch;){if(key=string(),white(),next(":"),Object.hasOwnProperty.call(object,key)&&error(\'Duplicate key "\'+key+\'"\'),object[key]=value(),white(),"}"===ch)return next("}"),object;next(","),white()}}error("Bad object")};return value=function(){switch(white(),ch){case"{":return object();case"[":return array();case\'"\':return string();case"-":return number();default:return ch>="0"&&"9">=ch?number():word()}},function(source,reviver){var result;return text=source,at=0,ch=" ",result=value(),white(),ch&&error("Syntax error"),"function"==typeof reviver?function walk(holder,key){var k,v,value=holder[key];if(value&&"object"==typeof value)for(k in value)Object.hasOwnProperty.call(value,k)&&(v=walk(value,k),void 0!==v?value[k]=v:delete value[k]);return reviver.call(holder,key,value)}({"":result},""):result}}),ace.define("ace/mode/json_worker",["require","exports","module","ace/lib/oop","ace/worker/mirror","ace/mode/json/json_parse"],function(acequire,exports){"use strict";var oop=acequire("../lib/oop"),Mirror=acequire("../worker/mirror").Mirror,parse=acequire("./json/json_parse"),JsonWorker=exports.JsonWorker=function(sender){Mirror.call(this,sender),this.setTimeout(200)};oop.inherits(JsonWorker,Mirror),function(){this.onUpdate=function(){var value=this.doc.getValue(),errors=[];try{value&&parse(value)}catch(e){var pos=this.doc.indexToPosition(e.at-1);errors.push({row:pos.row,column:pos.column,text:e.message,type:"error"})}this.sender.emit("annotate",errors)}}.call(JsonWorker.prototype)}),ace.define("ace/lib/es5-shim",["require","exports","module"],function(){function Empty(){}function doesDefinePropertyWork(object){try{return Object.defineProperty(object,"sentinel",{}),"sentinel"in object}catch(exception){}}function toInteger(n){return n=+n,n!==n?n=0:0!==n&&n!==1/0&&n!==-(1/0)&&(n=(n>0||-1)*Math.floor(Math.abs(n))),n}Function.prototype.bind||(Function.prototype.bind=function(that){var target=this;if("function"!=typeof target)throw new TypeError("Function.prototype.bind called on incompatible "+target);var args=slice.call(arguments,1),bound=function(){if(this instanceof bound){var result=target.apply(this,args.concat(slice.call(arguments)));return Object(result)===result?result:this}return target.apply(that,args.concat(slice.call(arguments)))};return target.prototype&&(Empty.prototype=target.prototype,bound.prototype=new Empty,Empty.prototype=null),bound});var defineGetter,defineSetter,lookupGetter,lookupSetter,supportsAccessors,call=Function.prototype.call,prototypeOfArray=Array.prototype,prototypeOfObject=Object.prototype,slice=prototypeOfArray.slice,_toString=call.bind(prototypeOfObject.toString),owns=call.bind(prototypeOfObject.hasOwnProperty);if((supportsAccessors=owns(prototypeOfObject,"__defineGetter__"))&&(defineGetter=call.bind(prototypeOfObject.__defineGetter__),defineSetter=call.bind(prototypeOfObject.__defineSetter__),lookupGetter=call.bind(prototypeOfObject.__lookupGetter__),lookupSetter=call.bind(prototypeOfObject.__lookupSetter__)),2!=[1,2].splice(0).length)if(function(){function makeArray(l){var a=Array(l+2);return a[0]=a[1]=0,a}var lengthBefore,array=[];return array.splice.apply(array,makeArray(20)),array.splice.apply(array,makeArray(26)),lengthBefore=array.length,array.splice(5,0,"XXX"),lengthBefore+1==array.length,lengthBefore+1==array.length?!0:void 0\n}()){var array_splice=Array.prototype.splice;Array.prototype.splice=function(start,deleteCount){return arguments.length?array_splice.apply(this,[void 0===start?0:start,void 0===deleteCount?this.length-start:deleteCount].concat(slice.call(arguments,2))):[]}}else Array.prototype.splice=function(pos,removeCount){var length=this.length;pos>0?pos>length&&(pos=length):void 0==pos?pos=0:0>pos&&(pos=Math.max(length+pos,0)),length>pos+removeCount||(removeCount=length-pos);var removed=this.slice(pos,pos+removeCount),insert=slice.call(arguments,2),add=insert.length;if(pos===length)add&&this.push.apply(this,insert);else{var remove=Math.min(removeCount,length-pos),tailOldPos=pos+remove,tailNewPos=tailOldPos+add-remove,tailCount=length-tailOldPos,lengthAfterRemove=length-remove;if(tailOldPos>tailNewPos)for(var i=0;tailCount>i;++i)this[tailNewPos+i]=this[tailOldPos+i];else if(tailNewPos>tailOldPos)for(i=tailCount;i--;)this[tailNewPos+i]=this[tailOldPos+i];if(add&&pos===lengthAfterRemove)this.length=lengthAfterRemove,this.push.apply(this,insert);else for(this.length=lengthAfterRemove+add,i=0;add>i;++i)this[pos+i]=insert[i]}return removed};Array.isArray||(Array.isArray=function(obj){return"[object Array]"==_toString(obj)});var boxedString=Object("a"),splitString="a"!=boxedString[0]||!(0 in boxedString);if(Array.prototype.forEach||(Array.prototype.forEach=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,thisp=arguments[1],i=-1,length=self.length>>>0;if("[object Function]"!=_toString(fun))throw new TypeError;for(;length>++i;)i in self&&fun.call(thisp,self[i],i,object)}),Array.prototype.map||(Array.prototype.map=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0,result=Array(length),thisp=arguments[1];if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");for(var i=0;length>i;i++)i in self&&(result[i]=fun.call(thisp,self[i],i,object));return result}),Array.prototype.filter||(Array.prototype.filter=function(fun){var value,object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0,result=[],thisp=arguments[1];if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");for(var i=0;length>i;i++)i in self&&(value=self[i],fun.call(thisp,value,i,object)&&result.push(value));return result}),Array.prototype.every||(Array.prototype.every=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0,thisp=arguments[1];if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");for(var i=0;length>i;i++)if(i in self&&!fun.call(thisp,self[i],i,object))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0,thisp=arguments[1];if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");for(var i=0;length>i;i++)if(i in self&&fun.call(thisp,self[i],i,object))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0;if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");if(!length&&1==arguments.length)throw new TypeError("reduce of empty array with no initial value");var result,i=0;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i++];break}if(++i>=length)throw new TypeError("reduce of empty array with no initial value")}for(;length>i;i++)i in self&&(result=fun.call(void 0,result,self[i],i,object));return result}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0;if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");if(!length&&1==arguments.length)throw new TypeError("reduceRight of empty array with no initial value");var result,i=length-1;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i--];break}if(0>--i)throw new TypeError("reduceRight of empty array with no initial value")}do i in this&&(result=fun.call(void 0,result,self[i],i,object));while(i--);return result}),Array.prototype.indexOf&&-1==[0,1].indexOf(1,2)||(Array.prototype.indexOf=function(sought){var self=splitString&&"[object String]"==_toString(this)?this.split(""):toObject(this),length=self.length>>>0;if(!length)return-1;var i=0;for(arguments.length>1&&(i=toInteger(arguments[1])),i=i>=0?i:Math.max(0,length+i);length>i;i++)if(i in self&&self[i]===sought)return i;return-1}),Array.prototype.lastIndexOf&&-1==[0,1].lastIndexOf(0,-3)||(Array.prototype.lastIndexOf=function(sought){var self=splitString&&"[object String]"==_toString(this)?this.split(""):toObject(this),length=self.length>>>0;if(!length)return-1;var i=length-1;for(arguments.length>1&&(i=Math.min(i,toInteger(arguments[1]))),i=i>=0?i:length-Math.abs(i);i>=0;i--)if(i in self&&sought===self[i])return i;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(object){return object.__proto__||(object.constructor?object.constructor.prototype:prototypeOfObject)}),!Object.getOwnPropertyDescriptor){var ERR_NON_OBJECT="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(object,property){if("object"!=typeof object&&"function"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT+object);if(owns(object,property)){var descriptor,getter,setter;if(descriptor={enumerable:!0,configurable:!0},supportsAccessors){var prototype=object.__proto__;object.__proto__=prototypeOfObject;var getter=lookupGetter(object,property),setter=lookupSetter(object,property);if(object.__proto__=prototype,getter||setter)return getter&&(descriptor.get=getter),setter&&(descriptor.set=setter),descriptor}return descriptor.value=object[property],descriptor}}}if(Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(object){return Object.keys(object)}),!Object.create){var createEmpty;createEmpty=null===Object.prototype.__proto__?function(){return{__proto__:null}}:function(){var empty={};for(var i in empty)empty[i]=null;return empty.constructor=empty.hasOwnProperty=empty.propertyIsEnumerable=empty.isPrototypeOf=empty.toLocaleString=empty.toString=empty.valueOf=empty.__proto__=null,empty},Object.create=function(prototype,properties){var object;if(null===prototype)object=createEmpty();else{if("object"!=typeof prototype)throw new TypeError("typeof prototype["+typeof prototype+"] != \'object\'");var Type=function(){};Type.prototype=prototype,object=new Type,object.__proto__=prototype}return void 0!==properties&&Object.defineProperties(object,properties),object}}if(Object.defineProperty){var definePropertyWorksOnObject=doesDefinePropertyWork({}),definePropertyWorksOnDom="undefined"==typeof document||doesDefinePropertyWork(document.createElement("div"));if(!definePropertyWorksOnObject||!definePropertyWorksOnDom)var definePropertyFallback=Object.defineProperty}if(!Object.defineProperty||definePropertyFallback){var ERR_NON_OBJECT_DESCRIPTOR="Property description must be an object: ",ERR_NON_OBJECT_TARGET="Object.defineProperty called on non-object: ",ERR_ACCESSORS_NOT_SUPPORTED="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(object,property,descriptor){if("object"!=typeof object&&"function"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT_TARGET+object);if("object"!=typeof descriptor&&"function"!=typeof descriptor||null===descriptor)throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR+descriptor);if(definePropertyFallback)try{return definePropertyFallback.call(Object,object,property,descriptor)}catch(exception){}if(owns(descriptor,"value"))if(supportsAccessors&&(lookupGetter(object,property)||lookupSetter(object,property))){var prototype=object.__proto__;object.__proto__=prototypeOfObject,delete object[property],object[property]=descriptor.value,object.__proto__=prototype}else object[property]=descriptor.value;else{if(!supportsAccessors)throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);owns(descriptor,"get")&&defineGetter(object,property,descriptor.get),owns(descriptor,"set")&&defineSetter(object,property,descriptor.set)}return object}}Object.defineProperties||(Object.defineProperties=function(object,properties){for(var property in properties)owns(properties,property)&&Object.defineProperty(object,property,properties[property]);return object}),Object.seal||(Object.seal=function(object){return object}),Object.freeze||(Object.freeze=function(object){return object});try{Object.freeze(function(){})}catch(exception){Object.freeze=function(freezeObject){return function(object){return"function"==typeof object?object:freezeObject(object)}}(Object.freeze)}if(Object.preventExtensions||(Object.preventExtensions=function(object){return object}),Object.isSealed||(Object.isSealed=function(){return!1}),Object.isFrozen||(Object.isFrozen=function(){return!1}),Object.isExtensible||(Object.isExtensible=function(object){if(Object(object)===object)throw new TypeError;for(var name="";owns(object,name);)name+="?";object[name]=!0;var returnValue=owns(object,name);return delete object[name],returnValue}),!Object.keys){var hasDontEnumBug=!0,dontEnums=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],dontEnumsLength=dontEnums.length;for(var key in{toString:null})hasDontEnumBug=!1;Object.keys=function(object){if("object"!=typeof object&&"function"!=typeof object||null===object)throw new TypeError("Object.keys called on a non-object");var keys=[];for(var name in object)owns(object,name)&&keys.push(name);if(hasDontEnumBug)for(var i=0,ii=dontEnumsLength;ii>i;i++){var dontEnum=dontEnums[i];owns(object,dontEnum)&&keys.push(dontEnum)}return keys}}Date.now||(Date.now=function(){return(new Date).getTime()});var ws=" \\n \\f\\r   ᠎              \\u2028\\u2029";if(!String.prototype.trim||ws.trim()){ws="["+ws+"]";var trimBeginRegexp=RegExp("^"+ws+ws+"*"),trimEndRegexp=RegExp(ws+ws+"*$");String.prototype.trim=function(){return(this+"").replace(trimBeginRegexp,"").replace(trimEndRegexp,"")}}var toObject=function(o){if(null==o)throw new TypeError("can\'t convert "+o+" to object");return Object(o)}});'; -},function(e,t,i){t.parse=i(60),t.stringify=i(61)},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.dataLevel,o=e.schema[t],s=e.errSchemaPath+"/"+t,a=!e.opts.allErrors,l="data"+(r||"");if("#"==o||"#/"==o)e.isRoot?(n+=" if (! validate("+l+", (dataPath || '')",'""'!=e.errorPath&&(n+=" + "+e.errorPath),n+=") ) { if (vErrors === null) vErrors = validate.errors; else vErrors = vErrors.concat(validate.errors); errors = vErrors.length; } ",a&&(n+=" else { ")):(n+=" if (! root.refVal[0]("+l+", (dataPath || '')",'""'!=e.errorPath&&(n+=" + "+e.errorPath),n+=") ) { if (vErrors === null) vErrors = root.refVal[0].errors; else vErrors = vErrors.concat(root.refVal[0].errors); errors = vErrors.length; } ",a&&(n+=" else { "));else{var c=e.resolveRef(e.baseId,o,e.isRoot);if(void 0===c){var h="can't resolve reference "+o+" from id "+e.baseId;if("fail"==e.opts.missingRefs){console.log(h);var d=d||[];d.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"$ref")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+s+"\" , params: { ref: '"+e.util.escapeQuotes(o)+"' } ",e.opts.messages!==!1&&(n+=" , message: 'can\\'t resolve reference "+e.util.escapeQuotes(o)+"' "),e.opts.verbose&&(n+=" , schema: "+e.util.toQuotedString(o)+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+l+" "),n+=" } "):n+=" {} ";var u=n;n=d.pop(),n+=!e.compositeRule&&a?" validate.errors = ["+u+"]; return false; ":" var err = "+u+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a&&(n+=" if (false) { ")}else{if("ignore"!=e.opts.missingRefs){var f=new Error(h);throw f.missingRef=e.resolve.url(e.baseId,o),f.missingSchema=e.resolve.normalizeId(e.resolve.fullPath(f.missingRef)),f}console.log(h),a&&(n+=" if (true) { ")}}else if("string"==typeof c)n+=" if (! "+c+"("+l+", (dataPath || '')",'""'!=e.errorPath&&(n+=" + "+e.errorPath),n+=") ) { if (vErrors === null) vErrors = "+c+".errors; else vErrors = vErrors.concat("+c+".errors); errors = vErrors.length; } ",a&&(n+=" else { ");else{var p=e.util.copy(e);p.level++,p.schema=c.schema,p.schemaPath="",p.errSchemaPath=o;var g=e.validate(p).replace(/validate\.schema/g,c.code);n+=" "+g+" ",a&&(n+=" if (valid"+p.level+") { ")}}return n}},function(e,t,i){"use strict";e.exports=function(e,t){var i=" ",n=e.schema[t],r=e.schemaPath+"."+t,o=e.errSchemaPath+"/"+t,s=!e.opts.allErrors,a=e.util.copy(e),l="";a.level++;var c=n;if(c)for(var h,d=-1,u=c.length-1;u>d;)h=c[d+=1],e.util.schemaHasRules(h,e.RULES.all)&&(a.schema=h,a.schemaPath=r+"["+d+"]",a.errSchemaPath=o+"/"+d,i+=" "+e.validate(a)+" ",s&&(i+=" if (valid"+a.level+") { ",l+="}"));return s&&(i+=" "+l.slice(0,-1)),i=e.util.cleanUpCode(i)}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u="errs__"+r,f=e.util.copy(e),p="";f.level++;var g=s.every(function(t){return e.util.schemaHasRules(t,e.RULES.all)});if(g){n+=" var "+u+" = errors; var "+d+" = false; ";var m=e.compositeRule;e.compositeRule=f.compositeRule=!0;var v=s;if(v)for(var w,A=-1,y=v.length-1;y>A;)w=v[A+=1],f.schema=w,f.schemaPath=a+"["+A+"]",f.errSchemaPath=l+"/"+A,n+=" "+e.validate(f)+" "+d+" = "+d+" || valid"+f.level+"; if (!"+d+") { ",p+="}";e.compositeRule=f.compositeRule=m,n+=" "+p+" if (!"+d+") { var err = ",e.createErrors!==!1?(n+=" { keyword: '"+(i||"anyOf")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: {} ',e.opts.messages!==!1&&(n+=" , message: 'should match some schema in anyOf' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ",n+="; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } else { errors = "+u+"; if (vErrors !== null) { if ("+u+") vErrors.length = "+u+"; else vErrors = null; } ",e.opts.allErrors&&(n+=" } "),n=e.util.cleanUpCode(n)}else c&&(n+=" if (true) { ");return n}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="errs__"+r,u=e.util.copy(e),f="";u.level++;var p={},g={};for(A in s){var m=s[A],v=Array.isArray(m)?g:p;v[A]=m}n+="var "+d+" = errors;";var w=e.errorPath;n+="var missing"+r+";";for(var A in g){v=g[A],n+=" if ("+h+e.util.getProperty(A)+" !== undefined && ( ";var y=v;if(y)for(var C,E=-1,b=y.length-1;b>E;){C=y[E+=1],E&&(n+=" || ");var F=e.util.getProperty(C);n+=" ( "+h+F+" === undefined && (missing"+r+" = "+e.util.toQuotedString(e.opts.jsonPointers?C:F)+") ) "}n+=")) { ";var x="missing"+r,S="' + "+x+" + '";e.opts._errorDataPathProperty&&(e.errorPath=e.opts.jsonPointers?e.util.getPathExpr(w,x,!0):w+" + "+x);var $=$||[];$.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"dependencies")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { property: '"+e.util.escapeQuotes(A)+"', missingProperty: '"+S+"', depsCount: "+v.length+", deps: '"+e.util.escapeQuotes(1==v.length?v[0]:v.join(", "))+"' } ",e.opts.messages!==!1&&(n+=" , message: 'should have ",n+=1==v.length?"property "+e.util.escapeQuotes(v[0]):"properties "+e.util.escapeQuotes(v.join(", ")),n+=" when property "+e.util.escapeQuotes(A)+" is present' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var D=n;n=$.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+D+"]; return false; ":" var err = "+D+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } ",c&&(f+="}",n+=" else { ")}e.errorPath=w;for(var A in p){var m=p[A];e.util.schemaHasRules(m,e.RULES.all)&&(n+=" valid"+u.level+" = true; if ("+h+"['"+A+"'] !== undefined) { ",u.schema=m,u.schemaPath=a+e.util.getProperty(A),u.errSchemaPath=l+"/"+e.util.escapeFragment(A),n+=" "+e.validate(u)+" } ",c&&(n+=" if (valid"+u.level+") { ",f+="}"))}return c&&(n+=" "+f+" if ("+d+" == errors) {"),n=e.util.cleanUpCode(n)}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u=e.opts.v5&&s.$data,f=u?e.util.getData(s.$data,o,e.dataPathArr):s;u&&(n+=" var schema"+r+" = "+f+"; ",f="schema"+r);var p="i"+r;u||(n+=" var schema"+r+" = validate.schema"+a+";"),n+="var "+d+";",u&&(n+=" if (schema"+r+" === undefined) "+d+" = true; else if (!Array.isArray(schema"+r+")) "+d+" = false; else {"),n+=""+d+" = false;for (var "+p+"=0; "+p+"b;)if(E=C[b+=1],e.util.schemaHasRules(E,e.RULES.all)){n+=" valid"+f.level+" = true; if ("+h+".length > "+b+") { ";var x=h+"["+b+"]";f.schema=E,f.schemaPath=a+"["+b+"]",f.errSchemaPath=l+"/"+b,f.errorPath=e.util.getPathExpr(e.errorPath,b,e.opts.jsonPointers,!0),e.opts.v5&&(f.dataPathArr[g]=b);var S=e.validate(f);n+=e.util.varOccurences(S,m)<2?" "+e.util.varReplace(S,m,x)+" ":" var "+m+" = "+x+"; "+S+" ",n+=" } ",c&&(n+=" if (valid"+f.level+") { ",p+="}")}if("object"==typeof v&&e.util.schemaHasRules(v,e.RULES.all)){f.schema=v,f.schemaPath=e.schemaPath+".additionalItems",f.errSchemaPath=e.errSchemaPath+"/additionalItems",n+=" valid"+f.level+" = true; if ("+h+".length > "+s.length+") { for (var i"+r+" = "+s.length+"; i"+r+" < "+h+".length; i"+r+"++) { ",f.errorPath=e.util.getPathExpr(e.errorPath,"i"+r,e.opts.jsonPointers,!0);var x=h+"[i"+r+"]";e.opts.v5&&(f.dataPathArr[g]="i"+r);var S=e.validate(f);n+=e.util.varOccurences(S,m)<2?" "+e.util.varReplace(S,m,x)+" ":" var "+m+" = "+x+"; "+S+" ",c&&(n+=" if (!valid"+f.level+") break; "),n+=" } } ",c&&(n+=" if (valid"+f.level+") { ",p+="}")}}else if(e.util.schemaHasRules(s,e.RULES.all)){f.schema=s,f.schemaPath=a,f.errSchemaPath=l,n+=" for (var i"+r+" = 0; i"+r+" < "+h+".length; i"+r+"++) { ",f.errorPath=e.util.getPathExpr(e.errorPath,"i"+r,e.opts.jsonPointers,!0);var x=h+"[i"+r+"]";e.opts.v5&&(f.dataPathArr[g]="i"+r);var S=e.validate(f);n+=e.util.varOccurences(S,m)<2?" "+e.util.varReplace(S,m,x)+" ":" var "+m+" = "+x+"; "+S+" ",c&&(n+=" if (!valid"+f.level+") break; "),n+=" } ",c&&(n+=" if (valid"+f.level+") { ",p+="}")}return c&&(n+=" "+p+" if ("+u+" == errors) {"),n=e.util.cleanUpCode(n)}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d=e.opts.v5&&s.$data,u=d?e.util.getData(s.$data,o,e.dataPathArr):s;d&&(n+=" var schema"+r+" = "+u+"; ",u="schema"+r);var f="maximum"==t,p=f?"exclusiveMaximum":"exclusiveMinimum",g=e.schema[p],m=e.opts.v5&&g&&g.$data,v=f?"<":">",w=f?">":"<";if(m){var A=e.util.getData(g.$data,o,e.dataPathArr),y="exclusive"+r,C="op"+r,E="' + "+C+" + '";n+=" var schemaExcl"+r+" = "+A+"; ",A="schemaExcl"+r,n+=" var exclusive"+r+"; if (typeof "+A+" != 'boolean' && typeof "+A+" != 'undefined') { ";var i=p,b=b||[];b.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_exclusiveLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: {} ',e.opts.messages!==!1&&(n+=" , message: '"+p+" should be boolean' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var F=n;n=b.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+F+"]; return false; ":" var err = "+F+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } else if( ",d&&(n+=" ("+u+" !== undefined && typeof "+u+" != 'number') || "),n+=" ((exclusive"+r+" = "+A+" === true) ? "+h+" "+w+"= "+u+" : "+h+" "+w+" "+u+")) { var op"+r+" = exclusive"+r+" ? '"+v+"' : '"+v+"=';"}else{var y=g===!0,E=v;y||(E+="=");var C="'"+E+"'";n+=" if ( ",d&&(n+=" ("+u+" !== undefined && typeof "+u+" != 'number') || "),n+=" "+h+" "+w,y&&(n+="="),n+=" "+u+") {"}var i=t,b=b||[];b.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_limit")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { comparison: '+C+", limit: "+u+", exclusive: "+y+" } ",e.opts.messages!==!1&&(n+=" , message: 'should be "+E+" ",n+=d?"' + "+u:""+s+"'"),e.opts.verbose&&(n+=" , schema: ",n+=d?"validate.schema"+a:""+s,n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var F=n;return n=b.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+F+"]; return false; ":" var err = "+F+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } ",c&&(n+=" else { "),n}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d=e.opts.v5&&s.$data,u=d?e.util.getData(s.$data,o,e.dataPathArr):s;d&&(n+=" var schema"+r+" = "+u+"; ",u="schema"+r);var f="maxItems"==t?">":"<";n+="if ( ",d&&(n+=" ("+u+" !== undefined && typeof "+u+" != 'number') || "),n+=" "+h+".length "+f+" "+u+") { ";var i=t,p=p||[];p.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_limitItems")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { limit: '+u+" } ",e.opts.messages!==!1&&(n+=" , message: 'should NOT have ",n+="maxItems"==t?"more":"less",n+=" than ",n+=d?"' + "+u+" + '":""+s,n+=" items' "),e.opts.verbose&&(n+=" , schema: ",n+=d?"validate.schema"+a:""+s,n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var g=n;return n=p.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+g+"]; return false; ":" var err = "+g+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="} ",c&&(n+=" else { "),n}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d=e.opts.v5&&s.$data,u=d?e.util.getData(s.$data,o,e.dataPathArr):s;d&&(n+=" var schema"+r+" = "+u+"; ",u="schema"+r);var f="maxLength"==t?">":"<";n+="if ( ",d&&(n+=" ("+u+" !== undefined && typeof "+u+" != 'number') || "),n+=e.opts.unicode===!1?" "+h+".length ":" ucs2length("+h+") ",n+=" "+f+" "+u+") { ";var i=t,p=p||[];p.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_limitLength")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { limit: '+u+" } ",e.opts.messages!==!1&&(n+=" , message: 'should NOT be ",n+="maxLength"==t?"longer":"shorter",n+=" than ",n+=d?"' + "+u+" + '":""+s,n+=" characters' "),e.opts.verbose&&(n+=" , schema: ",n+=d?"validate.schema"+a:""+s,n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var g=n;return n=p.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+g+"]; return false; ":" var err = "+g+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="} ",c&&(n+=" else { "),n}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d=e.opts.v5&&s.$data,u=d?e.util.getData(s.$data,o,e.dataPathArr):s;d&&(n+=" var schema"+r+" = "+u+"; ",u="schema"+r);var f="maxProperties"==t?">":"<";n+="if ( ",d&&(n+=" ("+u+" !== undefined && typeof "+u+" != 'number') || "),n+=" Object.keys("+h+").length "+f+" "+u+") { ";var i=t,p=p||[];p.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_limitProperties")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { limit: '+u+" } ",e.opts.messages!==!1&&(n+=" , message: 'should NOT have ",n+="maxProperties"==t?"more":"less",n+=" than ",n+=d?"' + "+u+" + '":""+s,n+=" properties' "),e.opts.verbose&&(n+=" , schema: ",n+=d?"validate.schema"+a:""+s,n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var g=n;return n=p.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+g+"]; return false; ":" var err = "+g+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="} ",c&&(n+=" else { "),n}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d=e.opts.v5&&s.$data,u=d?e.util.getData(s.$data,o,e.dataPathArr):s;d&&(n+=" var schema"+r+" = "+u+"; ",u="schema"+r),n+="var division"+r+";if (",d&&(n+=" "+u+" !== undefined && ( typeof "+u+" != 'number' || "),n+=" (division"+r+" = "+h+" / "+u+", ",n+=e.opts.multipleOfPrecision?" Math.abs(Math.round(division"+r+") - division"+r+") > 1e-"+e.opts.multipleOfPrecision+" ":" division"+r+" !== parseInt(division"+r+") ",n+=" ) ",d&&(n+=" ) "),n+=" ) { ";var f=f||[];f.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"multipleOf")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { multipleOf: '+u+" } ",e.opts.messages!==!1&&(n+=" , message: 'should be multiple of ",n+=d?"' + "+u:""+s+"'"),e.opts.verbose&&(n+=" , schema: ",n+=d?"validate.schema"+a:""+s,n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var p=n;return n=f.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+p+"]; return false; ":" var err = "+p+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="} ",c&&(n+=" else { "),n}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="errs__"+r,u=e.util.copy(e);if(u.level++,e.util.schemaHasRules(s,e.RULES.all)){u.schema=s,u.schemaPath=a,u.errSchemaPath=l,n+=" var "+d+" = errors; ";var f=e.compositeRule;e.compositeRule=u.compositeRule=!0,u.createErrors=!1,n+=" "+e.validate(u)+" ",u.createErrors=!0,e.compositeRule=u.compositeRule=f,n+=" if (valid"+u.level+") { ";var p=p||[];p.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"not")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: {} ',e.opts.messages!==!1&&(n+=" , message: 'should NOT be valid' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var g=n;n=p.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+g+"]; return false; ":" var err = "+g+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } else { errors = "+d+"; if (vErrors !== null) { if ("+d+") vErrors.length = "+d+"; else vErrors = null; } ",e.opts.allErrors&&(n+=" } ")}else n+=" var err = ",e.createErrors!==!1?(n+=" { keyword: '"+(i||"not")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: {} ',e.opts.messages!==!1&&(n+=" , message: 'should NOT be valid' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ",n+="; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",c&&(n+=" if (false) { ");return n}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u="errs__"+r,f=e.util.copy(e),p="";f.level++,n+="var "+u+" = errors;var prevValid"+r+" = false;var "+d+" = false; ";var g=e.compositeRule;e.compositeRule=f.compositeRule=!0;var m=s;if(m)for(var v,w=-1,A=m.length-1;A>w;)v=m[w+=1],e.util.schemaHasRules(v,e.RULES.all)?(f.schema=v,f.schemaPath=a+"["+w+"]",f.errSchemaPath=l+"/"+w,n+=" "+e.validate(f)+" "):n+=" var valid"+f.level+" = true; ",w&&(n+=" if (valid"+f.level+" && prevValid"+r+") "+d+" = false; else { ",p+="}"),n+=" if (valid"+f.level+") "+d+" = prevValid"+r+" = true;";e.compositeRule=f.compositeRule=g,n+=""+p+"if (!"+d+") { ";var y=y||[];y.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"oneOf")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: {} ',e.opts.messages!==!1&&(n+=" , message: 'should match exactly one schema in oneOf' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var C=n;return n=y.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+C+"]; return false; ":" var err = "+C+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="} else { errors = "+u+"; if (vErrors !== null) { if ("+u+") vErrors.length = "+u+"; else vErrors = null; }",e.opts.allErrors&&(n+=" } "),n}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d=e.opts.v5&&s.$data,u=d?e.util.getData(s.$data,o,e.dataPathArr):s;d&&(n+=" var schema"+r+" = "+u+"; ",u="schema"+r);var f=d?"(new RegExp("+u+"))":e.usePattern(s);n+="if ( ",d&&(n+=" ("+u+" !== undefined && typeof "+u+" != 'string') || "),n+=" !"+f+".test("+h+") ) { ";var p=p||[];p.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"pattern")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { pattern: ',n+=d?""+u:""+e.util.toQuotedString(s),n+=" } ",e.opts.messages!==!1&&(n+=" , message: 'should match pattern \"",n+=d?"' + "+u+" + '":""+e.util.escapeQuotes(s),n+="\"' "),e.opts.verbose&&(n+=" , schema: ",n+=d?"validate.schema"+a:""+e.util.toQuotedString(s),n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var g=n;return n=p.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+g+"]; return false; ":" var err = "+g+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="} ",c&&(n+=" else { "),n}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u="errs__"+r,f=e.util.copy(e),p="";f.level++;var g=f.dataLevel=e.dataLevel+1,m="data"+g,v=Object.keys(s||{}),w=e.schema.patternProperties||{},A=Object.keys(w),y=e.schema.additionalProperties,C=v.length||A.length,E=y===!1,b="object"==typeof y&&Object.keys(y).length,F=e.opts.removeAdditional,x=E||b||F,S=e.schema.required;if(S&&(!e.opts.v5||!S.$data)&&S.length5)n+=" || validate.schema"+a+"[key"+r+"] ";else{var B=v;if(B)for(var _,L=-1,R=B.length-1;R>L;)_=B[L+=1],n+=" || key"+r+" == "+e.util.toQuotedString(_)+" "}if(A.length){var T=A;if(T)for(var P,M=-1,O=T.length-1;O>M;)P=T[M+=1],n+=" || "+e.usePattern(P)+".test(key"+r+") "}if(e.opts.v5&&k&&k.length){var I=k;if(I)for(var N,M=-1,j=I.length-1;j>M;)N=I[M+=1],n+=" || "+e.usePattern(N)+".test(key"+r+") "}n+=" ); if (isAdditional"+r+") { "}if("all"==F)n+=" delete "+h+"[key"+r+"]; ";else{var W=e.errorPath,H="' + key"+r+" + '";if(e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPathExpr(e.errorPath,"key"+r,e.opts.jsonPointers)),E)if(F)n+=" delete "+h+"[key"+r+"]; ";else{n+=" valid"+f.level+" = false; ";var V=l;l=e.errSchemaPath+"/additionalProperties";var z=z||[];z.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"additionalProperties")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { additionalProperty: '"+H+"' } ",e.opts.messages!==!1&&(n+=" , message: 'should NOT have additional properties' "),e.opts.verbose&&(n+=" , schema: false , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var U=n;n=z.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+U+"]; return false; ":" var err = "+U+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",l=V,c&&(n+=" break; ")}else if(b)if("failing"==F){n+=" var "+u+" = errors; ";var K=e.compositeRule;e.compositeRule=f.compositeRule=!0,f.schema=y,f.schemaPath=e.schemaPath+".additionalProperties",f.errSchemaPath=e.errSchemaPath+"/additionalProperties",f.errorPath=e.opts._errorDataPathProperty?e.errorPath:e.util.getPathExpr(e.errorPath,"key"+r,e.opts.jsonPointers);var G=h+"[key"+r+"]";e.opts.v5&&(f.dataPathArr[g]="key"+r);var q=e.validate(f);n+=e.util.varOccurences(q,m)<2?" "+e.util.varReplace(q,m,G)+" ":" var "+m+" = "+G+"; "+q+" ",n+=" if (!valid"+f.level+") { errors = "+u+"; if (validate.errors !== null) { if (errors) validate.errors.length = errors; else validate.errors = null; } delete "+h+"[key"+r+"]; } ",e.compositeRule=f.compositeRule=K}else{f.schema=y,f.schemaPath=e.schemaPath+".additionalProperties",f.errSchemaPath=e.errSchemaPath+"/additionalProperties",f.errorPath=e.opts._errorDataPathProperty?e.errorPath:e.util.getPathExpr(e.errorPath,"key"+r,e.opts.jsonPointers);var G=h+"[key"+r+"]";e.opts.v5&&(f.dataPathArr[g]="key"+r);var q=e.validate(f);n+=e.util.varOccurences(q,m)<2?" "+e.util.varReplace(q,m,G)+" ":" var "+m+" = "+G+"; "+q+" ",c&&(n+=" if (!valid"+f.level+") break; ")}e.errorPath=W}C&&(n+=" } "),n+=" } ",c&&(n+=" if (valid"+f.level+") { ",p+="}")}var Q=e.opts.useDefaults&&!e.compositeRule;if(v.length){var Y=v;if(Y)for(var _,J=-1,X=Y.length-1;X>J;){_=Y[J+=1];var Z=s[_];if(e.util.schemaHasRules(Z,e.RULES.all)){var ee=e.util.getProperty(_),G=h+ee,te=Q&&void 0!==Z["default"];f.schema=Z,f.schemaPath=a+ee,f.errSchemaPath=l+"/"+e.util.escapeFragment(_),f.errorPath=e.util.getPath(e.errorPath,_,e.opts.jsonPointers),e.opts.v5&&(f.dataPathArr[g]=e.util.toQuotedString(_));var q=e.validate(f);if(e.util.varOccurences(q,m)<2){q=e.util.varReplace(q,m,G);var ie=G}else{var ie=m;n+=" var "+m+" = "+G+"; "}if(te)n+=" "+q+" ";else{if($&&$[_]){n+=" if ("+ie+" === undefined) { valid"+f.level+" = false; ";var W=e.errorPath,V=l,ne=e.util.escapeQuotes(_);e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPath(W,_,e.opts.jsonPointers)),l=e.errSchemaPath+"/required";var z=z||[];z.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { missingProperty: '"+ne+"' } ",e.opts.messages!==!1&&(n+=" , message: '",n+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+ne+"\\'",n+="' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var U=n;n=z.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+U+"]; return false; ":" var err = "+U+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",l=V,e.errorPath=W,n+=" } else { "}else n+=c?" if ("+ie+" === undefined) { valid"+f.level+" = true; } else { ":" if ("+ie+" !== undefined) { ";n+=" "+q+" } "}}c&&(n+=" if (valid"+f.level+") { ",p+="}")}}var re=A;if(re)for(var P,oe=-1,se=re.length-1;se>oe;){P=re[oe+=1];var Z=w[P];if(e.util.schemaHasRules(Z,e.RULES.all)){f.schema=Z,f.schemaPath=e.schemaPath+".patternProperties"+e.util.getProperty(P),f.errSchemaPath=e.errSchemaPath+"/patternProperties/"+e.util.escapeFragment(P),n+=" for (var key"+r+" in "+h+") { if ("+e.usePattern(P)+".test(key"+r+")) { ",f.errorPath=e.util.getPathExpr(e.errorPath,"key"+r,e.opts.jsonPointers);var G=h+"[key"+r+"]";e.opts.v5&&(f.dataPathArr[g]="key"+r);var q=e.validate(f);n+=e.util.varOccurences(q,m)<2?" "+e.util.varReplace(q,m,G)+" ":" var "+m+" = "+G+"; "+q+" ",c&&(n+=" if (!valid"+f.level+") break; "),n+=" } ",c&&(n+=" else valid"+f.level+" = true; "),n+=" } ",c&&(n+=" if (valid"+f.level+") { ",p+="}")}}if(e.opts.v5){var ae=k;if(ae)for(var N,le=-1,ce=ae.length-1;ce>le;){N=ae[le+=1];var he=D[N],Z=he.schema;if(e.util.schemaHasRules(Z,e.RULES.all)){f.schema=Z,f.schemaPath=e.schemaPath+".patternGroups"+e.util.getProperty(N)+".schema",f.errSchemaPath=e.errSchemaPath+"/patternGroups/"+e.util.escapeFragment(N)+"/schema",n+=" var pgPropCount"+r+" = 0; for (var key"+r+" in "+h+") { if ("+e.usePattern(N)+".test(key"+r+")) { pgPropCount"+r+"++; ",f.errorPath=e.util.getPathExpr(e.errorPath,"key"+r,e.opts.jsonPointers);var G=h+"[key"+r+"]";e.opts.v5&&(f.dataPathArr[g]="key"+r);var q=e.validate(f);n+=e.util.varOccurences(q,m)<2?" "+e.util.varReplace(q,m,G)+" ":" var "+m+" = "+G+"; "+q+" ",c&&(n+=" if (!valid"+f.level+") break; "),n+=" } ",c&&(n+=" else valid"+f.level+" = true; "),n+=" } ",c&&(n+=" if (valid"+f.level+") { ",p+="}");var de=he.minimum,ue=he.maximum;if(void 0!==de||void 0!==ue){n+=" var "+d+" = true; ";var V=l;if(void 0!==de){var fe=de,pe="minimum",ge="less";n+=" "+d+" = pgPropCount"+r+" >= "+de+"; ",l=e.errSchemaPath+"/patternGroups/minimum",n+=" if (!"+d+") { ";var z=z||[];z.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"patternGroups")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { reason: '"+pe+"', limit: "+fe+", pattern: '"+e.util.escapeQuotes(N)+"' } ",e.opts.messages!==!1&&(n+=" , message: 'should NOT have "+ge+" than "+fe+' properties matching pattern "'+e.util.escapeQuotes(N)+"\"' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var U=n;n=z.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+U+"]; return false; ":" var err = "+U+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } ",void 0!==ue&&(n+=" else ")}if(void 0!==ue){var fe=ue,pe="maximum",ge="more";n+=" "+d+" = pgPropCount"+r+" <= "+ue+"; ",l=e.errSchemaPath+"/patternGroups/maximum",n+=" if (!"+d+") { ";var z=z||[];z.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"patternGroups")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { reason: '"+pe+"', limit: "+fe+", pattern: '"+e.util.escapeQuotes(N)+"' } ",e.opts.messages!==!1&&(n+=" , message: 'should NOT have "+ge+" than "+fe+' properties matching pattern "'+e.util.escapeQuotes(N)+"\"' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var U=n;n=z.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+U+"]; return false; ":" var err = "+U+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ", -n+=" } "}l=V,c&&(n+=" if ("+d+") { ",p+="}")}}}}return c&&(n+=" "+p+" if ("+u+" == errors) {"),n=e.util.cleanUpCode(n)}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u=e.opts.v5&&s.$data,f=u?e.util.getData(s.$data,o,e.dataPathArr):s;if(u&&(n+=" var schema"+r+" = "+f+"; ",f="schema"+r),!u)if(s.lengthv;){m=g[v+=1];var A=e.schema.properties[m];A&&e.util.schemaHasRules(A,e.RULES.all)||(p[p.length]=m)}}else var p=s;if(u||p.length){var y=e.errorPath,C=u||p.length>=e.opts.loopRequired;if(c)if(n+=" var missing"+r+"; ",C){u||(n+=" var schema"+r+" = validate.schema"+a+"; ");var E="i"+r,b="schema"+r+"["+E+"]",F="' + "+b+" + '";e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPathExpr(y,b,e.opts.jsonPointers)),n+=" var "+d+" = true; ",u&&(n+=" if (schema"+r+" === undefined) "+d+" = true; else if (!Array.isArray(schema"+r+")) "+d+" = false; else {"),n+=" for (var "+E+" = 0; "+E+" < schema"+r+".length; "+E+"++) { "+d+" = "+h+"[schema"+r+"["+E+"]] !== undefined; if (!"+d+") break; } ",u&&(n+=" } "),n+=" if (!"+d+") { ";var x=x||[];x.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { missingProperty: '"+F+"' } ",e.opts.messages!==!1&&(n+=" , message: '",n+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+F+"\\'",n+="' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var S=n;n=x.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+S+"]; return false; ":" var err = "+S+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } else { "}else{n+=" if ( ";var $=p;if($)for(var D,E=-1,k=$.length-1;k>E;){D=$[E+=1],E&&(n+=" || ");var B=e.util.getProperty(D);n+=" ( "+h+B+" === undefined && (missing"+r+" = "+e.util.toQuotedString(e.opts.jsonPointers?D:B)+") ) "}n+=") { ";var b="missing"+r,F="' + "+b+" + '";e.opts._errorDataPathProperty&&(e.errorPath=e.opts.jsonPointers?e.util.getPathExpr(y,b,!0):y+" + "+b);var x=x||[];x.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { missingProperty: '"+F+"' } ",e.opts.messages!==!1&&(n+=" , message: '",n+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+F+"\\'",n+="' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var S=n;n=x.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+S+"]; return false; ":" var err = "+S+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } else { "}else if(C){u||(n+=" var schema"+r+" = validate.schema"+a+"; ");var E="i"+r,b="schema"+r+"["+E+"]",F="' + "+b+" + '";e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPathExpr(y,b,e.opts.jsonPointers)),u&&(n+=" if (schema"+r+" && !Array.isArray(schema"+r+")) { var err = ",e.createErrors!==!1?(n+=" { keyword: '"+(i||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { missingProperty: '"+F+"' } ",e.opts.messages!==!1&&(n+=" , message: '",n+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+F+"\\'",n+="' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ",n+="; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } else if (schema"+r+" !== undefined) { "),n+=" for (var "+E+" = 0; "+E+" < schema"+r+".length; "+E+"++) { if ("+h+"[schema"+r+"["+E+"]] === undefined) { var err = ",e.createErrors!==!1?(n+=" { keyword: '"+(i||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { missingProperty: '"+F+"' } ",e.opts.messages!==!1&&(n+=" , message: '",n+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+F+"\\'",n+="' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ",n+="; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } } ",u&&(n+=" } ")}else{var _=p;if(_)for(var m,E=-1,L=_.length-1;L>E;){m=_[E+=1];var B=e.util.getProperty(m),F=e.util.escapeQuotes(m);e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPath(y,m,e.opts.jsonPointers)),n+=" if ("+h+B+" === undefined) { var err = ",e.createErrors!==!1?(n+=" { keyword: '"+(i||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { missingProperty: '"+F+"' } ",e.opts.messages!==!1&&(n+=" , message: '",n+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+F+"\\'",n+="' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ",n+="; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } "}}e.errorPath=y}else c&&(n+=" if (true) {");return n}},function(e,t,i){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u=e.opts.v5&&s.$data,f=u?e.util.getData(s.$data,o,e.dataPathArr):s;if(u&&(n+=" var schema"+r+" = "+f+"; ",f="schema"+r),(s||u)&&e.opts.uniqueItems!==!1){u&&(n+=" var "+d+"; if ("+f+" === false || "+f+" === undefined) "+d+" = true; else if (typeof "+f+" != 'boolean') "+d+" = false; else { "),n+=" var "+d+" = true; if ("+h+".length > 1) { var i = "+h+".length, j; outer: for (;i--;) { for (j = i; j--;) { if (equal("+h+"[i], "+h+"[j])) { "+d+" = false; break outer; } } } } ",u&&(n+=" } "),n+=" if (!"+d+") { ";var p=p||[];p.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"uniqueItems")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { i: i, j: j } ',e.opts.messages!==!1&&(n+=" , message: 'should NOT have duplicate items (items ## ' + j + ' and ' + i + ' are identical)' "),e.opts.verbose&&(n+=" , schema: ",n+=u?"validate.schema"+a:""+s,n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var g=n;n=p.pop(),n+=!e.compositeRule&&c?" validate.errors = ["+g+"]; return false; ":" var err = "+g+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } ",c&&(n+=" else { ")}else c&&(n+=" if (true) { ");return n}},function(e,t,i){e.exports=function(){throw new Error("define cannot be used indirect")}},function(e,t,i){(function(t){function i(){if(t.Blob)try{return new Blob(["asdf"],{type:"text/plain"}),Blob}catch(e){}var i=t.WebKitBlobBuilder||t.MozBlobBuilder||t.MSBlobBuilder;return function(e,t){var n=new i,r=t.endings,o=t.type;if(r)for(var s=0,a=e.length;a>s;++s)n.append(e[s],r);else for(var s=0,a=e.length;a>s;++s)n.append(e[s]);return o?n.getBlob(o):n.getBlob()}}e.exports=i()}).call(t,function(){return this}())},function(e,t,i){var n,r,o,s,a={'"':'"',"\\":"\\","/":"/",b:"\b",f:"\f",n:"\n",r:"\r",t:" "},l=function(e){throw{name:"SyntaxError",message:e,at:n,text:o}},c=function(e){return e&&e!==r&&l("Expected '"+e+"' instead of '"+r+"'"),r=o.charAt(n),n+=1,r},h=function(){var e,t="";for("-"===r&&(t="-",c("-"));r>="0"&&"9">=r;)t+=r,c();if("."===r)for(t+=".";c()&&r>="0"&&"9">=r;)t+=r;if("e"===r||"E"===r)for(t+=r,c(),("-"===r||"+"===r)&&(t+=r,c());r>="0"&&"9">=r;)t+=r,c();return e=+t,isFinite(e)?e:void l("Bad number")},d=function(){var e,t,i,n="";if('"'===r)for(;c();){if('"'===r)return c(),n;if("\\"===r)if(c(),"u"===r){for(i=0,t=0;4>t&&(e=parseInt(c(),16),isFinite(e));t+=1)i=16*i+e;n+=String.fromCharCode(i)}else{if("string"!=typeof a[r])break;n+=a[r]}else n+=r}l("Bad string")},u=function(){for(;r&&" ">=r;)c()},f=function(){switch(r){case"t":return c("t"),c("r"),c("u"),c("e"),!0;case"f":return c("f"),c("a"),c("l"),c("s"),c("e"),!1;case"n":return c("n"),c("u"),c("l"),c("l"),null}l("Unexpected '"+r+"'")},p=function(){var e=[];if("["===r){if(c("["),u(),"]"===r)return c("]"),e;for(;r;){if(e.push(s()),u(),"]"===r)return c("]"),e;c(","),u()}}l("Bad array")},g=function(){var e,t={};if("{"===r){if(c("{"),u(),"}"===r)return c("}"),t;for(;r;){if(e=d(),u(),c(":"),Object.hasOwnProperty.call(t,e)&&l('Duplicate key "'+e+'"'),t[e]=s(),u(),"}"===r)return c("}"),t;c(","),u()}}l("Bad object")};s=function(){switch(u(),r){case"{":return g();case"[":return p();case'"':return d();case"-":return h();default:return r>="0"&&"9">=r?h():f()}},e.exports=function(e,t){var i;return o=e,n=0,r=" ",i=s(),u(),r&&l("Syntax error"),"function"==typeof t?function a(e,i){var n,r,o=e[i];if(o&&"object"==typeof o)for(n in o)Object.prototype.hasOwnProperty.call(o,n)&&(r=a(o,n),void 0!==r?o[n]=r:delete o[n]);return t.call(e,i,o)}({"":i},""):i}},function(e,t,i){function n(e){return l.lastIndex=0,l.test(e)?'"'+e.replace(l,function(e){var t=c[e];return"string"==typeof t?t:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function r(e,t){var i,l,c,h,d,u=o,f=t[e];switch(f&&"object"==typeof f&&"function"==typeof f.toJSON&&(f=f.toJSON(e)),"function"==typeof a&&(f=a.call(t,e,f)),typeof f){case"string":return n(f);case"number":return isFinite(f)?String(f):"null";case"boolean":case"null":return String(f);case"object":if(!f)return"null";if(o+=s,d=[],"[object Array]"===Object.prototype.toString.apply(f)){for(h=f.length,i=0;h>i;i+=1)d[i]=r(i,f)||"null";return c=0===d.length?"[]":o?"[\n"+o+d.join(",\n"+o)+"\n"+u+"]":"["+d.join(",")+"]",o=u,c}if(a&&"object"==typeof a)for(h=a.length,i=0;h>i;i+=1)l=a[i],"string"==typeof l&&(c=r(l,f),c&&d.push(n(l)+(o?": ":":")+c));else for(l in f)Object.prototype.hasOwnProperty.call(f,l)&&(c=r(l,f),c&&d.push(n(l)+(o?": ":":")+c));return c=0===d.length?"{}":o?"{\n"+o+d.join(",\n"+o)+"\n"+u+"}":"{"+d.join(",")+"}",o=u,c}}var o,s,a,l=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,c={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};e.exports=function(e,t,i){var n;if(o="",s="","number"==typeof i)for(n=0;i>n;n+=1)s+=" ";else"string"==typeof i&&(s=i);if(a=t,t&&"function"!=typeof t&&("object"!=typeof t||"number"!=typeof t.length))throw new Error("JSON.stringify");return r("",{"":e})}},function(e,t,i){var n;(function(e,r){!function(o){function s(e){throw RangeError(L[e])}function a(e,t){for(var i=e.length,n=[];i--;)n[i]=t(e[i]);return n}function l(e,t){var i=e.split("@"),n="";i.length>1&&(n=i[0]+"@",e=i[1]),e=e.replace(_,".");var r=e.split("."),o=a(r,t).join(".");return n+o}function c(e){for(var t,i,n=[],r=0,o=e.length;o>r;)t=e.charCodeAt(r++),t>=55296&&56319>=t&&o>r?(i=e.charCodeAt(r++),56320==(64512&i)?n.push(((1023&t)<<10)+(1023&i)+65536):(n.push(t),r--)):n.push(t);return n}function h(e){return a(e,function(e){var t="";return e>65535&&(e-=65536,t+=P(e>>>10&1023|55296),e=56320|1023&e),t+=P(e)}).join("")}function d(e){return 10>e-48?e-22:26>e-65?e-65:26>e-97?e-97:C}function u(e,t){return e+22+75*(26>e)-((0!=t)<<5)}function f(e,t,i){var n=0;for(e=i?T(e/x):e>>1,e+=T(e/t);e>R*b>>1;n+=C)e=T(e/R);return T(n+(R+1)*e/(e+F))}function p(e){var t,i,n,r,o,a,l,c,u,p,g=[],m=e.length,v=0,w=$,A=S;for(i=e.lastIndexOf(D),0>i&&(i=0),n=0;i>n;++n)e.charCodeAt(n)>=128&&s("not-basic"),g.push(e.charCodeAt(n));for(r=i>0?i+1:0;m>r;){for(o=v,a=1,l=C;r>=m&&s("invalid-input"),c=d(e.charCodeAt(r++)),(c>=C||c>T((y-v)/a))&&s("overflow"),v+=c*a,u=A>=l?E:l>=A+b?b:l-A,!(u>c);l+=C)p=C-u,a>T(y/p)&&s("overflow"),a*=p;t=g.length+1,A=f(v-o,t,0==o),T(v/t)>y-w&&s("overflow"),w+=T(v/t),v%=t,g.splice(v++,0,w)}return h(g)}function g(e){var t,i,n,r,o,a,l,h,d,p,g,m,v,w,A,F=[];for(e=c(e),m=e.length,t=$,i=0,o=S,a=0;m>a;++a)g=e[a],128>g&&F.push(P(g));for(n=r=F.length,r&&F.push(D);m>n;){for(l=y,a=0;m>a;++a)g=e[a],g>=t&&l>g&&(l=g);for(v=n+1,l-t>T((y-i)/v)&&s("overflow"),i+=(l-t)*v,t=l,a=0;m>a;++a)if(g=e[a],t>g&&++i>y&&s("overflow"),g==t){for(h=i,d=C;p=o>=d?E:d>=o+b?b:d-o,!(p>h);d+=C)A=h-p,w=C-p,F.push(P(u(p+A%w,0))),h=T(A/w);F.push(P(u(h,0))),o=f(i,v,n==r),i=0,++n}++i,++t}return F.join("")}function m(e){return l(e,function(e){return k.test(e)?p(e.slice(4).toLowerCase()):e})}function v(e){return l(e,function(e){return B.test(e)?"xn--"+g(e):e})}var w=("object"==typeof t&&t&&!t.nodeType&&t,"object"==typeof e&&e&&!e.nodeType&&e,"object"==typeof r&&r);(w.global===w||w.window===w||w.self===w)&&(o=w);var A,y=2147483647,C=36,E=1,b=26,F=38,x=700,S=72,$=128,D="-",k=/^xn--/,B=/[^\x20-\x7E]/,_=/[\x2E\u3002\uFF0E\uFF61]/g,L={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},R=C-E,T=Math.floor,P=String.fromCharCode;A={version:"1.3.2",ucs2:{decode:c,encode:h},decode:p,encode:g,toASCII:v,toUnicode:m},n=function(){return A}.call(t,i,t,e),!(void 0!==n&&(e.exports=n))}(this)}).call(t,i(64)(e),function(){return this}())},function(e,t,i){"use strict";t.decode=t.parse=i(65),t.encode=t.stringify=i(66)},function(e,t,i){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children=[],e.webpackPolyfill=1),e}},function(e,t,i){"use strict";function n(e,t){return Object.prototype.hasOwnProperty.call(e,t)}e.exports=function(e,t,i,r){t=t||"&",i=i||"=";var o={};if("string"!=typeof e||0===e.length)return o;var s=/\+/g;e=e.split(t);var a=1e3;r&&"number"==typeof r.maxKeys&&(a=r.maxKeys);var l=e.length;a>0&&l>a&&(l=a);for(var c=0;l>c;++c){var h,d,u,f,p=e[c].replace(s,"%20"),g=p.indexOf(i);g>=0?(h=p.substr(0,g),d=p.substr(g+1)):(h=p,d=""),u=decodeURIComponent(h),f=decodeURIComponent(d),n(o,u)?Array.isArray(o[u])?o[u].push(f):o[u]=[o[u],f]:o[u]=f}return o}},function(e,t,i){"use strict";var n=function(e){switch(typeof e){case"string":return e;case"boolean":return e?"true":"false";case"number":return isFinite(e)?e:"";default:return""}};e.exports=function(e,t,i,r){return t=t||"&",i=i||"=",null===e&&(e=void 0),"object"==typeof e?Object.keys(e).map(function(r){var o=encodeURIComponent(n(r))+i;return Array.isArray(e[r])?e[r].map(function(e){return o+encodeURIComponent(n(e))}).join(t):o+encodeURIComponent(n(e[r]))}).join(t):r?encodeURIComponent(n(r))+i+encodeURIComponent(n(e)):""}}])}); -//# sourceMappingURL=jsoneditor.map \ No newline at end of file diff --git a/out/platform.js b/out/platform.js index c51526d..daaf50d 100644 --- a/out/platform.js +++ b/out/platform.js @@ -88,12 +88,12 @@ InfinniUI.ScrollVisibility = { //####app/elements/stackPanel/enums/stackPanelOrientation.js -InfinniUI.StackPanelOrientation = { - horizontal: 'Horizontal', - vertical: 'Vertical' -}; - - +InfinniUI.StackPanelOrientation = { + horizontal: 'Horizontal', + vertical: 'Vertical' +}; + + //####app/elements/tabPanel/enums/tabHeaderLocation.js InfinniUI.TabHeaderLocation = { @@ -116,14624 +116,11506 @@ _.defaults( InfinniUI.config, { cacheMetadata: false, //boolean - enable/disable cache | milliseconds serverUrl: 'http://localhost:9900',//'http://10.0.0.32:9900'; configName: 'InfinniUI' -//devblockstart - ,editorService: { - url: 'http://localhost:5500/api/metadata' - } -//devblockstop - }); -//####app/utils/collection/collection.js -/** - * - * @param {Array} items - * @param {string} [idProperty] - * @param {function} [comparator] - * @constructor - */ -function Collection (items, idProperty, comparator) { - if (!Array.isArray(items)) { - items = []; - } - - /** - * @type {Array.} - * @protected - */ - this._items = items.map(function (value, index) { - return this.createCollectionItem(value, index); - }, this); - - /** - * @type {string|null} - * @protected - */ - this._idProperty = idProperty; - - /** - * @type {function} - * @protected - */ - this._comparator = comparator || defaultComparator; - function defaultComparator (a, b) { - if (a < b) { - return -1; - } else if (a > b) { - return 1; - } - return 0; - } +InfinniUI.VERSION = '2.1.60'; - /** - * - * @type {CollectionEventManager} - */ - this.events = new CollectionEventManager(); +//####app/localizations/culture.js +function Culture(name){ + this.name = name; + this.caption = InfinniUI.localizations[name].caption; + this.dateTimeFormatInfo = InfinniUI.localizations[name].dateTimeFormatInfo; + this.numberFormatInfo = InfinniUI.localizations[name].numberFormatInfo; } -window.InfinniUI.Collection = Collection; - +window.InfinniUI.global.culture = new Culture(InfinniUI.config.lang); +window.InfinniUI.Culture = Culture; -Object.defineProperties(Collection.prototype, /** @lends Collection.prototype */{ - /** - * @type {string|null} - */ - idProperty: { - get: function () { - return this._idProperty; - }, - enumerable: false - }, - /** - * @type {function} - */ - comparator: { - get: function () { - return this._comparator; - }, - enumerable: false - }, - /** - * @type {number} - */ - length: { - get: function () { - return this._items.length; - }, - enumerable: false - }, - /** - * @type {boolean} - */ - hasIdProperty: { - get: function () { - return typeof this._idProperty !== 'undefined'; - }, - enumerable: false - } -}); +//####app/localizations/dateTimeFormatInfo.js +InfinniUI.localizations['ru-RU'].dateTimeFormatInfo = { + monthNames: [ "Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь" ], + abbreviatedMonthNames: ["янв","фев","мар","апр","май","июн","июл","авг","сен","окт","ноя","дек"], + dayNames: [ "воскресенье","понедельник","вторник","среда","четверг","пятница","суббота" ], + abbreviatedDayNames: [ "Вс","Пн","Вт","Ср","Чт","Пт","Сб" ], + dateSeparator: '.', + timeSeparator: ':', + amDesignator: '', + pmDesignator: '', + firstDayOfWeek: 1 +}; + +InfinniUI.localizations['en-US'].dateTimeFormatInfo = { + monthNames: [ "January","February","March","April","May","June","July","August","September","October","November","December" ], + abbreviatedMonthNames: ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"], + dayNames: ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"], + abbreviatedDayNames: ["Sun", "Mon","Tue","Wed","Thu","Fri","Sat"], + dateSeparator: '/', + timeSeparator: ':', + amDesignator: 'AM', + pmDesignator: 'PM', + firstDayOfWeek: 0 +}; +//####app/localizations/localized.js +var localized = InfinniUI.localizations [InfinniUI.config.lang]; -/** - * - * @param {number} index - * @param {string} propertyName - * @param {*} value - * @returns {Collection} - */ -Collection.prototype.setProperty = function (index, propertyName, value) { - var item = this._items[index]; +InfinniUI.localized = localized; +//####app/localizations/numberFormatInfo.js +InfinniUI.localizations['ru-RU'].numberFormatInfo = { + numberDecimalDigits: 2, + numberDecimalSeparator: ',', + numberGroupSeparator: ' ', + numberNegativePattern: '-n', + numberPositivePattern: 'n', - if (item) { - item[propertyName] = value; - } - return this; -}; + percentDecimalDigits: 2, + percentDecimalSeparator: ',', + percentGroupSeparator: ' ', + percentSymbol: '%', + percentNegativePattern: '-p%', + percentPositivePattern: 'p%', -/** - * - * @param {number} index - * @param {string} propertyName - * @returns {*} - */ -Collection.prototype.getProperty = function (index, propertyName) { - var item = this._items[index]; + currencyDecimalDigits: 2, + currencyDecimalSeparator: ',', + currencyGroupSeparator: ' ', + currencySymbol: 'р.', + currencyNegativePattern: '-c$', + currencyPositivePattern: 'c$', - if (item) { - return item[propertyName]; - } + negativeInfinitySymbol: '-бесконечность', + positiveInfinitySymbol: 'бесконечность', + NaNSymbol: 'NaN' }; -/** - * @description Возвращает количество элементов в коллекции - * @returns {number} Количество элементов в коллекции - */ -Collection.prototype.size = function () { - return this.length; -}; +InfinniUI.localizations['en-US'].numberFormatInfo = { + numberDecimalDigits: 2, + numberDecimalSeparator: '.', + numberGroupSeparator: ',', + numberNegativePattern: '-n', + numberPositivePattern: 'n', -/** - * @description Добавляет элемент в конец коллекции - * @param {*} value - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.push = function (value) { - var items = this._items; - var item = this.createCollectionItem(value, items.length); + percentDecimalDigits: 2, + percentDecimalSeparator: '.', + percentGroupSeparator: ',', + percentSymbol: '%', + percentNegativePattern: '-p %', + percentPositivePattern: 'p %', - items.push(item); + currencyDecimalDigits: 2, + currencyDecimalSeparator: '.', + currencyGroupSeparator: ',', + currencySymbol: '$', + currencyNegativePattern: '($c)', + currencyPositivePattern: '$c', - this.events.onAdd([value]); - return true; + negativeInfinitySymbol: '-Infinity', + positiveInfinitySymbol: 'Infinity', + NaNSymbol: 'NaN' }; +//####app/localizations/patternDateFormats.js +InfinniUI.localizations['ru-RU'].patternDateFormats = { + f: 'dd MMMM yyyy г. HH:mm', + F: 'dd MMMM yyyy г. HH:mm:ss', -/** - * @description Добавляет элемент в конец коллекции. @see {@link Collection.push} - */ -Collection.prototype.add = Collection.prototype.push; + g: 'dd.MM.yyyy HH:mm', + G: 'dd.MM.yyyy HH:mm:ss', -/** - * @description Добавляет элементы в конец коллекции - * @param {Array} values - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.addAll = function (values) { - if (!Array.isArray(values)) { - return false; - } + d: 'dd.MM.yyyy', + D: 'dd MMMM yyyy г.', - var items = this._items; - var changed = values.length > 0; + t: 'H:mm', + T: 'HH:mm:ss', - values.forEach(function (value) { - var item = this.createCollectionItem(value, items.length); - items.push(item); - }, this); + y: 'MMMM yyyy', Y: 'MMMM yyyy', + m: 'MMMM dd', M: 'MMMM dd', - if (changed) { - this.events.onAdd(values); - } - return changed; + s: 'yyyy-MM-ddTHH:mm:ss', + u: 'yyyy-MM-dd HH:mm:ssZ' }; -/** - * @description Вставляет элемент в указанную позицию коллекции - * @param {number} index - * @param {*} newItem - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.insert = function (index, newItem) { - var item = this.createCollectionItem(newItem, index); - this._items.splice(index, 0, item); +InfinniUI.localizations['en-US'].patternDateFormats = { + f: 'dddd, MMMM dd, yyyy h:%m tt', + F: 'dddd, MMMM dd, yyyy h:%m:%s tt', - this.events.onAdd([newItem], index); - return true; -}; + // TODO: Изменен формат для корректного отображения в DateTimePicker (UI-2453) + g: 'M/%d/yyyy h:%m tt', + G: 'M/%d/yyyy h:%m:%s tt', -/** - * - * @param {number} index - * @param {Array} newItems - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.insertAll = function (index, newItems) { - if (!Array.isArray(newItems)) { - return false; - } + d: 'M/%d/yyyy', + D: 'dddd, MMMM dd, yyyy', - var items = this._items; - var changed = newItems.length > 0; + t: 'h:%m tt', + T: 'h:%m:%s tt', - newItems.forEach(function(value, i) { - var start = index + i; - var item = this.createCollectionItem(value, start); - items.splice(start, 0, item); - }, this); + y: 'MMMM, yyyy', Y: 'MMMM, yyyy', + m: 'MMMM dd', M: 'MMMM dd', - if (changed) { - this.events.onAdd(newItems, index); + s: 'yyyy-MM-ddTHH:mm:ss', + u: 'yyyy-MM-dd HH:mm:ssZ' +}; +//####app/localizations/stringResources.js +InfinniUI.localizations['ru-RU'].strings = { + ImageBox: { + chooseImage: 'Выбрать изображение', + imageSizeTooBig: 'Размер выбранного файла {chosen-size}Мб больше допустимого размера {permitted-size}Мб', + incorrectFormat: 'Загрузка данного типа файла не разрешена' + }, + FileBox: { + noFile: 'Файл не выбран...', + fileSizeTooBig: 'Размер выбранного файла {chosen-size}Мб больше допустимого размера {permitted-size}Мб', + incorrectFormat: 'Загрузка данного типа файла не разрешена' + }, + DateTimePicker: { + time: 'Время', + clear: 'Очистить', + today: 'Сегодня', + date: 'Дата' } - return changed; }; -/** - * @description Устанавливает список элементов коллекции - * @param {Array} newItems - * @return {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.reset = function (newItems) { - var changed, items; - - if (!Array.isArray(newItems)) { - return false; +InfinniUI.localizations['en-US'].strings = { + ImageBox: { + chooseImage: 'Choose photo', + imageSizeTooBig: 'Size of the chosen file {chosen-size}MB is more than allowed {permitted-size}MB', + incorrectFormat: 'Uploading of this file type is forbidden' + }, + FileBox: { + noFile: 'Choose file...', + fileSizeTooBig: 'Size of the chosen file {chosen-size}MB is more than allowed {permitted-size}MB', + incorrectFormat: 'Uploading of this file type is forbidden' + }, + DateTimePicker: { + time: 'Time', + clear: 'Clear', + today: 'Today', + date: 'Date' } +}; +//####app/utils/collection/collection.js +/** + * + * @param {Array} items + * @param {string} [idProperty] + * @param {function} [comparator] + * @constructor + */ +function Collection (items, idProperty, comparator) { + if (!Array.isArray(items)) { + items = []; + } + + /** + * @type {Array.} + * @protected + */ + this._items = items.map(function (value, index) { + return this.createCollectionItem(value, index); + }, this); + + /** + * @type {string|null} + * @protected + */ + this._idProperty = idProperty; + + /** + * @type {function} + * @protected + */ + this._comparator = comparator || defaultComparator; + + function defaultComparator (a, b) { + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } + return 0; + } + + /** + * + * @type {CollectionEventManager} + */ + this.events = new CollectionEventManager(); +} + +window.InfinniUI.Collection = Collection; + + +Object.defineProperties(Collection.prototype, /** @lends Collection.prototype */{ + /** + * @type {string|null} + */ + idProperty: { + get: function () { + return this._idProperty; + }, + enumerable: false + }, + /** + * @type {function} + */ + comparator: { + get: function () { + return this._comparator; + }, + enumerable: false + }, + /** + * @type {number} + */ + length: { + get: function () { + return this._items.length; + }, + enumerable: false + }, + /** + * @type {boolean} + */ + hasIdProperty: { + get: function () { + return typeof this._idProperty !== 'undefined'; + }, + enumerable: false + } +}); + +/** + * + * @param {number} index + * @param {string} propertyName + * @param {*} value + * @returns {Collection} + */ +Collection.prototype.setProperty = function (index, propertyName, value) { + var item = this._items[index]; + + if (item) { + item[propertyName] = value; + } + return this; +}; + +/** + * + * @param {number} index + * @param {string} propertyName + * @returns {*} + */ +Collection.prototype.getProperty = function (index, propertyName) { + var item = this._items[index]; + + if (item) { + return item[propertyName]; + } +}; + +/** + * @description Возвращает количество элементов в коллекции + * @returns {number} Количество элементов в коллекции + */ +Collection.prototype.size = function () { + return this.length; +}; + +/** + * @description Добавляет элемент в конец коллекции + * @param {*} value + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.push = function (value) { + var items = this._items; + var item = this.createCollectionItem(value, items.length); + + items.push(item); + + this.events.onAdd([value]); + return true; +}; + +/** + * @description Добавляет элемент в конец коллекции. @see {@link Collection.push} + */ +Collection.prototype.add = Collection.prototype.push; + +/** + * @description Добавляет элементы в конец коллекции + * @param {Array} values + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.addAll = function (values) { + if (!Array.isArray(values)) { + return false; + } + + var items = this._items; + var changed = values.length > 0; + + values.forEach(function (value) { + var item = this.createCollectionItem(value, items.length); + items.push(item); + }, this); + + if (changed) { + this.events.onAdd(values); + } + return changed; +}; + +/** + * @description Вставляет элемент в указанную позицию коллекции + * @param {number} index + * @param {*} newItem + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.insert = function (index, newItem) { + var item = this.createCollectionItem(newItem, index); + this._items.splice(index, 0, item); + + this.events.onAdd([newItem], index); + return true; +}; + +/** + * + * @param {number} index + * @param {Array} newItems + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.insertAll = function (index, newItems) { + if (!Array.isArray(newItems)) { + return false; + } + + var items = this._items; + var changed = newItems.length > 0; + + newItems.forEach(function(value, i) { + var start = index + i; + var item = this.createCollectionItem(value, start); + items.splice(start, 0, item); + }, this); + + if (changed) { + this.events.onAdd(newItems, index); + } + return changed; +}; + +/** + * @description Устанавливает список элементов коллекции + * @param {Array} newItems + * @return {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.reset = function (newItems) { + var changed, items; + + if (!Array.isArray(newItems)) { + return false; + } + + changed = this._items.length !== newItems.length; + + items = newItems.map(function (value, index) { + if (!changed) { + changed = !this.isEqual(value, this.getCollectionItemValue(index)); + } + return this.createCollectionItem(value, index); + + }, this); + + this._items.length = 0; + + Array.prototype.push.apply(this._items, items); + if (changed) { + this.events.onReset(); + } + return changed; +}; + + +/** + * @description Заменяет элемент коллекции на указанный + * @param {Array} newItems + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.set = function (newItems, silent) { + var items = this._items; + + if (!Array.isArray(newItems)) { + return false; + } + + var changed = items.length !== newItems.length; + var _newItems = newItems.slice(); + var matched, i = 0; + var itemValue, newValue = null, newValueIndex; + + + + _newItems.forEach(function(newItem, index){ + if (index < items.length) { + //Изменение элементов + if (!changed) { + changed = !this.isEqual(this.getCollectionItemValue(index), _newItems[index]); + } + if (changed) { + this.updateCollectionItem(items[index], newItem); + } + } else { + //Новые элементы + changed = true; + items.push(this.createCollectionItem(newItem, items.length)); + } + }, this); + + if (newItems.length < items.length) { + items.splice(newItems.length) + } + + if (changed && !silent) { + this.events.onReset(); + } + return changed; +}; + +/** + * @description Заменяет элемент коллекции на указанный. + * @param {*} oldItem + * @param {*} newItem + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.replace = function (oldItem, newItem) { + var itemValue; + var changed = false; + for (var i = 0; i < this._items.length; i = i + 1) { + itemValue = this.getCollectionItemValue(i); + if (this.isEqual(oldItem, itemValue)) { + this.updateCollectionItem(this._items[i], newItem); + changed = true; + break; + } + } + + if (changed) { + this.events.onReplace([oldItem], [newItem]); + } + return changed; +}; + +/** + * @description Удаляет последний элемент из коллекции + * @returns {*|undefined} Возвращает последний элемент коллекции, который был удален + */ +Collection.prototype.pop = function () { + if (this._items.length === 0) { + return; + } + + var itemValue = this.getCollectionItemValue(this.length - 1); + this._items.pop(); + this.events.onRemove([itemValue], this._items.length); + return itemValue; +}; + +/** + * @description Удаляет указанный элемент из коллекции + * @param {*} item + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.remove = function (item) { + var itemValue; + var itemIndex; + + var changed = true; + for (var i = 0; i < this._items.length; i = i + 1) { + itemValue = this.getCollectionItemValue(i); + itemIndex = i; + if (this.isEqual(item, itemValue)) { + this._items.splice(i, 1); + changed = true; + break; + } + } + + if (changed) { + this.events.onRemove([item], itemIndex); + } + return changed; +}; + +/** + * @description Удаляет элемент с указанным идентификатором из коллекции + * @param {number|string} id + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.removeById = function (id) { + if (!this.hasIdProperty) { + return false; + } + + var itemValue; + var itemIndex; + + var changed = true; + for (var i = 0; i < this._items.length; i = i + 1) { + itemValue = this.getCollectionItemValue(i); + itemIndex = i; + if (this.getValueId(itemValue) === id) { + this._items.splice(i, 1); + changed = true; + break; + } + } + + if (changed) { + this.events.onRemove([itemValue], itemIndex); + } + return changed; +}; + +/** + * @description Удаляет элемент с указанным индексом из коллекции + * @param {number} index + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.removeAt = function (index) { + if (index >= this._items.length) { + return false; + } + + var item = this.getCollectionItemValue(index); + this._items.splice(index, 1); + + this.events.onRemove([item], index); + return true; +}; + + +/** + * @description Удаляет указанные элементы из коллекции + * @param {Array} items + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.removeAll = function (items) { + if (!Array.isArray(items)) { + return false; + } + + var collectionItems = this._items; + var deletedItems = []; + var changed; + + items.forEach(function (value) { + + deletedItems = collectionItems.filter(function (item) { + return this.isEqual(value, this.getItemValue(item)); + }, this); + + deletedItems.forEach(function (item) { + var index = collectionItems.indexOf(item); + collectionItems.splice(index, 1); + }); + }, this); + + changed = deletedItems.length > 0; + + if (changed) { + var values = deletedItems.map(function (item) { + return this.getItemValue(item); + }, this); + //@TODO Добавить параметр oldStartingIndex для события + this.events.onRemove(values); + } + return changed; +}; + + +/** + * @description Удаляет диапазон элементов из коллекции + * @param {number} fromIndex + * @param {number} [count] + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.removeRange = function (fromIndex, count) { + var items = this._items; + var changed; + + if (fromIndex >= items.length) { + return false; + } + + if (typeof count === 'undefined') { + count = items.length - fromIndex; + } + + var deletedItems = items.splice(fromIndex, count); + changed = deletedItems.length > 0; + + if (changed) { + var values = deletedItems.map(function (item) { + return this.getItemValue(item); + }, this); + + this.events.onRemove(values, fromIndex); + } + return changed; +}; + + +/** + * @description Удаляет все элементы из коллекции, удовлетворяющие указанному условию + * @param {function} predicate + * @param [thisArg] + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.removeEvery = function (predicate, thisArg) { + if (typeof predicate !== 'function') { + return false; + } + + var items = this._items; + var changed; + var deletedItems = items.filter(function (item, index) { + var itemValue = this.getItemValue(item); + return predicate.call(thisArg, itemValue, index, this); + }, this); + + deletedItems.forEach(function (deletedItem) { + var index = items.indexOf(deletedItem); + items.splice(index, 1); + }); + + changed = deletedItems.length > 0; + if (changed) { + var values = deletedItems.map(function (item) { + return this.getItemValue(item); + }, this); + + this.events.onRemove(values); + } + return changed; +}; + + +/** + * @description Удаляет все элементы из коллекции + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.clear = function () { + var + items = this._items, + changed = items.length > 0, + values = items.map(function (item) { + return this.getItemValue(item); + }, this); + + + items.length = 0; + + if (changed) { + this.events.onRemove(values, 0); + } + + return changed; +}; + +/** + * @description Возвращает элемент коллекции с заданным идентификатором. + * @param {number|string} id + * @returns {*|undefined} Элемент коллекции с заданным идентификатором + */ +Collection.prototype.getById = function (id) { + if (!this.hasIdProperty) { + return false; + } + + var items = this._items; + var itemValue, result; + + for (var i = 0; i < items.length; i = i + 1) { + itemValue = this.getCollectionItemValue(i); + if (this.getValueId(itemValue) === id) { + result = itemValue; + break; + } + } + + return result; +}; + +/** + * @description Возвращает элемент коллекции с заданным индексом + * @param {number} index + * @returns {*|undefined} + */ +Collection.prototype.getByIndex = function (index) { + return this.getCollectionItemValue(index); +}; + +/** + * #description Возвращает первый найденный элемент коллекции, удовлетворяющий условию + * @param {function} predicate + * @param [thisArg] + * @returns {*|undefined} Первый найденный элемент коллекции, удовлетворяющий указанному условию. + */ +Collection.prototype.find = function (predicate, thisArg) { + if (typeof predicate !== 'function') { + return false; + } + + var items = this._items; + var itemIndex; + var matched = items.some(function (item, index) { + var itemValue = this.getItemValue(item); + itemIndex = index; + return predicate.call(thisArg, itemValue, index, this); + }, this); + + if (matched) { + return this.getCollectionItemValue(itemIndex); + } +}; + +/** + * @description Возвращает индекс первого найденного элемента коллекции при поиске с начала + * @param {*} item + * @param {number} [fromIndex = 0] + * @returns {number} �?ндекс первого найденного элемента коллекции или -1, если элемент не найден + */ +Collection.prototype.indexOf = function (item, fromIndex) { + var + items = this._items, + index = -1; + + if (typeof fromIndex === 'undefined') { + fromIndex = 0; + } + + for (var i = fromIndex; i < items.length; i = i + 1) { + var itemValue = this.getItemValue(items[i]); + if (this.isEqual(item, itemValue)) { + index = i; + break; + } + } + + return index; +}; + + +/** + * @description Возвращает индекс первого найденного элемента коллекции при поиске с конца + * @param {*} item + * @param {number} [fromIndex] + * @returns {number} �?ндекс первого найденного элемента коллекции или -1, если элемент не найден + */ +Collection.prototype.lastIndexOf = function (item, fromIndex) { + var + items = this._items, + index = -1; + + if (typeof fromIndex === 'undefined') { + fromIndex = items.length - 1; + } + + if (items.length === 0 || fromIndex >= items.length) { + return -1; + } + + for (var i = fromIndex; i > 0; i = i - 1) { + var itemValue = this.getItemValue(items[i]); + if (this.isEqual(item, itemValue)) { + index = i; + break; + } + } + + return index; +}; + +/** + * @description Возвращает индекс первого найденного элемента коллекции, удовлетворяющего условию + * @param {function} predicate + * @param [thisArg] + * @returns {*} �?ндекс первого найденного элемента коллекции, удовлетворяющего указанному условию + */ +Collection.prototype.findIndex = function (predicate, thisArg) { + if (typeof predicate !== 'function') { + return false; + } + + var items = this._items; + var itemIndex = -1; + var matched = items.some(function (item, index) { + var itemValue = this.getItemValue(item); + itemIndex = index; + return predicate.call(thisArg, itemValue, index, this); + }, this); + + return matched ? itemIndex : -1; +}; + +/** + * @description Проверяет наличие указанного элемента в коллекции + * @param {*} item + * @param {number} [fromIndex = 0] + * @returns {boolean} Возвращает true, если указанный элемент содержится в коллекции, иначе - false + */ +Collection.prototype.contains = function (item, fromIndex) { + fromIndex = fromIndex || 0; + + var + found = false, + items = this._items; + + for (var i = fromIndex; i < items.length; i = i + 1) { + var itemValue = this.getItemValue(items[i]); + found = this.isEqual(itemValue, item); + if (found) { + break; + } + } + + return found; +}; + + +/** + * @description Проверяет, что каждый элемент коллекции удовлетворяет указанному условию + * @param {function} predicate + * @param [thisArg] + * @returns {boolean} Возвращает true, если каждый элемент удовлетворяют указанному условию, иначе - false + */ +Collection.prototype.every = function (predicate, thisArg) { + + if (typeof predicate !== 'function') { + return false; + } + + var items = this._items; + + return items.every(function (item, index) { + var itemValue = this.getItemValue(item); + return predicate.call(thisArg, itemValue, index, this); + }, this); +}; + + +/** + * @description Проверяет, что некоторый элемент коллекции удовлетворяет указанному условию + * @param {function} predicate + * @param [thisArg] + * @returns {boolean} Возвращает true, если есть элемент, удовлетворяющий указанному условию, иначе - false + */ +Collection.prototype.some = function (predicate, thisArg) { + if (typeof predicate !== 'function') { + return false; + } + + var items = this._items; + + return items.some(function (item, index) { + var itemValue = this.getItemValue(item); + return predicate.call(thisArg, itemValue, index, this); + }, this); +}; + +/** + * @description Перечисляет все элементы коллекции + * @param {function} callback + * @param [thisArg] + */ +Collection.prototype.forEach = function (callback, thisArg) { + if (typeof callback !== 'function') { + return; + } + + var items = this._items; + + items.forEach(function (item, index) { + var itemValue = this.getItemValue(item); + + callback.call(thisArg, itemValue, index, this); + }, this); +}; + +/** + * @description Возвращает элементы коллекции, удовлетворяющие указанному условию + * @param {function} predicate + * @param [thisArg] + * @returns {Array} + */ +Collection.prototype.filter = function (predicate, thisArg) { + if (typeof predicate !== 'function') { + return []; + } + + var items = this._items; + + return items + .filter(function (item, index) { + var itemValue = this.getItemValue(item); + return predicate.call(thisArg, itemValue, index, this); + }, this) + .map(function (item) { + return this.getItemValue(item); + }, this); +}; + +/** + * @description Возвращает указанный диапазон элементов коллекции + * @param {number} fromIndex + * @param {number} [count] + * @returns {Array} + */ +Collection.prototype.take = function (fromIndex, count) { + var items = this._items; + + if (typeof count == 'undefined') { + count = items.length; + } + + return items + .slice(fromIndex, fromIndex + count) + .map(function(item) { + return this.getItemValue(item); + }, this); +}; + +/** + * @description Возвращает массив всех элементов коллекции + * @returns {Array} Массив, содержащий все элементы коллекции + */ +Collection.prototype.toArray = function () { + return this._items.map(function (item) { + return this.getItemValue(item); + }, this); +}; + +/** + * @description Перемещает элемент коллекции в позицию с указанным индексом + * @param {number} oldIndex + * @param {number} newIndex + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.move = function (oldIndex, newIndex) { + var items = this._items, + item; + + if (oldIndex < 0 || oldIndex >= items.length || oldIndex === newIndex) { + return false; + } + + item = items.splice(oldIndex, 1).pop(); + + if (oldIndex > newIndex) { + items.splice(newIndex, 0, item); + } else { + items.splice(newIndex - 1, 0, item); + } + + var changed = items[oldIndex] !== item; + + if (changed) { + var value = this.getItemValue(item); + this.events.onMove([value], [value], oldIndex, newIndex); + } + return changed; +}; + +/** + * @description Сортирует список элементов коллекции + * @param {function} comparator + * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false + */ +Collection.prototype.sort = function (comparator) { + if (typeof comparator !== 'function') { + comparator = this._comparator; + } + + var + items = this._items, + collection = this, + _items= items.slice(), + changed = false; + + items.sort(function(item1, item2) { + return comparator(collection.getItemValue(item1), collection.getItemValue(item2)); + }); + + for (var i = 0; i < items.length; i = i + 1) { + if (items[i] !== _items[i]) { + changed = true; + break; + } + } + + if (changed) { + this.events.onReset(); + } + return changed; +}; + +/** + * @description Создает копию коллекции элементов + * @returns {Collection} Новый экземпляр коллекции элементов, который является копией исходной коллекции + */ +Collection.prototype.clone = function () { + return new this.constructor(this.toArray(), this._idProperty, this.comparator); +}; + + +Collection.prototype.onAdd = function (handler) { + this.events.on('add', handler); +}; + +Collection.prototype.onReplace = function (handler) { + this.events.on('replace', handler); +}; + +Collection.prototype.onRemove = function (handler) { + this.events.on('remove', handler); +}; + +Collection.prototype.onMove = function (handler) { + this.events.on('move', handler); +}; + +Collection.prototype.onReset = function (handler) { + this.events.on('reset', handler); +}; + +Collection.prototype.onChange = function (handler) { + this.events.on('change', handler); +}; + +Collection.prototype.toString = function () { + return this._items + .map(function (item) { + return JSON.stringify(this.getItemValue(item)); + }, this) + .join(','); +}; + +/** + * @protected + * @param value + * @returns {*} + */ +Collection.prototype.getValueId = function (value) { + if (this.hasIdProperty && typeof value !== 'undefined' && value !== null) { + return value[this._idProperty] + } +}; + +/** + * @protected + * @param value1 + * @param value2 + * @returns {boolean} + */ +Collection.prototype.isEqual = function (value1, value2) { + var idProperty = this.idProperty; + + if (this.hasIdProperty) { + if(isNotEmpty(value1, value2)) { + return value1[idProperty] === value2[idProperty]; + } else { + return false; + } + } else { + return value1 === value2; + } + + function isNotEmpty() { + var values = Array.prototype.slice.call(arguments); + return values.every(function (value) { + return typeof value !== 'undefined' && value !== null; + }); + } +}; + +/** + * @protected + * @param {*} value + * @param {number} [index] + * @returns {CollectionItem} + */ +Collection.prototype.createCollectionItem = function (value, index) { + var item = Object.create(null); + + item.__value = value; + item.__index = index; + + return item; +}; + +/** + * @protected + * @param item + * @param value + * @returns {*} + */ +Collection.prototype.updateCollectionItem = function (item, value) { + item.__value = value; + return item; +}; + +/** + * @protected + * @param {number} index + * @return {*} + */ +Collection.prototype.getCollectionItemValue = function (index) { + var item = this._items[index]; + + return this.getItemValue(item); +}; + +Collection.prototype.getItemValue = function (item) { + if (item) { + return item.__value; + } +}; + +/** + * @typedef {Object} CollectionItem + * @property {*} __value + * @property {number} __index + */ - changed = this._items.length !== newItems.length; - - items = newItems.map(function (value, index) { - if (!changed) { - changed = !this.isEqual(value, this.getCollectionItemValue(index)); - } - return this.createCollectionItem(value, index); +//####app/utils/collection/collectionEventManager.js +/** + * + * @constructor + */ +function CollectionEventManager () {} + +window.InfinniUI.CollectionEventManager = CollectionEventManager; + + +_.extend(CollectionEventManager.prototype, Backbone.Events); + + +/** + * + * @param {Array} newItems + * @param {number} [newStartingIndex] + * @returns {CollectionEventManager} + */ +CollectionEventManager.prototype.onAdd = function (newItems, newStartingIndex) { + var params = { + action: 'add', + newItems: newItems, + newStartingIndex: typeof newStartingIndex !== 'undefined' ? newStartingIndex : -1 + }; + + this.trigger('add', params); + this.trigger('change', params); + + return this; +}; + +/** + * + * @returns {CollectionEventManager} + */ +CollectionEventManager.prototype.onReset = function () { + var params = { + action: 'reset' + }; + + this.trigger('reset', params); + this.trigger('change', params); + return this; +}; + +/** + * + * @param {Array} oldItems + * @param {Array} newItems + * @returns {CollectionEventManager} + */ +CollectionEventManager.prototype.onReplace = function (oldItems, newItems) { + var params = { + action: 'replace', + oldItems: oldItems, + newItems: newItems + }; + + this.trigger('replace', params); + this.trigger('change', params); + return this; +}; + +/** + * + * @param {Array} oldItems + * @param {number} [oldStartingIndex] + * @returns {CollectionEventManager} + */ +CollectionEventManager.prototype.onRemove = function (oldItems, oldStartingIndex) { + var params = { + action: 'remove', + oldItems: oldItems, + oldStartingIndex: typeof oldStartingIndex !== 'undefined' ? oldStartingIndex : -1 + }; + + this.trigger('remove', params); + this.trigger('change', params); + return this; +}; + +/** + * + * @param {Array} oldItems + * @param {Array} newItems + * @param {number} oldStartingIndex + * @param {number} newStartingIndex + * @returns {CollectionEventManager} + */ +CollectionEventManager.prototype.onMove = function (oldItems, newItems, oldStartingIndex, newStartingIndex) { + var params = { + oldItems: oldItems, + newItems: newItems, + oldStartingIndex: oldStartingIndex, + newStartingIndex: newStartingIndex + }; + + this.trigger('move', params); + this.trigger('change', params); + return this; +}; + + + - }, this); +//####app/utils/actionOnLoseFocus.js +var ActionOnLoseFocus = function ($el, action) { + var that = this; + this.$el = $el; + this.action = action; + this.checkNeedToAction_binded = _.bind(this.checkNeedToAction, this); - this._items.length = 0; + $(document).on('mousedown', that.checkNeedToAction_binded); +}; - Array.prototype.push.apply(this._items, items); - if (changed) { - this.events.onReset(); +ActionOnLoseFocus.prototype.checkNeedToAction = function (e) { + if ($(e.target).closest(this.$el).length == 0) { + this.action(); + $(document).off('mousedown', this.checkNeedToAction_binded) } - return changed; }; +window.InfinniUI.ActionOnLoseFocus = ActionOnLoseFocus; -/** - * @description Заменяет элемент коллекции на указанный - * @param {Array} newItems - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.set = function (newItems, silent) { - var items = this._items; - - if (!Array.isArray(newItems)) { - return false; - } - - var changed = items.length !== newItems.length; - var _newItems = newItems.slice(); - var matched, i = 0; - var itemValue, newValue = null, newValueIndex; +//####app/utils/basePathOfProperty.js +function BasePathOfProperty(basePathOfProperty, baseIndex, parentBasePath ) { + if(this.isRelativeProperty(basePathOfProperty)){ + this.basePathOfProperty = parentBasePath.basePathOfProperty + this.excludeFirstChar(basePathOfProperty); + }else{ + this.basePathOfProperty = basePathOfProperty; + } - _newItems.forEach(function(newItem, index){ - if (index < items.length) { - //Изменение элементов - if (!changed) { - changed = !this.isEqual(this.getCollectionItemValue(index), _newItems[index]); - } - if (changed) { - this.updateCollectionItem(items[index], newItem); - } - } else { - //Новые элементы - changed = true; - items.push(this.createCollectionItem(newItem, items.length)); + if(!parentBasePath){ + if(baseIndex !== undefined && baseIndex !== null){ + this.indexesInParentLists = [baseIndex]; + this.basePathOfProperty += baseIndex; } - }, this); - - if (newItems.length < items.length) { - items.splice(newItems.length) - } - if (changed && !silent) { - this.events.onReset(); - } - return changed; -}; + }else{ + this.indexesInParentLists = parentBasePath.indexesInParentLists ? parentBasePath.indexesInParentLists.slice() : []; + this.indexesInParentLists.push(baseIndex); -/** - * @description Заменяет элемент коллекции на указанный. - * @param {*} oldItem - * @param {*} newItem - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.replace = function (oldItem, newItem) { - var itemValue; - var changed = false; - for (var i = 0; i < this._items.length; i = i + 1) { - itemValue = this.getCollectionItemValue(i); - if (this.isEqual(oldItem, itemValue)) { - this.updateCollectionItem(this._items[i], newItem); - changed = true; - break; - } + this.parentBasePath = parentBasePath; } - if (changed) { - this.events.onReplace([oldItem], [newItem]); - } - return changed; -}; +} -/** - * @description Удаляет последний элемент из коллекции - * @returns {*|undefined} Возвращает последний элемент коллекции, который был удален - */ -Collection.prototype.pop = function () { - if (this._items.length === 0) { - return; - } +window.InfinniUI.BasePathOfProperty = BasePathOfProperty; - var itemValue = this.getCollectionItemValue(this.length - 1); - this._items.pop(); - this.events.onRemove([itemValue], this._items.length); - return itemValue; -}; +_.extend(BasePathOfProperty.prototype, { + /*возвращает полный путь к свойству элемента в коллекции*/ + resolveProperty: function(property) { + if(property === undefined || property === null){ + property = ''; + } -/** - * @description Удаляет указанный элемент из коллекции - * @param {*} item - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.remove = function (item) { - var itemValue; - var itemIndex; - - var changed = true; - for (var i = 0; i < this._items.length; i = i + 1) { - itemValue = this.getCollectionItemValue(i); - itemIndex = i; - if (this.isEqual(item, itemValue)) { - this._items.splice(i, 1); - changed = true; - break; + if(this.isRelativeProperty(property)){ + property = this.excludeFirstChar(property); + return stringUtils.formatProperty(this.basePathOfProperty + property, this.indexesInParentLists); + }else{ + return stringUtils.formatProperty(property, this.indexesInParentLists); } - } - if (changed) { - this.events.onRemove([item], itemIndex); - } - return changed; -}; - -/** - * @description Удаляет элемент с указанным идентификатором из коллекции - * @param {number|string} id - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.removeById = function (id) { - if (!this.hasIdProperty) { - return false; - } - - var itemValue; - var itemIndex; + }, - var changed = true; - for (var i = 0; i < this._items.length; i = i + 1) { - itemValue = this.getCollectionItemValue(i); - itemIndex = i; - if (this.getValueId(itemValue) === id) { - this._items.splice(i, 1); - changed = true; - break; + /*возвращает полный путь к свойству элемента в коллекции по заданному относительному пути*/ + resolveRelativeProperty: function(relativeProperty) { + var property; + if(this.basePathOfProperty != ''){ + property = this.basePathOfProperty + '.' + relativeProperty; + }else{ + property = relativeProperty; } - } - - if (changed) { - this.events.onRemove([itemValue], itemIndex); - } - return changed; -}; - -/** - * @description Удаляет элемент с указанным индексом из коллекции - * @param {number} index - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.removeAt = function (index) { - if (index >= this._items.length) { - return false; - } + return this.resolveProperty(property); + }, - var item = this.getCollectionItemValue(index); - this._items.splice(index, 1); + /*создает BasePathOfProperty следующего уровня*/ + buildChild: function(basePathOfProperty, baseIndex){ + return new BasePathOfProperty(basePathOfProperty, baseIndex, this); + }, - this.events.onRemove([item], index); - return true; -}; + /*создает BasePathOfProperty следующего уровня с относительным путем*/ + buildRelativeChild: function(basePathOfProperty, baseIndex){ + return new BasePathOfProperty(basePathOfProperty, baseIndex, this); + }, + isRelativeProperty: function(property){ + return property.substr(0,1) == '@'; + }, -/** - * @description Удаляет указанные элементы из коллекции - * @param {Array} items - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.removeAll = function (items) { - if (!Array.isArray(items)) { - return false; + excludeFirstChar: function(str){ + return str.substr(1, str.length - 1); } +}); - var collectionItems = this._items; - var deletedItems = []; - var changed; +//####app/utils/blobUtils.js +/** + * Набор утилит для работы с BlobData объектами + **/ - items.forEach(function (value) { - deletedItems = collectionItems.filter(function (item) { - return this.isEqual(value, this.getItemValue(item)); - }, this); +window.InfinniUI.BlobUtils = (function () { - deletedItems.forEach(function (item) { - var index = collectionItems.indexOf(item); - collectionItems.splice(index, 1); - }); - }, this); + var blobUtils = { + isFileInfo: isFileInfo, + getContentId: getContentByName.bind(null, 'Id'), + getName: getContentByName.bind(null, 'Name'), + getSize: getContentByName.bind(null, 'Size'), + getTime: getContentByName.bind(null, 'Time'), + getType: getContentByName.bind(null, 'Type') + }; - changed = deletedItems.length > 0; + return blobUtils; - if (changed) { - var values = deletedItems.map(function (item) { - return this.getItemValue(item); - }, this); - //@TODO Добавить параметр oldStartingIndex для события - this.events.onRemove(values); + function isFileInfo (data) { + return data && blobUtils.getContentId(data); } - return changed; -}; + function getContentByName(name, data, defaultValue) { + return _.isObject(data) ? data[name] : defaultValue; + } -/** - * @description Удаляет диапазон элементов из коллекции - * @param {number} fromIndex - * @param {number} [count] - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.removeRange = function (fromIndex, count) { - var items = this._items; - var changed; +})(); - if (fromIndex >= items.length) { - return false; - } - if (typeof count === 'undefined') { - count = items.length - fromIndex; - } - var deletedItems = items.splice(fromIndex, count); - changed = deletedItems.length > 0; - if (changed) { - var values = deletedItems.map(function (item) { - return this.getItemValue(item); - }, this); - this.events.onRemove(values, fromIndex); +//####app/utils/clone.js +_.mixin({ + deepClone: function (value) { + if (value !== null && typeof value !== 'undefined') { + return JSON.parse(JSON.stringify(value)); + } + return value; } - return changed; -}; +}); +//####app/utils/currentView.js +var OpenedViewCollection = function () { + var list = []; -/** - * @description Удаляет все элементы из коллекции, удовлетворяющие указанному условию - * @param {function} predicate - * @param [thisArg] - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.removeEvery = function (predicate, thisArg) { - if (typeof predicate !== 'function') { - return false; - } + this.appendView = function (metadata, viewMetadata, view) { - var items = this._items; - var changed; - var deletedItems = items.filter(function (item, index) { - var itemValue = this.getItemValue(item); - return predicate.call(thisArg, itemValue, index, this); - }, this); + list.push({ + metadata:metadata, + viewMetadata: viewMetadata, + view: view + }); + }; - deletedItems.forEach(function (deletedItem) { - var index = items.indexOf(deletedItem); - items.splice(index, 1); - }); + this.removeView = function (view) { + for (var i = 0, ln = list.length; i < ln; i = i + 1) { + if (view === list[i].view) { + list.splice(i, 1); + break; + } + } + }; - changed = deletedItems.length > 0; - if (changed) { - var values = deletedItems.map(function (item) { - return this.getItemValue(item); - }, this); + this.getLastView = function () { + if (list.length === 0) { + return; + } + + return list[list.length - 1]; + }; - this.events.onRemove(values); + this.getList = function () { + return list; } - return changed; + }; +window.InfinniUI.views = new OpenedViewCollection(); -/** - * @description Удаляет все элементы из коллекции - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.clear = function () { - var - items = this._items, - changed = items.length > 0, - values = items.map(function (item) { - return this.getItemValue(item); - }, this); +//####app/utils/date.js +window.InfinniUI.DateUtils = (function () { - items.length = 0; + init(); - if (changed) { - this.events.onRemove(values, 0); - } + var _defaultTimeZone; - return changed; -}; + return { + toISO8601: toISO8601, + dateToTimestamp: dateToTimestamp, + dateToTimestampTime: dateToTimestampTime, + changeTimezoneOffset: changeTimezoneOffset, + restoreTimezoneOffset: restoreTimezoneOffset, + toDate: toDate, + createDate: createDate, + parseTimeISO8601toDate: parseTimeISO8601toDate, + parseISO8601toDate:parseISO8601toDate, + checkRangeDate: checkRangeDate, + getNearestDate: getNearestDate, + cloneDate: cloneDate, + getDefaultTimeZone: getDefaultTimezone + }; -/** - * @description Возвращает элемент коллекции с заданным идентификатором. - * @param {number|string} id - * @returns {*|undefined} Элемент коллекции с заданным идентификатором - */ -Collection.prototype.getById = function (id) { - if (!this.hasIdProperty) { - return false; + function parseISO8601toDate(value) { + if (value === null || typeof value ==='undefined') { + return value; + } + return moment(value).toDate(); } - var items = this._items; - var itemValue, result; - - for (var i = 0; i < items.length; i = i + 1) { - itemValue = this.getCollectionItemValue(i); - if (this.getValueId(itemValue) === id) { - result = itemValue; - break; + function cloneDate(date) { + if (date instanceof Date) { + return new Date(date.getTime()); } + return date; } - return result; -}; + /** + * @description Возвращает ближаешее к исходному значению из диапазона + * @param date + * @param min + * @param max + * @returns {Date} + */ + function getNearestDate(date, min, max) { + var nearest; -/** - * @description Возвращает элемент коллекции с заданным индексом - * @param {number} index - * @returns {*|undefined} - */ -Collection.prototype.getByIndex = function (index) { - return this.getCollectionItemValue(index); -}; + var mMin = moment(min || null), + mMax = moment(max || null), + mVal = moment(date); -/** - * #description Возвращает первый найденный элемент коллекции, удовлетворяющий условию - * @param {function} predicate - * @param [thisArg] - * @returns {*|undefined} Первый найденный элемент коллекции, удовлетворяющий указанному условию. - */ -Collection.prototype.find = function (predicate, thisArg) { - if (typeof predicate !== 'function') { - return false; - } - var items = this._items; - var itemIndex; - var matched = items.some(function (item, index) { - var itemValue = this.getItemValue(item); - itemIndex = index; - return predicate.call(thisArg, itemValue, index, this); - }, this); + if (mMin.isValid() && mVal.isBefore(mMin)) { + nearest = mMin.toDate(); + } else if (mMax.isValid() && mVal.isAfter(mMax)) { + nearest = mMax.toDate(); + } else { + nearest = date; + } - if (matched) { - return this.getCollectionItemValue(itemIndex); + return nearest; } -}; -/** - * @description Возвращает индекс первого найденного элемента коллекции при поиске с начала - * @param {*} item - * @param {number} [fromIndex = 0] - * @returns {number} �?ндекс первого найденного элемента коллекции или -1, если элемент не найден - */ -Collection.prototype.indexOf = function (item, fromIndex) { - var - items = this._items, - index = -1; + /** + * @description Проверяет, что дата находится в заданном диапазоне + * @param date + * @param minDate + * @param maxDate + * @param {String} precision + * @returns {boolean} + */ + function checkRangeDate(date, minDate, maxDate, precision) { + var success = true; - if (typeof fromIndex === 'undefined') { - fromIndex = 0; - } + var mMin = moment(minDate || null), + mMax = moment(maxDate || null), + mVal = moment(date); - for (var i = fromIndex; i < items.length; i = i + 1) { - var itemValue = this.getItemValue(items[i]); - if (this.isEqual(item, itemValue)) { - index = i; - break; + + if (mMin.isValid() && mMax.isValid()) { + success = mVal.isSameOrBefore(mMax, precision) && mVal.isSameOrAfter(mMin, precision); + } else if (mMin.isValid()) { + success = mVal.isSameOrAfter(mMin, precision); + } else if (mMax.isValid()) { + success = mVal.isSameOrBefore(mMax, precision); } + + return success; } - return index; -}; + function parseTimeISO8601toDate(value) { + var date; + var formats = ['HH:mm', 'HH:mm:ss', 'HH:mm:ss.SSS', 'HHmm', 'HHmmss', 'HHmmss.SSS']; + var m = moment(value, formats); + if (m.isValid()) { + date = new Date(0); + date.setHours(m.hours(), m.minute(), m.second(), m.millisecond()); + } + return date; + } + function toDate(value) { + var m = moment(value); + var date = null; -/** - * @description Возвращает индекс первого найденного элемента коллекции при поиске с конца - * @param {*} item - * @param {number} [fromIndex] - * @returns {number} �?ндекс первого найденного элемента коллекции или -1, если элемент не найден - */ -Collection.prototype.lastIndexOf = function (item, fromIndex) { - var - items = this._items, - index = -1; + if (m.isValid()) { + date = m.toDate(); + } - if (typeof fromIndex === 'undefined') { - fromIndex = items.length - 1; + return date; } - if (items.length === 0 || fromIndex >= items.length) { - return -1; - } + function changeTimezoneOffset(date, timezoneOffset) { + var newDate = date; - for (var i = fromIndex; i > 0; i = i - 1) { - var itemValue = this.getItemValue(items[i]); - if (this.isEqual(item, itemValue)) { - index = i; - break; + if (typeof timezoneOffset !== 'undefined' && date instanceof Date) { + var currentOffset = date.getTimezoneOffset(); + + if (timezoneOffset !== currentOffset) { + newDate = new Date(date.getTime() + (currentOffset - timezoneOffset) * 60 * 1000); + } } + + return newDate; } - return index; -}; + function restoreTimezoneOffset(date, timezoneOffset) { + var newDate = date; -/** - * @description Возвращает индекс первого найденного элемента коллекции, удовлетворяющего условию - * @param {function} predicate - * @param [thisArg] - * @returns {*} �?ндекс первого найденного элемента коллекции, удовлетворяющего указанному условию - */ -Collection.prototype.findIndex = function (predicate, thisArg) { - if (typeof predicate !== 'function') { - return false; - } + if (typeof timezoneOffset !== 'undefined' && date instanceof Date) { + var currentOffset = date.getTimezoneOffset(); - var items = this._items; - var itemIndex = -1; - var matched = items.some(function (item, index) { - var itemValue = this.getItemValue(item); - itemIndex = index; - return predicate.call(thisArg, itemValue, index, this); - }, this); + if (timezoneOffset !== currentOffset) { + newDate = new Date(date.getTime() - (currentOffset - timezoneOffset) * 60 * 1000); + } + } - return matched ? itemIndex : -1; -}; + return newDate; + } -/** - * @description Проверяет наличие указанного элемента в коллекции - * @param {*} item - * @param {number} [fromIndex = 0] - * @returns {boolean} Возвращает true, если указанный элемент содержится в коллекции, иначе - false - */ -Collection.prototype.contains = function (item, fromIndex) { - fromIndex = fromIndex || 0; + /** + * @description Возвращает строковое представление даты в формате YYYY-MM-DDTHH:mm:ss.sss+HH:MM + * @param {Date} date + * @param {Object} options + * @param {Number} options.timezoneOffset Смещение часового пояса относительно часового пояса UTC в минутах + * @returns {string|null} + */ + function toISO8601(date, options) { - var - found = false, - items = this._items; + var config = options || {}; - for (var i = fromIndex; i < items.length; i = i + 1) { - var itemValue = this.getItemValue(items[i]); - found = this.isEqual(itemValue, item); - if (found) { - break; + if (typeof date === 'undefined' || date === null) { + return null; } - } - - return found; -}; - -/** - * @description Проверяет, что каждый элемент коллекции удовлетворяет указанному условию - * @param {function} predicate - * @param [thisArg] - * @returns {boolean} Возвращает true, если каждый элемент удовлетворяют указанному условию, иначе - false - */ -Collection.prototype.every = function (predicate, thisArg) { + if (date.constructor !== Date) { + return null; + } - if (typeof predicate !== 'function') { - return false; - } + var _date = changeTimezoneOffset(date, config.timezoneOffset); - var items = this._items; + var datePart = [ + padInt(_date.getFullYear(), 4), + padInt(_date.getMonth() + 1, 2), + padInt(_date.getDate(), 2) + ].join('-'); - return items.every(function (item, index) { - var itemValue = this.getItemValue(item); - return predicate.call(thisArg, itemValue, index, this); - }, this); -}; + var timePart = [ + padInt(_date.getHours(), 2), + padInt(_date.getMinutes(), 2), + padInt(_date.getSeconds(), 2) + ].join(':'); + var sssPart = padInt(_date.getMilliseconds(), 3) + '0';// '000' + '0' -/** - * @description Проверяет, что некоторый элемент коллекции удовлетворяет указанному условию - * @param {function} predicate - * @param [thisArg] - * @returns {boolean} Возвращает true, если есть элемент, удовлетворяющий указанному условию, иначе - false - */ -Collection.prototype.some = function (predicate, thisArg) { - if (typeof predicate !== 'function') { - return false; - } - var items = this._items; + var timezoneOffset = config.timezoneOffset; + if (typeof timezoneOffset === 'undefined' || timezoneOffset === null) { + timezoneOffset = date.getTimezoneOffset(); + } - return items.some(function (item, index) { - var itemValue = this.getItemValue(item); - return predicate.call(thisArg, itemValue, index, this); - }, this); -}; + var tz = Math.abs(timezoneOffset); + var tzOffsetPart = Math.sign(timezoneOffset) > 0 ? '-' : '+'; + var tzPart = [ + padInt(Math.floor(tz / 60), 2), + padInt(tz % 60, 2) + ].join(':'); -/** - * @description Перечисляет все элементы коллекции - * @param {function} callback - * @param [thisArg] - */ -Collection.prototype.forEach = function (callback, thisArg) { - if (typeof callback !== 'function') { - return; + return datePart + 'T' + timePart + '.' + sssPart + tzOffsetPart + tzPart; } - var items = this._items; + /** + * @description Возвращает заданную дату как количество секунд, прошедших с 01-01-1970T00:00 по UTC + * @param {String|Date} date ISO8601 + */ + function dateToTimestamp(date) { + var _date, datetime = null; - items.forEach(function (item, index) { - var itemValue = this.getItemValue(item); + if (date && date.constructor === String) { + _date = new Date(date); + } else if (date && date.constructor === Date) { + _date = date; + } - callback.call(thisArg, itemValue, index, this); - }, this); -}; + if (_date) { + _date.setUTCHours(0, 0, 0, 0); + datetime = _date.getTime() / 1000; + } -/** - * @description Возвращает элементы коллекции, удовлетворяющие указанному условию - * @param {function} predicate - * @param [thisArg] - * @returns {Array} - */ -Collection.prototype.filter = function (predicate, thisArg) { - if (typeof predicate !== 'function') { - return []; + return datetime; } - var items = this._items; + function dateToTimestampTime(date) { + var time = null, _date, datetime; - return items - .filter(function (item, index) { - var itemValue = this.getItemValue(item); - return predicate.call(thisArg, itemValue, index, this); - }, this) - .map(function (item) { - return this.getItemValue(item); - }, this); -}; + if (date && date.constructor === String) { + _date = new Date(date); + } else if (date && date.constructor === Date) { + _date = date; + } -/** - * @description Возвращает указанный диапазон элементов коллекции - * @param {number} fromIndex - * @param {number} [count] - * @returns {Array} - */ -Collection.prototype.take = function (fromIndex, count) { - var items = this._items; + if (_date) { + datetime = new Date(0); + datetime.setUTCHours(_date.getUTCHours(), _date.getUTCMinutes(), _date.getUTCSeconds(), _date.getUTCMilliseconds()); + time = datetime.getTime() / 1000; + } - if (typeof count == 'undefined') { - count = items.length; + return time; } - return items - .slice(fromIndex, fromIndex + count) - .map(function(item) { - return this.getItemValue(item); - }, this); -}; - -/** - * @description Возвращает массив всех элементов коллекции - * @returns {Array} Массив, содержащий все элементы коллекции - */ -Collection.prototype.toArray = function () { - return this._items.map(function (item) { - return this.getItemValue(item); - }, this); -}; + function createDate(d) { + var date; -/** - * @description Перемещает элемент коллекции в позицию с указанным индексом - * @param {number} oldIndex - * @param {number} newIndex - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.move = function (oldIndex, newIndex) { - var items = this._items, - item; + if (typeof d === Date) { + date = new Date(d.getTime()); + } else if (typeof d === 'number') { + //Числовое значение интерпретируем как секунды (as unix-time)! + date = new Date(d * 1000); + } else if (typeof d === 'undefined' || d === null) { + date = null; + } else { + date = toDate(d); + } - if (oldIndex < 0 || oldIndex >= items.length || oldIndex === newIndex) { - return false; + return date; } - item = items.splice(oldIndex, 1).pop(); + function getDefaultTimezone() { + return _defaultTimeZone; + } - if (oldIndex > newIndex) { - items.splice(newIndex, 0, item); - } else { - items.splice(newIndex - 1, 0, item); + function padInt(value, size) { + var str = '' + value; + var pad = ''; + if (str.length < size) { + pad = Array(size - str.length + 1).join('0'); + } + return pad + str; } - var changed = items[oldIndex] !== item; + function init() { - if (changed) { - var value = this.getItemValue(item); - this.events.onMove([value], [value], oldIndex, newIndex); - } - return changed; -}; + var date = new Date(); + _defaultTimeZone = date.getTimezoneOffset(); -/** - * @description Сортирует список элементов коллекции - * @param {function} comparator - * @returns {boolean} Возвращает true, если коллекция была изменена, иначе - false - */ -Collection.prototype.sort = function (comparator) { - if (typeof comparator !== 'function') { - comparator = this._comparator; + if (!Math.sign) { //fix for devices not support ES6 + Math.sign = function (x) { + return x ? x < 0 ? -1 : 1 : 0; + }; + } } - var - items = this._items, - collection = this, - _items= items.slice(), - changed = false; +})(); +//####app/utils/domHelper.js +var domHelper = { - items.sort(function(item1, item2) { - return comparator(collection.getItemValue(item1), collection.getItemValue(item2)); - }); + whenReady: function(conditionFunction, onConditionFunction, n){ + var that = this; - for (var i = 0; i < items.length; i = i + 1) { - if (items[i] !== _items[i]) { - changed = true; - break; + if(n === undefined){ + n = 100; } - } - if (changed) { - this.events.onReset(); + if(!conditionFunction()){ + if(n>0){ + setTimeout( function(){ + that.whenReady(conditionFunction, onConditionFunction, n-1); + }, 510); + } + }else{ + onConditionFunction(); + } } - return changed; -}; -/** - * @description Создает копию коллекции элементов - * @returns {Collection} Новый экземпляр коллекции элементов, который является копией исходной коллекции - */ -Collection.prototype.clone = function () { - return new this.constructor(this.toArray(), this._idProperty, this.comparator); }; +//####app/utils/dot.js +/** + * Синглтон для работы с путями построенными по dot-notation + **/ -Collection.prototype.onAdd = function (handler) { - this.events.on('add', handler); -}; +window.InfinniUI.ObjectUtils = (function () { -Collection.prototype.onReplace = function (handler) { - this.events.on('replace', handler); -}; + /** + * Возвращает значение свойства. + * + * @private + * @param {*} target Исходный объект. + * @param {array} propertyPathTerms Путь к свойству объекта в виде коллекции термов. + * @returns {*} Значение свойства. + */ + function getPropertyByPath(target, propertyPathTerms) { + if (target !== null && target !== undefined + && propertyPathTerms !== null && propertyPathTerms !== undefined) { -Collection.prototype.onRemove = function (handler) { - this.events.on('remove', handler); -}; + var parent = target; + var length = propertyPathTerms.length; -Collection.prototype.onMove = function (handler) { - this.events.on('move', handler); -}; + for (var i = 0; i < length; ++i) { + if (parent !== null && parent !== undefined) { + var term = propertyPathTerms[i]; -Collection.prototype.onReset = function (handler) { - this.events.on('reset', handler); -}; + var termCollectionIndex = parseCollectionIndex(term); -Collection.prototype.onChange = function (handler) { - this.events.on('change', handler); -}; + if (termCollectionIndex >= 0) { + parent = getCollectionItem(parent, termCollectionIndex); + } + else { + parent = getObjectProperty(parent, term); + } + } + else { + return null; + } + } -Collection.prototype.toString = function () { - return this._items - .map(function (item) { - return JSON.stringify(this.getItemValue(item)); - }, this) - .join(','); -}; + return parent; + } -/** - * @protected - * @param value - * @returns {*} - */ -Collection.prototype.getValueId = function (value) { - if (this.hasIdProperty && typeof value !== 'undefined' && value !== null) { - return value[this._idProperty] + return target; } -}; - -/** - * @protected - * @param value1 - * @param value2 - * @returns {boolean} - */ -Collection.prototype.isEqual = function (value1, value2) { - var idProperty = this.idProperty; - if (this.hasIdProperty) { - if(isNotEmpty(value1, value2)) { - return value1[idProperty] === value2[idProperty]; - } else { - return false; - } - } else { - return value1 === value2; - } + /** + * Возвращает значение свойства. + * + * @private + * @param {*} target Исходный объект. + * @param {array} propertyPathTerms Путь к свойству объекта в виде коллекции термов. + * @param {*} propertyValue Значение свойства объекта. + * @returns {*} Значение свойства. + */ + function setPropertyByPath(target, propertyPathTerms, propertyValue) { + var parent = target; + var length = propertyPathTerms.length - 1; - function isNotEmpty() { - var values = Array.prototype.slice.call(arguments); - return values.every(function (value) { - return typeof value !== 'undefined' && value !== null; - }); - } -}; + var term = propertyPathTerms[0]; + var termCollectionIndex = parseCollectionIndex(term); -/** - * @protected - * @param {*} value - * @param {number} [index] - * @returns {CollectionItem} - */ -Collection.prototype.createCollectionItem = function (value, index) { - var item = Object.create(null); + for (var i = 0; i < length; ++i) { + var termValue = (termCollectionIndex >= 0) + ? getCollectionItem(parent, termCollectionIndex) + : getObjectProperty(parent, term); - item.__value = value; - item.__index = index; + var nextTerm = propertyPathTerms[i + 1]; + var nextTermCollectionIndex = parseCollectionIndex(nextTerm); - return item; -}; + if(nextTermCollectionIndex >= 0){ + if(!$.isArray(termValue)){ + termValue = []; + } -/** - * @protected - * @param item - * @param value - * @returns {*} - */ -Collection.prototype.updateCollectionItem = function (item, value) { - item.__value = value; - return item; -}; + setCollectionItem(parent, termCollectionIndex, termValue); + }else{ + if(!$.isPlainObject(termValue)){ + termValue = {}; + } -/** - * @protected - * @param {number} index - * @return {*} - */ -Collection.prototype.getCollectionItemValue = function (index) { - var item = this._items[index]; + setObjectProperty(parent, term, termValue); + } - return this.getItemValue(item); -}; + parent = termValue; + term = nextTerm; + termCollectionIndex = nextTermCollectionIndex; + } -Collection.prototype.getItemValue = function (item) { - if (item) { - return item.__value; + if (termCollectionIndex >= 0) { + setCollectionItem(parent, termCollectionIndex, propertyValue); + } + else { + setObjectProperty(parent, term, propertyValue); + } } -}; -/** - * @typedef {Object} CollectionItem - * @property {*} __value - * @property {number} __index - */ -//####app/utils/collection/collectionEventManager.js -/** - * - * @constructor - */ -function CollectionEventManager () {} + /** + * Разбивает путь к свойству, записанному в dot-notation, на термы. + * + * @private + * @param {string} propertyPath Имя свойства. + */ + function splitPropertyPath(propertyPath) { + if (_.isEmpty(propertyPath)) { + return null; + } -window.InfinniUI.CollectionEventManager = CollectionEventManager; + return propertyPath.split("."); + } + /** + * Пытается интерпретировать имя свойства, как индекс элемента коллекции. + * + * @private + * @param {string} propertyName Имя свойства. + * @returns {number} Индекс элемента коллекции или -1. + */ + function parseCollectionIndex(propertyName) { + var index = -1; -_.extend(CollectionEventManager.prototype, Backbone.Events); + if (propertyName === "$") { + index = 0; + } + else { + var tryParse = parseInt(propertyName); + if (!isNaN(tryParse)) { + index = tryParse; + } + } -/** - * - * @param {Array} newItems - * @param {number} [newStartingIndex] - * @returns {CollectionEventManager} - */ -CollectionEventManager.prototype.onAdd = function (newItems, newStartingIndex) { - var params = { - action: 'add', - newItems: newItems, - newStartingIndex: typeof newStartingIndex !== 'undefined' ? newStartingIndex : -1 - }; + return index; + } - this.trigger('add', params); - this.trigger('change', params); - return this; -}; + /** + * Возвращает элемент коллекции. + * + * @private + * @param {array} target Исходная коллекция. + * @param {number} index Индекс элемента. + * @returns {*} Элемент коллекции. + */ + function getCollectionItem(target, index) { + if (target !== null && target !== undefined + && Object.prototype.toString.call(target) === "[object Array]" + && index >= 0 && index < target.length) { -/** - * - * @returns {CollectionEventManager} - */ -CollectionEventManager.prototype.onReset = function () { - var params = { - action: 'reset' - }; + return target[index]; + } - this.trigger('reset', params); - this.trigger('change', params); - return this; -}; + return null; + } -/** - * - * @param {Array} oldItems - * @param {Array} newItems - * @returns {CollectionEventManager} - */ -CollectionEventManager.prototype.onReplace = function (oldItems, newItems) { - var params = { - action: 'replace', - oldItems: oldItems, - newItems: newItems - }; + /** + * Устанавливает элемент коллекции. + * + * @private + * @param {array} target Исходная коллекция. + * @param {number} index Индекс элемента. + * @param {*} item Элемент коллекции. + */ + function setCollectionItem(target, index, item) { + if (target !== null && target !== undefined + && Object.prototype.toString.call(target) === "[object Array]" + && index >= 0 && index < target.length) { - this.trigger('replace', params); - this.trigger('change', params); - return this; -}; + target[index] = item; + } + } -/** - * - * @param {Array} oldItems - * @param {number} [oldStartingIndex] - * @returns {CollectionEventManager} - */ -CollectionEventManager.prototype.onRemove = function (oldItems, oldStartingIndex) { - var params = { - action: 'remove', - oldItems: oldItems, - oldStartingIndex: typeof oldStartingIndex !== 'undefined' ? oldStartingIndex : -1 - }; - this.trigger('remove', params); - this.trigger('change', params); - return this; -}; + /** + * Возвращает значение свойства объекта. + * + * @private + * @param {object} target Исходный объект. + * @param {string} propertyName Наименование свойства. + * @returns {*} Значение свойства. + */ + function getObjectProperty(target, propertyName) { + if (target !== null && target !== undefined + && Object.prototype.toString.call(target) === "[object Object]" + && propertyName !== null && propertyName !== undefined) { -/** - * - * @param {Array} oldItems - * @param {Array} newItems - * @param {number} oldStartingIndex - * @param {number} newStartingIndex - * @returns {CollectionEventManager} - */ -CollectionEventManager.prototype.onMove = function (oldItems, newItems, oldStartingIndex, newStartingIndex) { - var params = { - oldItems: oldItems, - newItems: newItems, - oldStartingIndex: oldStartingIndex, - newStartingIndex: newStartingIndex - }; + return target[propertyName]; + } - this.trigger('move', params); - this.trigger('change', params); - return this; -}; + return null; + } + /** + * Устанавливает значение свойства объекта. + * + * @private + * @param {object} target Исходный объект. + * @param {string} propertyName Наименование свойства. + * @param {*} propertyValue Значение свойства. + */ + function setObjectProperty(target, propertyName, propertyValue) { + if (target !== null && target !== undefined + && Object.prototype.toString.call(target) === "[object Object]" + && propertyName !== null && propertyName !== undefined) { + target[propertyName] = propertyValue; + } + } + return { -//####app/utils/actionOnLoseFocus.js -var ActionOnLoseFocus = function ($el, action) { - var that = this; - this.$el = $el; - this.action = action; - this.checkNeedToAction_binded = _.bind(this.checkNeedToAction, this); + /** + * Возвращает значение свойства. + * + * @public + * @param {*} target Исходный объект. + * @param {string|Object} propertyPath Путь к свойству или объект для построения значения. + * @returns {*} Значение свойства. + */ + getPropertyValue: function (target, propertyPath) { + var result; - $(document).on('mousedown', that.checkNeedToAction_binded); -}; + var getPropertyValue = function (target, propertyPath) { + var propertyPathTerms = splitPropertyPath(propertyPath); + var result = getPropertyByPath(target, propertyPathTerms); + return typeof result === 'undefined' ? null : result; + }; -ActionOnLoseFocus.prototype.checkNeedToAction = function (e) { - if ($(e.target).closest(this.$el).length == 0) { - this.action(); - $(document).off('mousedown', this.checkNeedToAction_binded) - } -}; + if (_.isObject(propertyPath)) { + result = {}; + _.each(propertyPath, function (v, n) { + result[n] = getPropertyValue(target, v); + }); + } else { + result = getPropertyValue(target, propertyPath); + } + return result; + }, -window.InfinniUI.ActionOnLoseFocus = ActionOnLoseFocus; + /** + * Устанавливает значение свойства. + * + * @public + * @param {*} target Исходный объект. + * @param {string} propertyPath Путь к свойству. + * @param {*} propertyValue Значение свойства. + */ + setPropertyValue: function (target, propertyPath, propertyValue) { + if (target !== null && target !== undefined && !_.isEmpty(propertyPath)) { + var propertyPathTerms = splitPropertyPath(propertyPath); -//####app/utils/basePathOfProperty.js -function BasePathOfProperty(basePathOfProperty, baseIndex, parentBasePath ) { + if(propertyValue instanceof Date){ + setPropertyByPath(target, propertyPathTerms, new Date(propertyValue)); + } else if(propertyValue instanceof File){ + setPropertyByPath(target, propertyPathTerms, propertyValue); + } else{ + setPropertyByPath(target, propertyPathTerms, propertyValue); + } + } + }, + setPropertyValueDirect: function (target, propertyPath, propertyValue) { + if (target !== null && target !== undefined && !_.isEmpty(propertyPath)) { + var propertyPathTerms = splitPropertyPath(propertyPath); + setPropertyByPath(target, propertyPathTerms, propertyValue); + } + } + }; +})(); - if(this.isRelativeProperty(basePathOfProperty)){ - this.basePathOfProperty = parentBasePath.basePathOfProperty + this.excludeFirstChar(basePathOfProperty); - }else{ - this.basePathOfProperty = basePathOfProperty; - } - if(!parentBasePath){ - if(baseIndex !== undefined && baseIndex !== null){ - this.indexesInParentLists = [baseIndex]; - this.basePathOfProperty += baseIndex; - } - - }else{ - this.indexesInParentLists = parentBasePath.indexesInParentLists ? parentBasePath.indexesInParentLists.slice() : []; - this.indexesInParentLists.push(baseIndex); - - this.parentBasePath = parentBasePath; - } +//####app/utils/eventsManager.js +function EventsManager () { + this.handlers = {}; } -window.InfinniUI.BasePathOfProperty = BasePathOfProperty; - -_.extend(BasePathOfProperty.prototype, { - /*возвращает полный путь к свойству элемента в коллекции*/ - resolveProperty: function(property) { - if(property === undefined || property === null){ - property = ''; - } - - if(this.isRelativeProperty(property)){ - property = this.excludeFirstChar(property); - return stringUtils.formatProperty(this.basePathOfProperty + property, this.indexesInParentLists); - }else{ - return stringUtils.formatProperty(property, this.indexesInParentLists); - } - - }, - - /*возвращает полный путь к свойству элемента в коллекции по заданному относительному пути*/ - resolveRelativeProperty: function(relativeProperty) { - var property; - if(this.basePathOfProperty != ''){ - property = this.basePathOfProperty + '.' + relativeProperty; - }else{ - property = relativeProperty; - } - return this.resolveProperty(property); - }, - - /*создает BasePathOfProperty следующего уровня*/ - buildChild: function(basePathOfProperty, baseIndex){ - return new BasePathOfProperty(basePathOfProperty, baseIndex, this); - }, - - /*создает BasePathOfProperty следующего уровня с относительным путем*/ - buildRelativeChild: function(basePathOfProperty, baseIndex){ - return new BasePathOfProperty(basePathOfProperty, baseIndex, this); - }, - - isRelativeProperty: function(property){ - return property.substr(0,1) == '@'; - }, +window.InfinniUI.EventsManager = EventsManager; - excludeFirstChar: function(str){ - return str.substr(1, str.length - 1); +EventsManager.prototype.on = function (event, handler) { + if (typeof this.handlers[event] === 'undefined') { + this.handlers[event] = []; } -}); - -//####app/utils/blobUtils.js -/** - * Набор утилит для работы с BlobData объектами - **/ - -window.InfinniUI.BlobUtils = (function () { + var handlers = this.handlers[event]; + var manager = this; + handlers.push(handler); - var blobUtils = { - isFileInfo: isFileInfo, - getContentId: getContentByName.bind(null, 'Id'), - getName: getContentByName.bind(null, 'Name'), - getSize: getContentByName.bind(null, 'Size'), - getTime: getContentByName.bind(null, 'Time'), - getType: getContentByName.bind(null, 'Type') + return { + off: this.off.bind(this, event, handler) }; +}; - return blobUtils; - - function isFileInfo (data) { - return data && blobUtils.getContentId(data); - } - - function getContentByName(name, data, defaultValue) { - return _.isObject(data) ? data[name] : defaultValue; - } - -})(); - - - - +EventsManager.prototype.off = function (event, handler) { + if (typeof event !== 'undefined') { + var handlers = this.handlers[event]; -//####app/utils/clone.js -_.mixin({ - deepClone: function (value) { - if (value !== null && typeof value !== 'undefined') { - return JSON.parse(JSON.stringify(value)); + if (Array.isArray(handlers)) { + for(var i = 0; i < handlers.length; i = i + 1) { + if (handlers[i] === handler) { + handlers.splice(i, 1); + break; + } + } } - return value; } -}); -//####app/utils/currentView.js -var OpenedViewCollection = function () { - - var list = []; +}; - this.appendView = function (metadata, viewMetadata, view) { +EventsManager.prototype.trigger = function (event) { + var handlers = this.handlers[event], + args = Array.prototype.slice.call(arguments, 1), + deferred = $.Deferred(); - list.push({ - metadata:metadata, - viewMetadata: viewMetadata, - view: view + if (Array.isArray(handlers)) { + var results = handlers.map(function (handler) { + return handler.apply(null, args); }); - }; - - this.removeView = function (view) { - for (var i = 0, ln = list.length; i < ln; i = i + 1) { - if (view === list[i].view) { - list.splice(i, 1); - break; - } - } - }; - - this.getLastView = function () { - if (list.length === 0) { - return; - } - - return list[list.length - 1]; - }; + $.when.apply($, results) + .done(function () { + var results = Array.prototype.slice.call(arguments); + var cancel = results.some(function (res) { + return res === false; + }); - this.getList = function () { - return list; + if (cancel) { + deferred.reject(); + } else { + deferred.resolve(results); + } + }) + .fail(function () { + deferred.reject(); + }); + } else { + deferred.resolve(); } + return deferred.promise(); }; -window.InfinniUI.views = new OpenedViewCollection(); +//####app/utils/fileSize.js +window.InfinniUI = window.InfinniUI || {}; +window.InfinniUI.format = window.InfinniUI.format || {}; + +window.InfinniUI.format.humanFileSize = function (size) { + /** + * @see {@link http://stackoverflow.com/questions/10420352/converting-file-size-in-bytes-to-human-readable} + */ + var i = Math.floor( Math.log(size) / Math.log(1024) ); + return ( size / Math.pow(1024, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]; +}; +//####app/utils/filterItems.js +var filterItems = (function() { + return function(items, filter) { + if( !filter ){ + return items; + } -//####app/utils/date.js -window.InfinniUI.DateUtils = (function () { + var itemsForFilter = JSON.parse(JSON.stringify(items)), + filterMethods = filterItems.filterMethods, + filterTree = filterItems.filterTreeBuilder.buildUpFilterTree(filter); - init(); + function stringToNum(value) { + if( typeof value === 'string' && !isNaN(value) ) { + value = +value; + } + return value; + } + function stringToBoolean(value) { + if( value === 'true' ) { + value = true; + } else if( value === 'false' ) { + value = false; + } else if( value === 'null' ) { + value = null; + } + return value; + } + function stringToArr(value) { + if( typeof value === 'string' && value.search(/\[[\'a-zA-Z0-9,]+\]/) !== -1 ) { + value = value.slice(1, -1).split(','); + for( var i = 0, ii = value.length; i < ii; i += 1 ) { + if( value[i].slice(-1) === "'" ) { + value[i] = value[i].slice(1, -1); + } + value[i] = stringToBoolean( value[i] ); + value[i] = stringToNum( value[i] ); + } + } + return value; + } + function findContext(currentContext, currentFunc) { + if( currentFunc.functionName === 'match' ) { + currentContext = currentFunc.children[0].valueName; + } + return currentContext; + } + function filterExec(filterTree, items, context) { // filterTree is object, items is array + var tmpChild1, tmpChild2 = []; + // find context + context = findContext( context, filterTree ); + for( var j = 0, jj = filterTree.children.length; j < jj; j += 1 ) { + // if any child is function + // call filterExec with children of this child + if( filterTree.children[j].type === 'function' ) { + tmpChild1 = filterTree.children[j]; - var _defaultTimeZone; + filterTree.children[j].valueName = filterExec(tmpChild1, items, context); + filterTree.children[j].newType = 'value'; + } + if( filterTree.children[j].type === 'value' || filterTree.children[j].newType === 'value' ) { + if( filterTree.children[j].type === 'value' ) { + filterTree.children[j].valueName = stringToNum( filterTree.children[j].valueName ); // check on Number + filterTree.children[j].valueName = stringToBoolean( filterTree.children[j].valueName ); // check on Boolean + filterTree.children[j].valueName = stringToArr( filterTree.children[j].valueName ); // check on Array + } + tmpChild2.push( filterTree.children[j].valueName ); + } + } + return filterMethods[filterTree.functionName](tmpChild2, items, context); // tmpChild2 is array + } + return filterExec(filterTree, itemsForFilter); + }; +})(filterItems); - return { - toISO8601: toISO8601, - dateToTimestamp: dateToTimestamp, - dateToTimestampTime: dateToTimestampTime, - changeTimezoneOffset: changeTimezoneOffset, - restoreTimezoneOffset: restoreTimezoneOffset, - toDate: toDate, - createDate: createDate, - parseTimeISO8601toDate: parseTimeISO8601toDate, - parseISO8601toDate:parseISO8601toDate, - checkRangeDate: checkRangeDate, - getNearestDate: getNearestDate, - cloneDate: cloneDate, - getDefaultTimeZone: getDefaultTimezone - }; - - function parseISO8601toDate(value) { - if (value === null || typeof value ==='undefined') { - return value; - } - return moment(value).toDate(); - } - - function cloneDate(date) { - if (date instanceof Date) { - return new Date(date.getTime()); - } - return date; - } - - /** - * @description Возвращает ближаешее к исходному значению из диапазона - * @param date - * @param min - * @param max - * @returns {Date} - */ - function getNearestDate(date, min, max) { - var nearest; - - var mMin = moment(min || null), - mMax = moment(max || null), - mVal = moment(date); - - - if (mMin.isValid() && mVal.isBefore(mMin)) { - nearest = mMin.toDate(); - } else if (mMax.isValid() && mVal.isAfter(mMax)) { - nearest = mMax.toDate(); - } else { - nearest = date; - } - - return nearest; - } - - /** - * @description Проверяет, что дата находится в заданном диапазоне - * @param date - * @param minDate - * @param maxDate - * @param {String} precision - * @returns {boolean} - */ - function checkRangeDate(date, minDate, maxDate, precision) { - var success = true; - - var mMin = moment(minDate || null), - mMax = moment(maxDate || null), - mVal = moment(date); - - - if (mMin.isValid() && mMax.isValid()) { - success = mVal.isSameOrBefore(mMax, precision) && mVal.isSameOrAfter(mMin, precision); - } else if (mMin.isValid()) { - success = mVal.isSameOrAfter(mMin, precision); - } else if (mMax.isValid()) { - success = mVal.isSameOrBefore(mMax, precision); - } - - return success; - } - - function parseTimeISO8601toDate(value) { - var date; - var formats = ['HH:mm', 'HH:mm:ss', 'HH:mm:ss.SSS', 'HHmm', 'HHmmss', 'HHmmss.SSS']; - var m = moment(value, formats); - if (m.isValid()) { - date = new Date(0); - date.setHours(m.hours(), m.minute(), m.second(), m.millisecond()); - } - return date; - } - - function toDate(value) { - var m = moment(value); - var date = null; - - if (m.isValid()) { - date = m.toDate(); - } - - return date; - } - - function changeTimezoneOffset(date, timezoneOffset) { - var newDate = date; - - if (typeof timezoneOffset !== 'undefined' && date instanceof Date) { - var currentOffset = date.getTimezoneOffset(); - - if (timezoneOffset !== currentOffset) { - newDate = new Date(date.getTime() + (currentOffset - timezoneOffset) * 60 * 1000); - } - } - - return newDate; - } - - function restoreTimezoneOffset(date, timezoneOffset) { - var newDate = date; - - if (typeof timezoneOffset !== 'undefined' && date instanceof Date) { - var currentOffset = date.getTimezoneOffset(); - - if (timezoneOffset !== currentOffset) { - newDate = new Date(date.getTime() - (currentOffset - timezoneOffset) * 60 * 1000); - } - } - - return newDate; - } - - /** - * @description Возвращает строковое представление даты в формате YYYY-MM-DDTHH:mm:ss.sss+HH:MM - * @param {Date} date - * @param {Object} options - * @param {Number} options.timezoneOffset Смещение часового пояса относительно часового пояса UTC в минутах - * @returns {string|null} - */ - function toISO8601(date, options) { - - var config = options || {}; - - if (typeof date === 'undefined' || date === null) { - return null; - } - - if (date.constructor !== Date) { - return null; - } - - var _date = changeTimezoneOffset(date, config.timezoneOffset); - - var datePart = [ - padInt(_date.getFullYear(), 4), - padInt(_date.getMonth() + 1, 2), - padInt(_date.getDate(), 2) - ].join('-'); - - var timePart = [ - padInt(_date.getHours(), 2), - padInt(_date.getMinutes(), 2), - padInt(_date.getSeconds(), 2) - ].join(':'); - - var sssPart = padInt(_date.getMilliseconds(), 3) + '0';// '000' + '0' - - - var timezoneOffset = config.timezoneOffset; - if (typeof timezoneOffset === 'undefined' || timezoneOffset === null) { - timezoneOffset = date.getTimezoneOffset(); - } - - var tz = Math.abs(timezoneOffset); - var tzOffsetPart = Math.sign(timezoneOffset) > 0 ? '-' : '+'; - var tzPart = [ - padInt(Math.floor(tz / 60), 2), - padInt(tz % 60, 2) - ].join(':'); - - return datePart + 'T' + timePart + '.' + sssPart + tzOffsetPart + tzPart; - } - - /** - * @description Возвращает заданную дату как количество секунд, прошедших с 01-01-1970T00:00 по UTC - * @param {String|Date} date ISO8601 - */ - function dateToTimestamp(date) { - var _date, datetime = null; - - if (date && date.constructor === String) { - _date = new Date(date); - } else if (date && date.constructor === Date) { - _date = date; - } - - if (_date) { - _date.setUTCHours(0, 0, 0, 0); - datetime = _date.getTime() / 1000; - } - - return datetime; - } - - function dateToTimestampTime(date) { - var time = null, _date, datetime; - - if (date && date.constructor === String) { - _date = new Date(date); - } else if (date && date.constructor === Date) { - _date = date; - } - - if (_date) { - datetime = new Date(0); - datetime.setUTCHours(_date.getUTCHours(), _date.getUTCMinutes(), _date.getUTCSeconds(), _date.getUTCMilliseconds()); - time = datetime.getTime() / 1000; - } - - return time; - } - - function createDate(d) { - var date; - - if (typeof d === Date) { - date = new Date(d.getTime()); - } else if (typeof d === 'number') { - //Числовое значение интерпретируем как секунды (as unix-time)! - date = new Date(d * 1000); - } else if (typeof d === 'undefined' || d === null) { - date = null; - } else { - date = toDate(d); - } - - return date; - } - - function getDefaultTimezone() { - return _defaultTimeZone; - } - - function padInt(value, size) { - var str = '' + value; - var pad = ''; - if (str.length < size) { - pad = Array(size - str.length + 1).join('0'); - } - return pad + str; - } - - function init() { - - var date = new Date(); - _defaultTimeZone = date.getTimezoneOffset(); - - if (!Math.sign) { //fix for devices not support ES6 - Math.sign = function (x) { - return x ? x < 0 ? -1 : 1 : 0; - }; - } - } - -})(); -//####app/utils/domHelper.js -var domHelper = { - - whenReady: function(conditionFunction, onConditionFunction, n){ - var that = this; - - if(n === undefined){ - n = 100; - } - - if(!conditionFunction()){ - if(n>0){ - setTimeout( function(){ - that.whenReady(conditionFunction, onConditionFunction, n-1); - }, 510); - } - }else{ - onConditionFunction(); - } - } - -}; - -//####app/utils/dot.js -/** - * Синглтон для работы с путями построенными по dot-notation - **/ - -window.InfinniUI.ObjectUtils = (function () { - - /** - * Возвращает значение свойства. - * - * @private - * @param {*} target Исходный объект. - * @param {array} propertyPathTerms Путь к свойству объекта в виде коллекции термов. - * @returns {*} Значение свойства. - */ - function getPropertyByPath(target, propertyPathTerms) { - if (target !== null && target !== undefined - && propertyPathTerms !== null && propertyPathTerms !== undefined) { - - var parent = target; - var length = propertyPathTerms.length; - - for (var i = 0; i < length; ++i) { - if (parent !== null && parent !== undefined) { - var term = propertyPathTerms[i]; - - var termCollectionIndex = parseCollectionIndex(term); - - if (termCollectionIndex >= 0) { - parent = getCollectionItem(parent, termCollectionIndex); - } - else { - parent = getObjectProperty(parent, term); - } - } - else { - return null; - } - } - - return parent; - } - - return target; - } - - /** - * Возвращает значение свойства. - * - * @private - * @param {*} target Исходный объект. - * @param {array} propertyPathTerms Путь к свойству объекта в виде коллекции термов. - * @param {*} propertyValue Значение свойства объекта. - * @returns {*} Значение свойства. - */ - function setPropertyByPath(target, propertyPathTerms, propertyValue) { - var parent = target; - var length = propertyPathTerms.length - 1; - - var term = propertyPathTerms[0]; - var termCollectionIndex = parseCollectionIndex(term); - - for (var i = 0; i < length; ++i) { - var termValue = (termCollectionIndex >= 0) - ? getCollectionItem(parent, termCollectionIndex) - : getObjectProperty(parent, term); - - var nextTerm = propertyPathTerms[i + 1]; - var nextTermCollectionIndex = parseCollectionIndex(nextTerm); - - if(nextTermCollectionIndex >= 0){ - if(!$.isArray(termValue)){ - termValue = []; - } - - setCollectionItem(parent, termCollectionIndex, termValue); - }else{ - if(!$.isPlainObject(termValue)){ - termValue = {}; - } - - setObjectProperty(parent, term, termValue); - } - - parent = termValue; - term = nextTerm; - termCollectionIndex = nextTermCollectionIndex; - } - - if (termCollectionIndex >= 0) { - setCollectionItem(parent, termCollectionIndex, propertyValue); - } - else { - setObjectProperty(parent, term, propertyValue); - } - } - - - /** - * Разбивает путь к свойству, записанному в dot-notation, на термы. - * - * @private - * @param {string} propertyPath Имя свойства. - */ - function splitPropertyPath(propertyPath) { - if (_.isEmpty(propertyPath)) { - return null; - } - - return propertyPath.split("."); - } - - /** - * Пытается интерпретировать имя свойства, как индекс элемента коллекции. - * - * @private - * @param {string} propertyName Имя свойства. - * @returns {number} Индекс элемента коллекции или -1. - */ - function parseCollectionIndex(propertyName) { - var index = -1; - - if (propertyName === "$") { - index = 0; - } - else { - var tryParse = parseInt(propertyName); - - if (!isNaN(tryParse)) { - index = tryParse; - } - } - - return index; - } - - - /** - * Возвращает элемент коллекции. - * - * @private - * @param {array} target Исходная коллекция. - * @param {number} index Индекс элемента. - * @returns {*} Элемент коллекции. - */ - function getCollectionItem(target, index) { - if (target !== null && target !== undefined - && Object.prototype.toString.call(target) === "[object Array]" - && index >= 0 && index < target.length) { - - return target[index]; - } - - return null; - } - - /** - * Устанавливает элемент коллекции. - * - * @private - * @param {array} target Исходная коллекция. - * @param {number} index Индекс элемента. - * @param {*} item Элемент коллекции. - */ - function setCollectionItem(target, index, item) { - if (target !== null && target !== undefined - && Object.prototype.toString.call(target) === "[object Array]" - && index >= 0 && index < target.length) { - - target[index] = item; - } - } - - - /** - * Возвращает значение свойства объекта. - * - * @private - * @param {object} target Исходный объект. - * @param {string} propertyName Наименование свойства. - * @returns {*} Значение свойства. - */ - function getObjectProperty(target, propertyName) { - if (target !== null && target !== undefined - && Object.prototype.toString.call(target) === "[object Object]" - && propertyName !== null && propertyName !== undefined) { - - return target[propertyName]; - } - - return null; - } - - /** - * Устанавливает значение свойства объекта. - * - * @private - * @param {object} target Исходный объект. - * @param {string} propertyName Наименование свойства. - * @param {*} propertyValue Значение свойства. - */ - function setObjectProperty(target, propertyName, propertyValue) { - if (target !== null && target !== undefined - && Object.prototype.toString.call(target) === "[object Object]" - && propertyName !== null && propertyName !== undefined) { - - target[propertyName] = propertyValue; - } - } - - return { - - /** - * Возвращает значение свойства. - * - * @public - * @param {*} target Исходный объект. - * @param {string|Object} propertyPath Путь к свойству или объект для построения значения. - * @returns {*} Значение свойства. - */ - getPropertyValue: function (target, propertyPath) { - var result; - - var getPropertyValue = function (target, propertyPath) { - var propertyPathTerms = splitPropertyPath(propertyPath); - var result = getPropertyByPath(target, propertyPathTerms); - return typeof result === 'undefined' ? null : result; - }; - - if (_.isObject(propertyPath)) { - result = {}; - _.each(propertyPath, function (v, n) { - result[n] = getPropertyValue(target, v); - }); - } else { - result = getPropertyValue(target, propertyPath); - } - return result; - }, - - /** - * Устанавливает значение свойства. - * - * @public - * @param {*} target Исходный объект. - * @param {string} propertyPath Путь к свойству. - * @param {*} propertyValue Значение свойства. - */ - setPropertyValue: function (target, propertyPath, propertyValue) { - if (target !== null && target !== undefined && !_.isEmpty(propertyPath)) { - var propertyPathTerms = splitPropertyPath(propertyPath); - - if(propertyValue instanceof Date){ - setPropertyByPath(target, propertyPathTerms, new Date(propertyValue)); - } else if(propertyValue instanceof File){ - setPropertyByPath(target, propertyPathTerms, propertyValue); - } else{ - setPropertyByPath(target, propertyPathTerms, propertyValue); - } - } - }, - - setPropertyValueDirect: function (target, propertyPath, propertyValue) { - if (target !== null && target !== undefined && !_.isEmpty(propertyPath)) { - var propertyPathTerms = splitPropertyPath(propertyPath); - setPropertyByPath(target, propertyPathTerms, propertyValue); - } - } - }; -})(); - - - -//####app/utils/eventsManager.js -function EventsManager () { - this.handlers = {}; -} - -window.InfinniUI.EventsManager = EventsManager; - -EventsManager.prototype.on = function (event, handler) { - if (typeof this.handlers[event] === 'undefined') { - this.handlers[event] = []; - } - - var handlers = this.handlers[event]; - var manager = this; - handlers.push(handler); - - return { - off: this.off.bind(this, event, handler) - }; -}; - -EventsManager.prototype.off = function (event, handler) { - if (typeof event !== 'undefined') { - var handlers = this.handlers[event]; - - if (Array.isArray(handlers)) { - for(var i = 0; i < handlers.length; i = i + 1) { - if (handlers[i] === handler) { - handlers.splice(i, 1); - break; - } - } - } - } -}; - -EventsManager.prototype.trigger = function (event) { - var handlers = this.handlers[event], - args = Array.prototype.slice.call(arguments, 1), - deferred = $.Deferred(); - - if (Array.isArray(handlers)) { - var results = handlers.map(function (handler) { - return handler.apply(null, args); - }); - $.when.apply($, results) - .done(function () { - var results = Array.prototype.slice.call(arguments); - var cancel = results.some(function (res) { - return res === false; - }); - - if (cancel) { - deferred.reject(); - } else { - deferred.resolve(results); - } - }) - .fail(function () { - deferred.reject(); - }); - } else { - deferred.resolve(); - } - - return deferred.promise(); -}; - -//####app/utils/fileSize.js -window.InfinniUI = window.InfinniUI || {}; -window.InfinniUI.format = window.InfinniUI.format || {}; - -window.InfinniUI.format.humanFileSize = function (size) { - /** - * @see {@link http://stackoverflow.com/questions/10420352/converting-file-size-in-bytes-to-human-readable} - */ - var i = Math.floor( Math.log(size) / Math.log(1024) ); - return ( size / Math.pow(1024, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]; -}; -//####app/utils/filterItems.js -var filterItems = (function() { - - return function(items, filter) { - if( !filter ){ - return items; - } - - var itemsForFilter = JSON.parse(JSON.stringify(items)), - filterMethods = filterItems.filterMethods, - filterTree = filterItems.filterTreeBuilder.buildUpFilterTree(filter); - - function stringToNum(value) { - if( typeof value === 'string' && !isNaN(value) ) { - value = +value; - } - return value; - } - function stringToBoolean(value) { - if( value === 'true' ) { - value = true; - } else if( value === 'false' ) { - value = false; - } else if( value === 'null' ) { - value = null; - } - return value; - } - function stringToArr(value) { - if( typeof value === 'string' && value.search(/\[[\'a-zA-Z0-9,]+\]/) !== -1 ) { - value = value.slice(1, -1).split(','); - for( var i = 0, ii = value.length; i < ii; i += 1 ) { - if( value[i].slice(-1) === "'" ) { - value[i] = value[i].slice(1, -1); - } - value[i] = stringToBoolean( value[i] ); - value[i] = stringToNum( value[i] ); - } - } - return value; - } - function findContext(currentContext, currentFunc) { - if( currentFunc.functionName === 'match' ) { - currentContext = currentFunc.children[0].valueName; - } - return currentContext; - } - function filterExec(filterTree, items, context) { // filterTree is object, items is array - var tmpChild1, tmpChild2 = []; - // find context - context = findContext( context, filterTree ); - for( var j = 0, jj = filterTree.children.length; j < jj; j += 1 ) { - // if any child is function - // call filterExec with children of this child - if( filterTree.children[j].type === 'function' ) { - tmpChild1 = filterTree.children[j]; - - filterTree.children[j].valueName = filterExec(tmpChild1, items, context); - filterTree.children[j].newType = 'value'; - } - if( filterTree.children[j].type === 'value' || filterTree.children[j].newType === 'value' ) { - if( filterTree.children[j].type === 'value' ) { - filterTree.children[j].valueName = stringToNum( filterTree.children[j].valueName ); // check on Number - filterTree.children[j].valueName = stringToBoolean( filterTree.children[j].valueName ); // check on Boolean - filterTree.children[j].valueName = stringToArr( filterTree.children[j].valueName ); // check on Array - } - tmpChild2.push( filterTree.children[j].valueName ); - } - } - return filterMethods[filterTree.functionName](tmpChild2, items, context); // tmpChild2 is array - } - return filterExec(filterTree, itemsForFilter); - }; -})(filterItems); - -window.InfinniUI.FilterItems = filterItems; - - -filterItems.filterTreeBuilder = (function() { - var that = {}, - splitStringToArray = function(filter) { //filter is string - var tmpArr, - tmpNum, - tmpString, - tmpString2, - tmpRE, - reForDates = /date\(\'[0-9a-zA-Z\:\-\+\.\s]+\'\)/g, - reForParamAsArray = /\,[a-zA-Z0-9\'\,\_\.]+\)/g, - reForArrayFromOneElem = /\[[a-zA-Z0-9\'\_\.]+\]/g, - reForElemsOfTree = /[a-zA-Z]+[(]|\[[a-zA-Z0-9\S]+\]|[-\']{0,1}[a-zA-Z0-9_\.]+[\']{0,1}[,)$]/g, - reForClosingBrackets = /[)]/g, - reForRegExp = /\'([a-zA-Z0-9\S\W\D]+\s*)+\'/g, - reForSpaces = /\s+/g, - reForFewWordsInQuotes = /\'([a-zA-Z0-9\s]+\s*)+\'/g, - arr = []; - while( tmpArr = reForDates.exec(filter) ) { // search all dates and convert it to number of s [0.000] - tmpNum = Date.parse( tmpArr[0].slice(6, -2) ) / 1000 + ''; - filter = filter.slice(0, tmpArr.index) + tmpNum + filter.slice(tmpArr.index + tmpArr[0].length); - reForDates.lastIndex = tmpArr.index + tmpNum.length; - } - while( tmpArr = reForRegExp.exec(filter) ) { // search for regexp - tmpNum = tmpArr[0]; - if( tmpNum.search(reForSpaces) !== -1 || tmpNum.search(reForFewWordsInQuotes) !== -1 ) { - while( tmpString = reForFewWordsInQuotes.exec(tmpNum) ) { - tmpString2 = tmpString[0].replace(reForSpaces, '_'); - tmpNum = tmpNum.slice(0, tmpString.index) + tmpString2 + tmpNum.slice(tmpString.index + tmpString[0].length); - } - } else { - tmpRE = tmpNum.slice(1, -1); - tmpNum = 'tmpRE'; - } - filter = filter.slice(0, tmpArr.index) + tmpNum + filter.slice(tmpArr.index + tmpArr[0].length); - reForRegExp.lastIndex = tmpArr.index + tmpNum.length; - } - filter = filter.replace(/\s+/g, ''); - while( tmpArr = reForParamAsArray.exec(filter) ) { // search second param - tmpNum = '[' + tmpArr[0].slice(1, -1) + '])'; - filter = filter.slice(0, tmpArr.index + 1) + tmpNum + filter.slice(tmpArr.index + tmpArr[0].length); - reForParamAsArray.lastIndex = tmpArr.index + tmpNum.length; - } - while( tmpArr = reForArrayFromOneElem.exec(filter) ) { // convert array from 1 element to number or string or boolean - tmpNum = tmpArr[0].slice(1, -1); - filter = filter.slice(0, tmpArr.index) + tmpNum + filter.slice(tmpArr.index + tmpArr[0].length); - reForArrayFromOneElem.lastIndex = tmpArr.index + tmpNum.length; - } - while( tmpArr = reForElemsOfTree.exec(filter) ) { // search all functions and values with their index - if( tmpArr[0].length > 1 && (tmpArr[0].slice(-1) === ',' || tmpArr[0].slice(-1) === ')') ) { - tmpArr[0] = tmpArr[0].slice(0, -1); - } - if( tmpArr[0].length > 1 && tmpArr[0].slice(0, 1) === "'" ) { - tmpArr[0] = tmpArr[0].slice(1, -1); - } - if( tmpArr[0].search(/tmpRE/) !== -1 ) { - tmpArr[0] = tmpArr[0].slice(1, -1).split(','); - tmpArr[0][0] = tmpRE; - } - arr.push(tmpArr); - } - while( tmpArr = reForClosingBrackets.exec(filter) ) { // search all closing brackets with their index - arr.push(tmpArr); - } - arr.sort(function(a, b) { // sort arr by indexes to put all data in right order - return a.index - b.index; - }); - return arr; - }, - divideToFunctionsAndValues = function(arrayToDivide) { //arrayToDivide is array - var tmpArr = [], - values = [], - filterArr = [], - counter = 0, - that, - tmpSymbol, - thatValue, - firstPart; - // split all data to different functions - for( var i = 0, ii = arrayToDivide.length; i < ii; i += 1 ) { - if( typeof arrayToDivide[i][0] === 'string' ) { - tmpSymbol = arrayToDivide[i][0].slice(-1); - } else { - tmpSymbol = ']'; - } - if( tmpSymbol === '(' ) { // define functions from string - that = {}; - that.type = 'function'; - that.functionName = arrayToDivide[i][0].slice(0, -1); - that.index = arrayToDivide[i].index; - tmpArr.push( that ); - } else if( tmpSymbol === ')' ) { // define where end of function - filterArr[counter] = []; - firstPart = tmpArr.pop(); - firstPart.range = []; - firstPart.range.push( firstPart.index ); - firstPart.children = []; - firstPart.range.push( arrayToDivide[i].index ); - filterArr[counter] = firstPart; - counter += 1; - } else { // define params that are values - thatValue = {}; - thatValue.type = 'value'; - thatValue.valueName = arrayToDivide[i][0]; - thatValue.index = arrayToDivide[i].index; - values.push( thatValue ); - } - } - return [filterArr, values]; - }, - addValuesAsChildren = function(filterArr, values) { // filterArr, values are arrays - //add values to right place as children for functions - //define right place by range of index property - for( var i = 0, ii = values.length; i < ii; i += 1 ) { - for( var j = 0, jj = filterArr.length; j < jj; j += 1 ) { - if( values[i] !== null ) { - if( values[i].index > filterArr[j].range[0] && values[i].index < filterArr[j].range[1] ) { - filterArr[j].children.push( values[i] ); - values[i] = null; - } - } - } - } - return filterArr; - }, - filterArrToTree = function(filterArr) { // filterArr is array - // build up a filter tree - // by putting some functions as children for other - for( var i = 0; i < filterArr.length; i += 1 ) { - for( var j = 0; j < filterArr.length; j += 1 ) { - if( filterArr[j] !== null || filterArr[i] !== null ) { - //search for first result[j] where we can put result[i] as his child - //if find, put it and remove result[i] - if( filterArr[i].range[0] > filterArr[j].range[0] && filterArr[i].range[1] < filterArr[j].range[1] ) { - //if result[j] already have any children, check their indexes to define where put new child - if( filterArr[j].children[0] !== undefined && filterArr[j].children[0].index > filterArr[i].range[0] ) { - filterArr[j].children.unshift( filterArr[i] ); - filterArr.splice(i, 1); - i -= 1; - break; - } else { - filterArr[j].children.push( filterArr[i] ); - filterArr.splice(i, 1); - i -= 1; - break; - } - } - } - } - } - return filterArr[0]; - }; - that.buildUpFilterTree = function(filter) { // filter is string - var tmpArr; - tmpArr = splitStringToArray(filter); - tmpArr = divideToFunctionsAndValues(tmpArr); - tmpArr = addValuesAsChildren(tmpArr[0], tmpArr[1]); - return filterArrToTree(tmpArr); - }; - return that; -})(); - -//sub method for filterItems with filter methods -filterItems.filterMethods = (function() { - var that = {}; - - that.eq = function(value, items, context) { // value is array: value[0] - param, value[1] - value - var tmpResult = [], - tmpResult2, - length, - globalUI = InfinniUI.ObjectUtils; - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - if( context ) { - tmpResult2 = []; - if( items[i][context] === undefined ) { - length = -1; - } else { - length = items[i][context].length; - } - for( var j = 0, jj = length; j < jj; j += 1 ) { - if( globalUI.getPropertyValue( items[i][context][j], value[0] ) === value[1] ) { - tmpResult2.push( items[i] ); - } - } - if( length === tmpResult2.length ) { - tmpResult.push( items[i] ); - } - } else { - if( globalUI.getPropertyValue( items[i], value[0] ) === value[1] ) { - tmpResult.push( items[i] ); - } - } - } - return tmpResult; - }; - - that.and = function(values, items, context) { - return _.intersection.apply(_, values); - }; - - that.or = function(values, items, context) { - return _.union.apply(_, values); - }; - - that.not = function(values, items, context) { // values[0] is array - var tmpResult = items.slice(); - return _.difference(tmpResult, values[0]); - }; - - that.notEq = function(value, items, context) { - var tmpResult = [], - tmpResult2, - length, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - if( context ) { - tmpResult2 = []; - if( items[i][context] === undefined ) { - length = -1; - } else { - length = items[i][context].length; - } - for( var j = 0, jj = length; j < jj; j += 1 ) { - if( globalUI.getPropertyValue( items[i][context][j], value[0] ) !== value[1] ) { - tmpResult2.push( items[i] ); - } - } - if( length === tmpResult2.length ) { - tmpResult.push( items[i] ); - } - } else { - if( globalUI.getPropertyValue( items[i], value[0] ) !== value[1] ) { - tmpResult.push( items[i] ); - } - } - } - return tmpResult; - }; - // compare for numbers and dates - that.gt = function(value, items, context) { // value is array: value[0] - param, value[1] - value - var tmpResult = [], - tmpResult2, - length, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - if( context ) { - tmpResult2 = []; - if( items[i][context] === undefined ) { - length = -1; - } else { - length = items[i][context].length; - } - for( var j = 0, jj = length; j < jj; j += 1 ) { - if( globalUI.getPropertyValue( items[i][context][j], value[0] ) > value[1] ) { - tmpResult2.push( items[i] ); - } - } - if( length === tmpResult2.length ) { - tmpResult.push( items[i] ); - } - } else { - if( globalUI.getPropertyValue( items[i], value[0] ) > value[1] ) { - tmpResult.push( items[i] ); - } - } - } - return tmpResult; - }; - // compare for numbers and dates - that.gte = function(value, items, context) { // value is array: value[0] - param, value[1] - value - var tmpResult = [], - tmpResult2, - length, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - if( context ) { - tmpResult2 = []; - if( items[i][context] === undefined ) { - length = -1; - } else { - length = items[i][context].length; - } - for( var j = 0, jj = length; j < jj; j += 1 ) { - if( globalUI.getPropertyValue( items[i][context][j], value[0] ) >= value[1] ) { - tmpResult2.push( items[i] ); - } - } - if( length === tmpResult2.length ) { - tmpResult.push( items[i] ); - } - } else { - if( globalUI.getPropertyValue( items[i], value[0] ) >= value[1] ) { - tmpResult.push( items[i] ); - } - } - } - return tmpResult; - }; - // compare for numbers and dates - that.lt = function(value, items, context) { // value is array: value[0] - param, value[1] - value - var tmpResult = [], - tmpResult2, - length, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - if( context ) { - tmpResult2 = []; - if( items[i][context] === undefined ) { - length = -1; - } else { - length = items[i][context].length; - } - for( var j = 0, jj = length; j < jj; j += 1 ) { - if( globalUI.getPropertyValue( items[i][context][j], value[0] ) < value[1] ) { - tmpResult2.push( items[i] ); - } - } - if( length === tmpResult2.length ) { - tmpResult.push( items[i] ); - } - } else { - if( globalUI.getPropertyValue( items[i], value[0] ) < value[1] ) { - tmpResult.push( items[i] ); - } - } - } - return tmpResult; - }; - // compare for numbers and dates - that.lte = function(value, items, context) { // value is array: value[0] - param, value[1] - value - var tmpResult = [], - tmpResult2, - length, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - if( context ) { - tmpResult2 = []; - if( items[i][context] === undefined ) { - length = -1; - } else { - length = items[i][context].length; - } - for( var j = 0, jj = length; j < jj; j += 1 ) { - if( globalUI.getPropertyValue( items[i][context][j], value[0] ) <= value[1] ) { - tmpResult2.push( items[i] ); - } - } - if( length === tmpResult2.length ) { - tmpResult.push( items[i] ); - } - } else { - if( globalUI.getPropertyValue( items[i], value[0] ) <= value[1] ) { - tmpResult.push( items[i] ); - } - } - } - return tmpResult; - }; - - that.in = function(values, items, context) { // values[1] is array - var tmpResult = [], - tmpResult2, - length, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - if( context ) { - tmpResult2 = []; - if( items[i][context] === undefined ) { - length = -1; - } else { - length = items[i][context].length; - } - for( var j = 0, jj = length; j < jj; j += 1 ) { - if( _.indexOf( values[1], globalUI.getPropertyValue( items[i][context][j], values[0] ) ) !== -1 ) { - tmpResult2.push( items[i] ); - } - } - if( length === tmpResult2.length ) { - tmpResult.push( items[i] ); - } - } else { - if( _.indexOf( values[1], globalUI.getPropertyValue( items[i], values[0] ) ) !== -1 ) { - tmpResult.push( items[i] ); - } - } - } - return tmpResult; - }; - - that.notIn = function(values, items, context) { // values[1] is array - var tmpResult = [], - tmpResult2, - length, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - if( context ) { - tmpResult2 = []; - if( items[i][context] === undefined ) { - length = -1; - } else { - length = items[i][context].length; - } - for( var j = 0, jj = length; j < jj; j += 1 ) { - if( _.indexOf( values[1], globalUI.getPropertyValue( items[i][context][j], values[0] ) ) === -1 ) { - tmpResult2.push( items[i] ); - } - } - if( length === tmpResult2.length ) { - tmpResult.push( items[i] ); - } - } else { - if( _.indexOf( values[1], globalUI.getPropertyValue( items[i], values[0] ) ) === -1 ) { - tmpResult.push( items[i] ); - } - } - } - return tmpResult; - }; - - that.exists = function(value, items, context) { // value[1] is string - var tmpResult = [], - tmpValue, - globalUI = InfinniUI.ObjectUtils; - - if( value[1] === undefined ) { - value[1] = true; - } - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpValue = globalUI.getPropertyValue( items[i], value[0] ); - if( value[1] === true ) { - if( !_.isUndefined(tmpValue) && !_.isNull(tmpValue) ) { - tmpResult.push( items[i] ); - } - } else { - if( _.isUndefined(tmpValue) || _.isNull(tmpValue) ) { - tmpResult.push( items[i] ); - } - } - } - return tmpResult; - }; - - that.match = function(values, items, context) { - var tmpResult = [], - globalUI = InfinniUI.ObjectUtils; - for( var i = 0, ii = values[1].length; i < ii; i += 1 ) { - if( globalUI.getPropertyValue( values[1][i], values[0] ) !== undefined ) { - tmpResult.push( values[1][i] ); - } - } - return tmpResult; - }; - - that.all = function(values, items, context) { // value[1] is array - var tmpResult = [], - counter, - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], values[0] ); - counter = 0; - for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { - if( _.indexOf( values[1], tmpArr[j] ) !== -1 ) { - counter += 1; - } - } - if( jj === counter ) { - tmpResult.push( items[i] ); - } - } - return tmpResult; - }; - - that.anyIn = function(values, items, context) { // value[1] is array - var tmpResult = [], - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], values[0] ); - for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { - if( _.indexOf( values[1], tmpArr[j] ) !== -1 ) { - tmpResult.push( items[i] ); - break; - } - } - } - return tmpResult; - }; - - that.anyNotIn = function(values, items, context) { // value[1] is array - var tmpResult = [], - counter, - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], values[0] ); - counter = 0; - for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { - if( _.indexOf( values[1], tmpArr[j] ) !== -1 ) { - counter += 1; - } - } - if( counter === 0 ) { - tmpResult.push( items[i] ); - } - } - return tmpResult; - }; - - that.anyEq = function(value, items, context) { - var tmpResult = [], - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], value[0] ); - if( _.indexOf(tmpArr, value[1]) !== -1 ) { - tmpResult.push( items[i] ); - } - } - return tmpResult; - }; - - that.anyNotEq = function(value, items, context) { - var tmpResult = [], - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], value[0] ); - for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { - if( tmpArr[j] !== value[1] ) { - tmpResult.push( items[i] ); - break; - } - } - } - return tmpResult; - }; - - that.anyGt = function(value, items, context) { - var tmpResult = [], - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], value[0] ); - for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { - if( tmpArr[j] > value[1] ) { - tmpResult.push( items[i] ); - break; - } - } - } - return tmpResult; - }; - - that.anyGte = function(value, items, context) { - var tmpResult = [], - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], value[0] ); - for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { - if( tmpArr[j] >= value[1] ) { - tmpResult.push( items[i] ); - break; - } - } - } - return tmpResult; - }; - - that.anyLt = function(value, items, context) { - var tmpResult = [], - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], value[0] ); - for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { - if( tmpArr[j] < value[1] ) { - tmpResult.push( items[i] ); - break; - } - } - } - return tmpResult; - }; - - that.anyLte = function(value, items, context) { - var tmpResult = [], - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], value[0] ); - for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { - if( tmpArr[j] <= value[1] ) { - tmpResult.push( items[i] ); - break; - } - } - } - return tmpResult; - }; - - that.sizeEq = function(value, items, context) { - var tmpResult = [], - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], value[0] ); - if( tmpArr.length === value[1] ) { - tmpResult.push( items[i] ); - } - } - return tmpResult; - }; - - that.sizeNotEq = function(value, items, context) { - var tmpResult = [], - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], value[0] ); - if( tmpArr.length !== value[1] ) { - tmpResult.push( items[i] ); - } - } - return tmpResult; - }; - - that.sizeGt = function(value, items, context) { - var tmpResult = [], - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], value[0] ); - if( tmpArr.length > value[1] ) { - tmpResult.push( items[i] ); - } - } - return tmpResult; - }; - - that.sizeGte = function(value, items, context) { - var tmpResult = [], - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], value[0] ); - if( tmpArr.length >= value[1] ) { - tmpResult.push( items[i] ); - } - } - return tmpResult; - }; - - that.sizeLt = function(value, items, context) { - var tmpResult = [], - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], value[0] ); - if( tmpArr.length < value[1] ) { - tmpResult.push( items[i] ); - } - } - return tmpResult; - }; - - that.sizeLte = function(value, items, context) { - var tmpResult = [], - tmpArr, - globalUI = InfinniUI.ObjectUtils; - - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpArr = globalUI.getPropertyValue( items[i], value[0] ); - if( tmpArr.length <= value[1] ) { - tmpResult.push( items[i] ); - } - } - return tmpResult; - }; - - that.regexp = function(values, items, context) { // value[1] is array - var tmpResult = [], - tmpObjValue, - globalUI = InfinniUI.ObjectUtils, - flags = '', - regexp; - for( var j = 1, jj = values[1].length; j < jj; j += 1 ) { - flags += values[1][j]; - } - regexp = new RegExp(values[1][0], flags); - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpObjValue = globalUI.getPropertyValue( items[i], values[0] ); - if( tmpObjValue.search(regexp) !== -1 ) { - tmpResult.push( items[i] ); - } - } - return tmpResult; - }; - - that.text = function(value, items, context) { - var tmpResult = [], - tmpString, - subString = value[0].replace('_', ' ').toLowerCase(); - for( var i = 0, ii = items.length; i < ii; i += 1 ) { - tmpString = JSON.stringify(items[i]).toLowerCase(); - if( tmpString.indexOf( subString ) !== -1 ) { - tmpResult.push( items[i] ); - } - } - return tmpResult; - }; - return that; -})(); - -//####app/utils/hashMap.js -/** - * @description Простая реализация хеша у которого в качестве ключей м.б. объект - * @constructor - */ -function HashMap() { - this._keys = []; - this._values = []; -} - -window.InfinniUI.HashMap = HashMap; - -Object.defineProperties(HashMap.prototype, /** @lends HashMap.prototype **/{ - length: { - get: function () { - return this._keys.length; - } - }, - keys: { - get: function () { - return this._keys; - } - }, - - values: { - get: function () { - return this._values; - } - } -}); - -HashMap.prototype.add = function (key, value) { - var i = this._getIndexOfKey(key); - - if (i === -1) { - this._keys.push(key); - this._values.push(value); - } else { - this._values[i] = value; - } -}; - -HashMap.prototype.remove = function (key) { - var i = this._getIndexOfKey(key); - - if (i !== -1) { - this._keys.splice(i, 1); - this._values.splice(i, 1); - } -}; - -HashMap.prototype.getKeyByValue = function (value) { - var key, - i = this._getIndexOfValue(value); - - if (i !== -1) { - key = this._keys[i]; - } - return key; -}; - -/** - * - * @param {Function} predicate - * @param thisArg - * @returns {numeric} - */ -HashMap.prototype.findIndex = function (predicate, thisArg) { - var key, value, index = -1; - for (var i = 0; i < this._keys.length; i = i + 1) { - key = this._keys[i]; - value = this._values[i]; - if (predicate.call(thisArg, key, value)) { - index = i; - break; - } - } - - return index; -}; - -HashMap.prototype.get = function (key) { - var value, - i = this._getIndexOfKey(key); - - if (i !== -1) { - value = this._values[i]; - } - - return value; -}; - -HashMap.prototype.forEach = function (callback, thisArg) { - this._keys.forEach(function (key, index) { - callback.call(thisArg, this._values[index], key, index); - }, this); -}; - -HashMap.prototype.clear = function (callback) { - if (typeof callback === 'function') { - this.forEach(callback); - } - this._keys.length = 0; - this._values.length = 0; -}; - -/** - * @param key - * @returns {number} - * @private - */ -HashMap.prototype._getIndexOfKey = function (key) { - return this._keys.indexOf(key); -}; - -/** - * @param {*} value - * @returns {number} - * @private - */ -HashMap.prototype._getIndexOfValue = function (value) { - return this._values.indexOf(value); -}; - -//####app/utils/hiddenScreen.js -function hiddenScreen() { - this.middleElement = $('
').css({ - 'position': 'absolute', - top: '-10000px' - }); -} -hiddenScreen.prototype = { - add: function (element) { - $('body').prepend(this.middleElement); - this.middleElement.append(element); - } -}; - -window.InfinniUI.hiddenScreen = hiddenScreen; - -//####app/utils/inheritance.js -_.mixin({ - 'inherit': function (child, parent) { - var f = new Function(); - f.prototype = parent.prototype; - - child.prototype = new f(); - child.prototype.constructor = child; - - child.superclass = parent.prototype; - }, - - 'superClass': function (obj, context, values) { - var args = _.toArray(arguments); - args.splice(0, 2); - - obj.superclass.constructor.apply(context, args); - } -}); -//####app/utils/isEqual.js -(function () { - var isEqual = _.isEqual; - _.isEqual = function(a, b) { - if (typeof File !== 'undefined') { - if (a instanceof File || b instanceof File) { - return a === b; - } - } - return isEqual(a, b); - }; - -})(); - -//####app/utils/keycodes.js -window.InfinniUI.Keyboard = { - KeyCode: { - ESCAPE: 27, - HOME: 36, - LEFT_ARROW: 37, - RIGHT_ARROW: 39, - END: 35, - UP_ARROW: 38, - DOWN_ARROW: 40, - DELETE: 46, - BACKSPACE: 8, - TAB: 9, - SPACE: 32, - NUMPAD_0: 96, - NUMPAD_1: 97, - NUMPAD_2: 98, - NUMPAD_3: 99, - NUMPAD_4: 100, - NUMPAD_5: 101, - NUMPAD_6: 102, - NUMPAD_7: 103, - NUMPAD_8: 104, - NUMPAD_9: 105, - PLUS: 43, - MINUS: 45, - ASTERISK: 42, - SLASH: 47, - 0: 48, - 1: 49, - 2: 50, - 3: 51, - 4: 52, - 5: 53, - 6: 54, - 7: 55, - 8: 56, - 9: 57 - }, - - getCharByKeyCode: function (keyCode) { - var char, code; - - if (keyCode < 32) { - //Спецсимвол - char = null; - } else { - //@see http://unixpapa.com/js/key.html - if (keyCode >= this.KeyCode.NUMPAD_0 && keyCode <= this.KeyCode.NUMPAD_9) { - code = keyCode - 48; - } else { - switch (keyCode) { - //convert numpad key codes - case 110: - code = this.KeyCode.DELETE; //.Del - break; - case 107: - code = this.KeyCode.PLUS; //+ - break; - case 109: - code = this.KeyCode.MINUS; //- - break; - case 106: - code = this.KeyCode.ASTERISK; //* - break; - case 111: - code = this.KeyCode.SLASH; // / - break; - //Symbol Keys - case 188: - code = 44; - break; - case 173: - code = 45; - break; - case 190: - code = 46; - break; - case 191: - code = 47; - break; - case 192: - code = 96; - break; - case 219: - code = 91; - break; - case 220: - code = 92; - break; - case 221: - code = 93; - break; - case 222: - code = 39; - break; - default: - code = keyCode; - } - } - char = String.fromCharCode(code); - } - return char; - } -}; -//####app/utils/layoutManager.js -var layoutManager = { - windowHeight: 0, - clientHeight: 0, - exchange: null, - times: [], - - setOuterHeight: function ($el, height, fix) { - var delta = 0; - 'border-top-width,border-bottom-width,padding-top,padding-bottom,margin-top,margin-bottom' - .split(',') - .forEach(function(name) { - delta += parseInt($el.css(name)); - }); - var contentHeight = height - delta; - if (fix) { - contentHeight += fix; - } - - //@TODO Разобраться с багом, при задании clearfix.height = 0 вылезает лишний 1 пиксел. Временное решение: - //contentHeight = (contentHeight > 0) ? contentHeight - 1 : contentHeight; - - $el.height(contentHeight); - - return contentHeight; - }, - - getModalSelector: function () { - return '.modal-scrollable'; - }, - - getSelector: function () { - //return '.pl-data-grid, .pl-scroll-panel, .pl-document-viewer, .pl-menu.vertical, .pl-tab-panel, .pl-treeview'; - return '.verticalAlignmentStretch:not(:hidden)'; - }, - - buildTree: function(items, parentEl, $parentEl, elements, list) { - var items = _.where(list, {parent: parentEl}), - manager = this; - - return { - isElement: _.indexOf(elements, parentEl) !== -1, - element: parentEl, - $element: $parentEl, - child: _.map(items, function (item) { - return manager.buildTree(items, item.element, item.$element, elements, list ); - }) - }; - }, - - formTree: function(elements, el, $el) { - var $parent, - list = [], - $element, - element; - //Строим дерево элементов: от концевых элементов поднимается к корневому элементу - for (var i = 0, ln = elements.length; i < ln; i = i + 1) { - element = elements[i]; - $element = $(element); - do { - $parent = $element.parent(); - - var a = _.findWhere(list, {element: element}); - if (typeof a !== 'undefined') { - //Элемент уже занесен в список - break; - } - list.push({ - element: element, - $element: $element, - parent: $parent.get(0), - $parent: $parent - }); - - $element = $parent; - element = $parent.get(0); - } while (element !== el); - } - - return this.buildTree(list, el, $el, elements, list); - }, - - setHeight: function (node, height) { - var originalHeight = node.$element.attr('data-height-original'); - if (originalHeight === '') { - node.$element.attr('data-height-original', node.element.style.height); - } - return this.setOuterHeight(node.$element, height); - }, - - defineWay: function(node, height) { - var nodeHeight = this.setHeight(node, height), - manager = this; - - if( node.$element.hasClass('pl-scroll-panel') || node.$element.hasClass('modal-scrollable') ) { - //Т.к. скроллпанель бесконечная по высоте, контролы внутри нее по высоте не растягиваем - return; - } else if( node.$element.hasClass('tab-content') ) { - _.each(node.child, function (node) { - manager.defineWay(node, nodeHeight); - }); - } else if( node.child.length > 0 ) { - this.goThroughTree(node, nodeHeight); - } - }, - - goThroughTree: function(node, height) { - var manager = this; - if( node.$element.parentsUntil('.modal').length ) { - node.$element.attr('data-height-original', node.element.style.height); - } - - var children = node.$element.children(':not(:hidden):not(.modal-scrollable):not(.modal-backdrop):not(.pl-dropdown-container)'), - /* - * @TODO Возможно правильнее исключать из обсчета все элементы с абсолютным позиционированием - */ - grid = _.chain(children) - .filter(function (el) { - var position = $(el).css('position'); - return ['absolute', 'fixed'].indexOf(position) === -1; - }) - .groupBy('offsetTop') - .value(), - - heights = []; - - _.each(grid, function (row, i) { - var nodes = []; - _.each(row, function (e) { - var n = _.find(node.child, function (c) {return c.element === e;}); - if (n) nodes.push(n); - }); - - heights.push(nodes.length ? 0 : _.reduce(row, function (height, e) { - return Math.max(height, $(e).outerHeight(true)); - }, 0)); - - grid[i] = nodes; - }, this); - - var fixedHeight = _.reduce(heights, function (total, height) {return total + height}, 0), - count = _.reduce(grid, function (count, row) {return row.length ? count + 1 : count}, 0), - - heightForNode = Math.floor((height - fixedHeight) / count); - - _.each(grid, function (row) { - if (row.length === 0) return; - _.each(row, function (node) { - manager.defineWay(node, heightForNode); - }, this); - }, this); - }, - - resize: function(el, pageHeight) { - var startTime = Date.now(); //start time - var $el = $(el), - contentHeight = this.setOuterHeight($el, pageHeight), - elements = $el.find(this.getSelector()); - - //var elements = Array.prototype.filter.call($el.find(this.getSelector()), function (element) { - // //Исключаем элементы которые долдны занитмать всю доступную высоту, - // // которые по какой-то причине оказались внутри ScrollPanel - // return $(element).parents('.pl-scrollpanel').length === 0; - //}); - if (elements.length === 0) { - return; - } - - var tree = this.formTree(elements, el, $el); - /** - * Если внутри child один элемент: - * - устанавливаем высоту в 100% - * Если внутри child несколько элементов - * - offsetTop совпадают - устанавливаем высоту в 100% - * - offsetTop не совпадают - устанавливаем высоту в (100 / child.length)% - */ - this.defineWay(tree, pageHeight); - var endTime = Date.now(); //end time - this.timeWatcher(endTime - startTime); - }, - - timeWatcher: function(time) { - if( time >= 20 ) { - this.times.push(time); - } - }, - - getTimes: function() { - return this.times; - }, - - resizeView: function (container, clientHeight) { - var $page = $('#page-content', container); - //$page.height(clientHeight); - var contentHeight = this.setOuterHeight($page, clientHeight); - var that = this; - - this.resize($page.get(0), contentHeight); - - //$page.children().each(function (i, el) { - // if (el.style.display !== 'none') { - // //Обработка активной вкладки - // var $tab = $(el); - // - // var $bar = $(".pl-active-bar:not(:hidden)", $tab); - // - // var barHeight = $bar.length ? $bar.outerHeight(true) : 0; - // //var barHeight = $(".pl-active-bar", $tab).outerHeight(true); - // $tab.children().each(function (i, el) { - // if (false === el.classList.contains('pl-active-bar') && el.style.display !== 'none') { - // var pageHeight = contentHeight - barHeight; - // that.resize(el, pageHeight); - // } - // }); - // } - //}); - }, - - resizeDialog: function () { - var manager = this; - $(this.getModalSelector()).each(function (i, el) { - manager._resizeDialog($(el)); - manager.resetDialogHeight($(el)); - }); - }, - - resetDialogHeight: function($modal){ - var space = 10; - - if($modal.children()) { - var $container = $modal.children(); - - var $header = $('.modal-header', $container); - var $body = $('.modal-body', $container); - - var $el = $(this.getSelector(), $modal); - - $el.parentsUntil('.modal').css('height', 'auto'); - $container.css('top', (this.windowHeight - $header.outerHeight(true) - $body.outerHeight(true)) / 2); - - $modal.children('.modal:not(.messagebox)').height($body.outerHeight(true) + $header.outerHeight(true)); - - } - - //var $header = $('.modal-header', $container); - //var $body = $('.modal-body', $container); - - //var headerHeight = $header.outerHeight(true); - // - //$container.css('margin-top', 0); - // - //var el = $(this.getSelector(), $modal); - //if (el.length === 0) { - // //Если диалог не содержит элементы которые должны растягиваться по вертикали на 100% - // //Выравниваем по вертикали в центр - // $container.css('top', (this.windowHeight - headerHeight - $body.outerHeight(true)) / 2); - // return; - //} - // - //$body.css('min-height', '0'); - //var containerHeight = this.setOuterHeight($modal, 'auto'); - // - ////Высота для содержимого окна диалога - //var clientHeight = this.setOuterHeight($container, containerHeight) - $header.outerHeight(); - // - //this.resize($body[0], clientHeight); - //$container.css('top', (this.windowHeight - headerHeight - clientHeight) / 2); - }, - - _resizeDialog: function ($modal) { - var space = 10;//Высота отступа от вертикальных границ диалога до границ экрана - - var $container = $modal.children(); - - $container.css('margin-top', 0); - //var marginTop = parseInt($container.css('margin-top'), 10); - - var $header = $('.modal-header', $container); - var $body = $('.modal-body', $container); - - var headerHeight = $header.outerHeight(true); - $body.css('max-height', this.windowHeight - headerHeight); - - $container.css('margin-top', 0); - - var el = $(this.getSelector(), $modal); - if (el.length !== 0) { - // Если диалог содержит элементы которые должны растягиваться по вертикали на 100% - // пересчитываем высоту - - //@TODO Зачем задавалась минимальная высота диалогов? - //$body.css('min-height', (this.windowHeight - $header.outerHeight(true) - space * 2) / 2); - var containerHeight = this.setOuterHeight($modal, this.windowHeight - space * 2); - - //Высота для содержимого окна диалога - var clientHeight = this.setOuterHeight($container, containerHeight) - $header.outerHeight(); - - this.resize($body[0], clientHeight); - } - }, - - init: function (container) { - if( window.InfinniUI.config.disableLayoutManager === true ) { - return false; - } - container = container || document; - $('#page-content').addClass('page-content-overflow-hidden'); - this.windowHeight = $(window).height(); - this.onChangeLayout(container); - if (this.exchange === null) { - this.exchange = window.InfinniUI.global.messageBus; - this.exchange.subscribe('OnChangeLayout', _.debounce(this.onChangeLayout.bind(this), 42)); - } - }, - - onChangeLayout: function (container) { - if (_.isEmpty(container)) { - container = document; - } - - var clientHeight = this.windowHeight - - $("#page-top:not(:hidden)", container).outerHeight() - - $("#page-bottom:not(:hidden)", container).outerHeight() - - $("#menu-area:not(:hidden)", container).outerHeight(); - this.resizeView(container, clientHeight); - this.resizeDialog(); - } -}; - -window.InfinniUI.LayoutManager = layoutManager; - -//####app/utils/logger.js -var LOG_LEVEL = { - debug: 1, - info: 2, - warn: 3, - error: 4, - trace: 5 -} - -function Logger(level){ - this.messages = []; - this.setLevel(level || LOG_LEVEL.debug); - - - this.showMessages = true; -}; - -_.extend(Logger.prototype, { - getLevel: function(){ - return this.level; - }, - - setLevel: function(level){ - this.level = level; - }, - - addMessage: function(messageType, message){ - this.messages.push({ - type: messageType, - message: message - }); - }, - - debug: function(message){ - if(this.level > LOG_LEVEL.debug){ - return; - } - - if(this.showMessages){ - console.debug(message.message || message); - } - - this.addMessage(LOG_LEVEL.debug, message); - }, - - info: function(message){ - if(this.level > LOG_LEVEL.info){ - return; - } - - if(this.showMessages){ - console.info(message.message || message); - } - - this.addMessage(LOG_LEVEL.info, message); - }, - - warn: function(message){ - if(this.level > LOG_LEVEL.warn){ - return; - } - - if(this.showMessages){ - console.warn(message.message || message); - } - - this.addMessage(LOG_LEVEL.warn, message); - }, - - error: function(message){ - if(this.level > LOG_LEVEL.error){ - return; - } - - if(this.showMessages){ - console.error(message.message || message); - } - - this.addMessage(LOG_LEVEL.error, message); - }, - - trace: function(message){ - if(this.level > LOG_LEVEL.trace){ - return; - } - - if(this.showMessages){ - console.error(message.message || message); - } - - this.addMessage(LOG_LEVEL.trace, message); - } -}) - -window.InfinniUI.global.logger = new Logger(); -//####app/utils/metadata.js -InfinniUI.Metadata = InfinniUI.Metadata || {}; - -InfinniUI.Metadata.isValidValue = function (value, metadata) { - var result = false; - for (var i in metadata) { - if (metadata[i] === value) { - result = true; - break; - } - } - - return result; -}; - -InfinniUI.Metadata.isBindingMetadata = function(metadata){ - return $.isPlainObject(metadata) && 'Source' in metadata; -}; -//####app/utils/numeric.js -Number.isInteger = Number.isInteger || function(value) { - return typeof value === "number" && - isFinite(value) && - Math.floor(value) === value; -}; -//####app/utils/stringUtils.js -if (!String.prototype.includes) { - String.prototype.includes = function() { - return String.prototype.indexOf.apply(this, arguments) !== -1; - }; -} - -var stringUtils = { - format: function(value,args){ - return value.replace(/{(\d+)}/g, function (match, number) { - return typeof args[number] != 'undefined' - ? args[number] - : match - ; - }); - }, - - formatProperty: function(property, indexes){ - if(!indexes || indexes.length == 0 || property == ''){ - return property; - } - - var propertyPaths = property.split('.'); - - var j = indexes.length-1; - - for(var i = propertyPaths.length-1; i>=0; i--){ - if(propertyPaths[i] == '#' && j >= 0){ - propertyPaths[i] = indexes[j]; - j--; - }else if(propertyPaths[i] == '$' || stringUtils.isNumeric(propertyPaths[i])){ - j--; - } - } - - return propertyPaths.join('.'); - }, - - padLeft: function a (value, len, char) { - if (typeof char == 'undefined' || char === null) { - char = ' '; - } - - var str = String(value); - - if (str.length < len) { - return new Array(len - str.length + 1).join(char) + str; - } - return str; - }, - - isNumeric: function(n) { - return !isNaN(parseFloat(n)) && isFinite(n); - }, - - replaced: { - '+': '%2B' - }, - - joinDataForQuery: function(data){ - var result = []; - var that = this; - - for(var k in data){ - var p = _.isString(data[k]) ? data[k].replace(/[\+]/g, function (c) { - return that.replaced[c] || c; - }) : data[k]; - - result.push(k + '=' + p); - } - - return result.join('&'); - } -}; - -window.InfinniUI.StringUtils = stringUtils; -window.InfinniUI.guid = guid; - -function guid() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); -} - -//####app/utils/testMode.js -(function (window, document, $) { - 'use strict'; - - var DATA_NAME_ATTRIBUTE = 'data-pl-name'; - var DATA_NAME_VIEW_ATTRIBUTE = 'data-pl-name-view'; - var NO_NAME = 'No name'; - var DATA_NAME_SELECTOR = '[' + DATA_NAME_ATTRIBUTE + ']:first'; - var DATA_NAME_VIEW_SELECTOR = '[' + DATA_NAME_VIEW_ATTRIBUTE + ']:first'; - - var location = window.location; - if (location.hash !== '#test') { - return; - } - - $(function () { - - patchBootstrapTooltip(); - var info = new InfoElement(); - - $(document).on('mouseover', function (event) { - info.setElement(event.target); - }); - - function patchBootstrapTooltip() { - $.fn.tooltip.Constructor.prototype.getTitle = function () { - var $e = this.$element; - var o = this.options; - - return o.title; - } - } - }); - - - /*************************************/ - - function ClickManager() { - this._unsubscribe = []; - } - - ClickManager.prototype.append = function (element, handler) { - var EVENT_NAME = 'contextmenu'; - this.clear(); - - if (typeof element === 'undefined' || element === null) { - return; - } - element.addEventListener(EVENT_NAME, handler, true); - this._unsubscribe.push(function () { - element.removeEventListener(EVENT_NAME, handler, true); - }); - return this; - }; - - ClickManager.prototype.clear = function () { - this._unsubscribe.forEach(function (fn) { - fn.call(); - }); - return this; - }; - - function InfoElement() { - this.marker = new Marker(); - this.$currentControl = null; - this.clickManager = new ClickManager(); - } - - InfoElement.prototype.setElement = function (el) { - var - $el = $(el), - $control = getControl($el), - name = getName($control), - viewName = getViewName($control); - - this.hideInfo(); - if ($control) { - this.showInfo($control, viewName, _.isEmpty(name) ? NO_NAME : name); - } - - function getControl($el) { - var $control; - - var name = $el.attr(DATA_NAME_ATTRIBUTE); - if (typeof name !== 'undefined') { - $control = $el; - } else { - $control = $el.parents(DATA_NAME_SELECTOR); - } - return $control; - } - - function getName($el) { - if ($el.length) { - return $el.attr(DATA_NAME_ATTRIBUTE); - } - } - - function getViewName($el) { - var $e = $el.parents(DATA_NAME_VIEW_SELECTOR); - if ($e.length) { - return $e.attr(DATA_NAME_VIEW_ATTRIBUTE); - } - } - }; - - InfoElement.prototype.copyInfo = function (viewName, name) { - if (viewName || name) { - window.prompt("Copy to clipboard: Ctrl+C", formatInfo(viewName, name)); - } - }; - - InfoElement.prototype.showInfo = function ($control, viewName, name) { - if (this.$currentControl && this.$currentControl[0] !== $control[0]) { - this.marker.reset(this.$currentControl); - this.clickManager.clear(); - } - this.marker.highlight($control); - this.$currentControl = $control; - this.clickManager.append($control[0], this.copyInfo.bind(this, viewName, name)); - - $control.tooltip({ - title: formatInfo(viewName, name), - placement: "auto" - }) - .tooltip('show'); - }; - - InfoElement.prototype.hideInfo = function () { - this.clickManager.clear(); - if (this.$currentControl) { - this.marker - .reset(this.$currentControl); - this.$currentControl.tooltip('destroy'); - } - }; - - - /********************************************/ - - function Marker() { - this.DATA_NAME = 'data-pl-original-style'; - - this.css = { - 'box-shadow': 'inset 0 0 1em #ff0000' - }; - } - - Marker.prototype.highlight = function ($el) { - var data; - - if ($el) { - data = $el.data(this.DATA_NAME); - if (!data) { - data = Object.create(null); - for (var i in this.css) { - data[i] = $el.css(i); - } - $el.data(this.DATA_NAME, data); - } - $el.css(this.css); - } - return this; - }; - - Marker.prototype.reset = function ($el) { - var data; - if ($el) { - data = $el.data(this.DATA_NAME); - $el.data(this.DATA_NAME, null); - if (data) { - $el.css(data); - } - } - return this; - }; - - - /********************/ - - function formatInfo(viewName, name) { - var info = viewName ? [viewName] : []; - info.push(name); - - return info.join(':'); - }; - - -})(window, document, jQuery); - - -//####app/utils/treeModel.js -var TreeModel = function(context, source, startTree){ - this.context = context; - this.source = source; - this.dataTree = startTree || {}; - - this.handlersTree = {}; - - this.mirroringFrom = null; - this.mirroringTo = null; -}; - -window.InfinniUI.TreeModel = TreeModel; - -_.extend(TreeModel.prototype, { - - counter: 1, - - getProperty: function(propertyName){ - if(this.mirroringFrom){ - propertyName = propertyName.replace(this.mirroringFrom, this.mirroringTo); - } - return InfinniUI.ObjectUtils.getPropertyValue(this.dataTree, propertyName) - }, - - setProperty: function(propertyName, value){ - var oldValue = this.getProperty(propertyName); - if(value == oldValue){ - return false; - } - - InfinniUI.ObjectUtils.setPropertyValue(this.dataTree, propertyName, value); - - this._notifyAboutPropertyChanged(propertyName, oldValue); - - return true; - }, - - onPropertyChanged: function(propertyName, handler, params){ - var handlersNode; - var bindId = this.counter + '-bindId'; - this.counter ++; - - if(_.isFunction(propertyName)){ - params = handler; - handler = propertyName; - - handlersNode = this._getHandlersSubTree('*', true); - }else{ - handlersNode = this._getHandlersSubTree(propertyName, true); - } - - handler._bindId = bindId; - if(params && 'owner' in params){ - handler._owner = params.owner; - } - - handlersNode[bindId] = handler; - }, - - _getHandlersSubTree: function(propertyName, restoreIfNoProperty){ - if(propertyName == ''){ - return this.handlersTree; - } - - var propertyPaths = propertyName.split('.'); - var tmpResult = this.handlersTree; - for(var i = 0, ii = propertyPaths.length; i 0){ - index = location.href.indexOf(searchPath); - if(index > 0){ - newUrl = location.href.substr(0, index); - } - } - - if(newUrl){ - history.pushState(null, null, newUrl); - } - - }, - - setParameter: function(name, value){ - var oldSearch = location.search; - var newSearch = _.isEmpty(oldSearch) ? - stringUtils.format("?{0}={1}", [name, value]) : - stringUtils.format("{0}&{1}={2}", [oldSearch, name, value]); - - var newUrl = stringUtils.format("{0}//{1}{2}{3}{4}",[location.protocol, location.host, location.pathname, newSearch, location.hash]); - - history.pushState(null, null, newUrl); - }, - - deleteParameter: function(name){ - var params = urlManager.getParams(); - delete params[name]; - - var newSearch = generateSearch(params); - - var newUrl = stringUtils.format("{0}//{1}{2}{3}{4}",[location.protocol, location.host, location.pathname, newSearch, location.hash]); - history.pushState(null, null, newUrl); - - function generateSearch(params){ - var paramsArray = []; - _.mapObject(params, function(val, key){ - var param = stringUtils.format("{0}={1}",[key, val]); - paramsArray.push( param ); - }); - - return _.isEmpty(paramsArray) ? - "" : - "?" + paramsArray.join("&"); - }; - } -}; - -window.InfinniUI.UrlManager = urlManager; -//####app/messaging/messageBus.js -function MessageBus(view) { - var subscriptions = {}; - - this.send = function (messageType, messageBody) { - messageType = patchMessageType(messageType); - if (subscriptions[messageType]) { - var context; - if (view && view.getContext) { - context = view.getContext(); - } - _.each(subscriptions[messageType], function (handler) { - handler(context, { value: messageBody }); - }); - } - }; - - this.subscribe = function (messageType, messageHandler) { - messageType = patchMessageType(messageType); - if (!subscriptions[messageType]) { - subscriptions[messageType] = []; - } - - subscriptions[messageType].push(messageHandler); - }; - - this.unsubscribeByType = function (messageType) { - messageType = patchMessageType(messageType); - if (subscriptions[messageType]) { - delete subscriptions[messageType]; - } - }; - - this.getView = function () { - return view; - }; - - function patchMessageType(messageType) { - - if (typeof messageType === 'object' && typeof messageType.name !== 'undefined') { - messageType = messageType.name; - } - - return messageType; - } -} - -window.InfinniUI.global.messageBus = new MessageBus(); -//####app/messaging/messageTypes.js -window.messageTypes = { - - onViewBuildError: {name: 'onViewBuildError'}, - onViewCreated: {name: 'onViewCreated'}, - - onChangeLayout: {name: 'OnChangeLayout'}, - onNotifyUser: {name: 'onNotifyUser'}, - onToolTip: {name: 'onToolTip'}, - - onContextMenu: {name: 'onContextMenu'}, - onOpenContextMenu: {name: 'onOpenContextMenu'}, - - onDataLoading: {name: 'onDataLoading'}, - onDataLoaded: {name: 'onDataLoaded'} - -}; - - -//####app/controls/_base/_mixins/ajaxRequestMixin.js -var ajaxRequestMixin = (function (bus) { - - function invokeCallback(cb, args) { - var result; - if (typeof cb === 'function') { - result = cb.apply(null, Array.prototype.slice.call(args)); - } - return result; - } - - return { - - onBeforeRequest: function (callback) { - return function () { - bus.send(messageTypes.onDataLoading, {}); - return invokeCallback(callback, arguments); - } - }, - - onSuccessRequest: function (callback) { - return function () { - bus.send(messageTypes.onDataLoaded, {success: true}); - return invokeCallback(callback, arguments); - } - }, - - onErrorRequest: function (callback) { - return function () { - bus.send(messageTypes.onDataLoaded, {success: false}); - return invokeCallback(callback, arguments); - } - } - } - -})(window.InfinniUI.global.messageBus); -//####app/controls/_base/_mixins/bindUIElementsMixin.js -var bindUIElementsMixin = { - /** - * Сохраняет в поле ui элементы по селектору в UI - * - * UI: {"name1": "selector1", "name2": "selector2"} - */ - bindUIElements: function () { - this.ui = {}; - - if (typeof this.UI === 'undefined') { - return; - } - - for (var i in this.UI) { - if (!this.UI.hasOwnProperty(i)) continue; - - this.ui[i] = this.$(this.UI[i]); - } - } -}; -//####app/controls/_base/_mixins/eventHandlerMixin.js -var eventHandlerMixin = { - - /** - * - * @param {String} name - * @callback handler - * @returns {boolean} - */ - addEventHandler: function (name, handler) { - - this.initEventHandlerMixin(); - - if (name === null || typeof name === 'undefined') { - return false; - } - - if (handler === null || typeof handler === 'undefined') { - return false; - } - - if (typeof this.eventHandlers[name] === 'undefined') { - this.eventHandlers[name] = []; - } - - var handlers = this.eventHandlers[name]; - - if (handlers.indexOf(handler) === -1) { - handlers.push(handler); - } - }, - - /** - * @description Вызывает обработчики указанного события. - * Формат вызова callEventHandler(name, [data],[handler]) - * @param {string} name Название события - * @param {Array} [data] Параметры, которые будут переданы в обработчик - * @callback [callback] Функцию в которую будут переданы результат вызова каждого обработчика - */ - callEventHandler: function (name) { - if (typeof this.eventHandlers === 'undefined' || name === null || typeof name === 'undefined') { - return; - } - var handlers = this.eventHandlers[name]; - - if (typeof handlers === 'undefined') { - return; - } - - var args = Array.prototype.slice.call(arguments, 1); - - var params = args.pop(); - var callback; - - if (typeof params === 'function') { - callback = params; - } - params = args.pop(); - - _.each(handlers, function (handler) { - var result = handler.apply(undefined, params); - if (typeof callback !== 'undefined') { - callback(result); - } - }); - }, - - /** - * @private - */ - initEventHandlerMixin: function () { - if (typeof this.eventHandlers === 'undefined') { - this.eventHandlers = {}; - } - } - - -}; -//####app/controls/_base/control/control.js -/** - * @description Базовый класс контролов - * @class Control - */ -var Control = function (viewMode) { - this.controlModel = this.createControlModel(); - this.controlView = this.createControlView(this.controlModel, viewMode); - - this.initHandlers(); - -}; - -_.extend(Control.prototype, { - - createControlModel: function () { - throw ('Не перегружен абстрактный метод Control.createControlModel()'); - }, - - createControlView: function (model, viewMode) { - throw ('Не перегружен абстрактный метод Control.createControlView()'); - }, - - initHandlers: function () { - this.controlView.on('onLoaded', function () { - this.controlModel.set('isLoaded', true); - }, this); - }, - - set: function (key, value) { - this.controlModel.set(key, value); - }, - - get: function (key) { - return this.controlModel.get(key); - }, - - on: function (name, handler) { - return this.controlModel.on(name, handler); - }, - - render: function () { - return this.controlView.render().$el; - }, - - getChildElements: function () { - return []; - }, - - onLoaded: function (handler) { - this.controlModel.on('change:isLoaded', function (isLoaded) { - if (isLoaded) { - handler(); - } - }); - }, - - isLoaded: function () { - return this.controlModel.get('isLoaded'); - }, - - onBeforeClick: function (handler) { - this.controlView.on('beforeClick', handler); - }, - - onClick: function (handler) { - this.controlView.$el.on('click', handler); - }, - - onDoubleClick: function (handler) { - this.controlView.$el.on('dblclick', handler); - }, - - onMouseDown: function (handler) { - this.controlView.$el.on('mousedown', handler); - }, - - onMouseUp: function (handler) { - this.controlView.$el.on('mouseup', handler); - }, - - onMouseEnter: function (handler) { - this.controlView.$el.on('mouseenter', handler); - }, - - onMouseLeave: function (handler) { - this.controlView.$el.on('mouseleave', handler); - }, - - onMouseMove: function (handler) { - this.controlView.$el.on('mousemove', handler); - }, - - onMouseWheel: function (handler) { - this.controlView.$el.on('mousewheel DOMMouseScroll', handler); - }, - - onKeyDown: function (handler) { - this.controlView.$el.on('keydown', handler); - }, - - onKeyUp: function (handler) { - this.controlView.$el.on('keyup', handler); - }, - - remove: function () { - this.controlView.remove(); - }, - - setFocus: function () { - this.controlView.setFocus(); - } -}); - -InfinniUI.Control = Control; -//####app/controls/_base/control/controlModel.js -var ControlModel = Backbone.Model.extend({ - defaults: { - text: null, - name: null, - enabled: true, - parentEnabled: true, - visible: true, - textHorizontalAlignment: InfinniUI.TextHorizontalAlignment.left, - horizontalAlignment: 'Stretch', - verticalAlignment: 'Top', - textStyle: null, - background: null, - foreground: null, - isLoaded: false, - validationState: 'success', - validationMessage: '', - focusable: true, - focused: false - }, - - initialize: function(){ - this.set('guid', guid(), {silent: true}); - this.on('change:focused', function (model, value) { - this.trigger(value ? 'OnGotFocus' : 'OnLostFocus'); - }); - }, - - set: function (key, val, options) { - var - defaults = this.defaults, - attrs; - - if (key == null) return this; - if (typeof key === 'object') { - attrs = key; - options = val; - } else { - (attrs = {})[key] = val; - } - - for (var name in attrs) { - if (typeof attrs[name] !== 'undefined' && attrs[name] !== null) { - continue; - } - - if (name in defaults) { - attrs[name] = defaults[name]; - } - } - return Backbone.Model.prototype.set.call(this, attrs, options); - } - -}); - -InfinniUI.ControlModel = ControlModel; -//####app/controls/_base/control/controlView.js -/** - * @class - * @augments Backbone.View - */ -var ControlView = Backbone.View.extend(/** @lends ControlView.prototype */{ - - initialize: function () { - this.wasRendered = false; - this.once('render', this.initHandlersForProperties, this); - this._initDomHandlers(); - - }, - - classNameFocused: 'pl-focused', - - _initDomHandlers: function () { - var - view = this, - $el = this.$el; - - $el[0].addEventListener('click', function (event) { - view.trigger('beforeClick', null, {value: event}); - }, true); - }, - - initHandlersForProperties: function () { - this.listenTo(this.model, 'change:visible', this.updateVisible); - this.listenTo(this.model, 'change:horizontalAlignment', this.updateHorizontalAlignment); - this.listenTo(this.model, 'change:textHorizontalAlignment', this.updateTextHorizontalAlignment); - this.listenTo(this.model, 'change:verticalAlignment', this.updateVerticalAlignment); - this.listenTo(this.model, 'change:enabled', this.updateEnabled); - this.listenTo(this.model, 'change:name', this.updateName); - this.listenTo(this.model, 'change:style', this.updateStyle); - this.listenTo(this.model, 'change:text', this.updateText); - - this.listenTo(this.model, 'change:textStyle', this.updateTextStyle); - this.listenTo(this.model, 'change:background', this.updateBackground); - this.listenTo(this.model, 'change:foreground', this.updateForeground); - - this.listenTo(this.model, 'change:validationState', this.updateValidationState); - - - this.listenTo(this.model, 'change:focusable', this.updateFocusable); - this.listenTo(this.model, 'change:focused', this.updateFocused); - - this.initFocusHandlers(); - }, - - initFocusHandlers: function () { - var $el = this.$el, - el = this.el, - view = this, - model = this.model; - - - $el - .on('focusin', onFocusIn) - .on('focusout', onFocusOut); - - function onFocusIn(event) { - model.set('focused', true); - } - - function onFocusOut(event) { - if (view.isControlElement(event.relatedTarget)) { - //focus out to element inside control - model.set('focused', true); - } else { - //focus out - model.set('focused', false); - } - } - }, - - isControlElement: function (el) { - return this.el === el || $.contains(this.el, el) - }, - - updateProperties: function () { - this.updateVisible(); - this.updateTextHorizontalAlignment(); - this.updateHorizontalAlignment(); - this.updateVerticalAlignment(); - this.updateEnabled(); - this.updateName(); - this.updateText(); - this.updateStyle(); - - this.updateTextStyle(); - this.updateBackground(); - this.updateForeground(); - - this.updateValidationState(); - - this.updateFocusable(); - this.updateFocused(); - - this.updateViewMode(); - }, - - /** - * @description Изменяет контрол в соответсвии со значением focusable. Напр. добавить tabindex="0" - */ - updateFocusable: function () { - - }, - - /** - * @description Возвращает элемент, который должен получить фокус - */ - getElementForFocus: function () { - return this.$el; - }, - - updateFocused: function () { - var focused = this.model.get('focused'); - - if (focused) { - var $el = this.getElementForFocus(); - if ($el && $el.length) { - //$el.focus(); - } - } - this.$el.toggleClass(this.classNameFocused, focused); - }, - - - onFocusHandler: function (event) { - //console.log('onFocus'); - }, - - - updateVisible: function () { - var isVisible = this.model.get('visible'); - this.$el - .toggleClass('hidden', !isVisible); - - this.onUpdateVisible(); - }, - - onUpdateVisible: function () { - this.updateLayout(); - }, - - updateLayout: function () { - var exchange = window.InfinniUI.global.messageBus; - exchange.send('OnChangeLayout', {}); - }, - - updateEnabled: function () { - var isEnabled = this.model.get('enabled'); - this.$el - .toggleClass('pl-disabled', !isEnabled); - }, - - updateVerticalAlignment: function () { - //var verticalAlignment = this.model.get('verticalAlignment'); - this.switchClass('verticalAlignment', this.model.get('verticalAlignment'), this.$el, false); - - //var prefix = 'verticalAlignment'; - //var regexp = new RegExp('(^|\\s)' + prefix + '\\S+', 'ig'); - // - //this.$el.removeClass(function (i, name) { - // return (name.match(regexp) || []).join(' '); - // }) - // .addClass(prefix + verticalAlignment); - }, - - updateTextHorizontalAlignment: function () { - this.switchClass('pl-text-horizontal', this.model.get('textHorizontalAlignment')); - }, - - updateHorizontalAlignment: function () { - this.switchClass('pl-horizontal', this.model.get('horizontalAlignment')); - }, - - updateName: function () { - var newName = this.model.get('name'), - currentName = this.$el.attr('data-pl-name'); - if (newName != currentName && typeof newName == 'string') { - this.$el.attr('data-pl-name', newName); - } - }, - - updateText: function () { - - }, - - updateTextStyle: function () { - var customStyle = this.model.get('textStyle'); - - if (this.currentTextStyle) { - this.$el - .removeClass(this.valueToTextClassName(this.currentTextStyle)); - } - - if (customStyle) { - this.$el - .addClass(this.valueToTextClassName(customStyle)); - } - - this.currentTextStyle = customStyle; - }, - - updateBackground: function () { - var customStyle = this.model.get('background'); - - if (this.currentBackground) { - this.$el - .removeClass(this.valueToBackgroundClassName(this.currentBackground)); - } - - if (customStyle) { - this.$el - .addClass(this.valueToBackgroundClassName(customStyle)); - } - - this.currentBackground = customStyle; - }, - - updateForeground: function () { - var customStyle = this.model.get('foreground'); - - if (this.currentForeground) { - this.$el - .removeClass(this.valueToForegroundClassName(this.currentForeground)); - } - - if (customStyle) { - this.$el - .addClass(this.valueToForegroundClassName(customStyle)); - } - - this.currentForeground = customStyle; - }, - - updateStyle: function () { - var customStyle = this.model.get('style'); - - if (this.currentStyle) { - this.$el - .removeClass(this.currentStyle); - } - - if (customStyle) { - this.$el - .addClass(customStyle); - } - - this.currentStyle = customStyle; - }, - - updateViewMode: function () { - if(this.viewMode == 'FormGroup' ){ - this.$el.addClass('pl-form-group'); - } - }, - - updateValidationState: function () { - var newState = this.model.get('validationState'), - message = this.model.get('validationMessage'); - switch (newState) { - - case 'success': - { - this.$el - .removeClass('has-warning has-error'); - this.hideErrorMessage(); - } - break; - - case 'warning': - { - this.$el - .removeClass('has-error') - .addClass('has-warning'); - this.showErrorMessage(message); - } - break; - - case 'error': - { - this.$el - .removeClass('has-warning') - .addClass('has-error'); - this.showErrorMessage(message); - } - break; - - } - - }, - - showErrorMessage: function (message) { - var $errorIcn = $(_.template('')({message: message})); - - this.hideErrorMessage(); - this.$el.find('.form-control:first') - .before($errorIcn); - - $errorIcn.tooltip({'container': 'body'}); - }, - - hideErrorMessage: function () { - this.$el.find('.error-icn') - .remove(); - }, - - rerender: function () { - if (this.wasRendered) { - this.render(); - } - }, - - prerenderingActions: function () { - this.wasRendered = true; - }, - - /** - * - * @param {Boolean} [onLoaded=true] - */ - postrenderingActions: function (triggeringOnLoaded) { - this.delegateEvents(); - - triggeringOnLoaded = triggeringOnLoaded === undefined ? true : triggeringOnLoaded; - - if (triggeringOnLoaded) { - this.trigger('onLoaded'); - } - }, - - switchClass: function (name, value, $el, separator) { - if (typeof separator === 'undefined') { - separator = '-'; - } else if (separator === false) { - separator = ''; - } - - var startWith = name + separator; - var regexp = new RegExp('(^|\\s)' + startWith + '\\S+', 'ig'); - var $element = $el || this.$el; - $element.removeClass(function (i, name) { - return (name.match(regexp) || []).join(' '); - }) - .addClass(startWith + value); - }, - - valueToBackgroundClassName: function (value) { - return 'pl-' + value.toLowerCase() + '-bg'; - }, - - valueToForegroundClassName: function (value) { - return 'pl-' + value.toLowerCase() + '-fg'; - }, - - valueToTextClassName: function (value) { - return 'pl-' + value.toLowerCase(); - }, - - renderTemplate: function (template) { - var data = this.getData(); - this.$el.html(template(data)); - this.bindUIElements(); - }, - - getData: function () { - var model = this.model; - return { - name: model.get('name'), - text: model.get('text'), - focusable: model.get('focusable'), - focused: model.get('focused'), - enabled: model.get('enabled'), - visible: model.get('visible'), - horizontalAlignment: model.get('horizontalAlignment'), - verticalAlignment: model.get('verticalAlignment'), - textHorizontalAlignment: model.get('textHorizontalAlignment'), - textVerticalAlignment: model.get('textVerticalAlignment'), - textStyle: model.get('textStyle'), - foreground: model.get('foreground'), - background: model.get('background') - } - }, - - setFocus: function () { - this.$el.focus(); - } - -}); - -_.extend(ControlView.prototype, bindUIElementsMixin, eventHandlerMixin); - -InfinniUI.ControlView = ControlView; - -//####app/controls/_base/button/buttonControlMixin.js -var buttonControlMixin = { - - click: function () { - this.controlView.$el.click(); - } - -}; -//####app/controls/_base/container/containerControl.js -/** - * - * @param parent - * @constructor - * @augments Control - */ -function ContainerControl(viewMode) { - _.superClass(ContainerControl, this, viewMode); -} - -_.inherit(ContainerControl, Control); - -_.extend(ContainerControl.prototype, {}); -//####app/controls/_base/container/containerModel.js -/** - * @constructor - * @augments ControlModel - */ -var ContainerModel = ControlModel.extend( - - /** @lends ContainerModel.prototype */ - { - defaults: _.defaults({ - //items: new Collection() - itemTemplate: null - }, ControlModel.prototype.defaults), - - initialize: function () { - ControlModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - this.set('items', new Collection()); - } - } -); - - - - -//####app/controls/_base/container/containerView.js -/** - * @class - * @augments ControlView - */ -var ContainerView = ControlView.extend( - /** @lends ContainerView.prototype */ - { - initialize: function (options) { - ControlView.prototype.initialize.call(this, options); - - this.childElements = []; - - this.listenTo(this.model, 'change:groupValueSelector', this.updateGrouping); - this.updateGrouping(); - }, - - updateGrouping: function(){ - throw 'ContainerView.updateGrouping В потомке ContainerView не реализовано обновление группировок.'; - }, - - initHandlersForProperties: function(){ - ControlView.prototype.initHandlersForProperties.call(this); - - var that = this; - this.model.get('items').onChange(function(event){ - switch (event.action) { - case 'replace': - break; - default: - that.rerender(); - } - }); - }, - - removeChildElements: function(){ - for(var i = 0, ii = this.childElements.length; i < ii; i++){ - this.childElements[i].remove(); - } - - this.childElements = []; - }, - - addChildElement: function(child){ - this.childElements.push(child); - } - } -); -//####app/controls/_base/editorBase/editorBaseControlMixin.js -var editorBaseControlMixin = { - - initialize_editorBaseControl: function(){ - - }, - - setValue: function (value) { - this.controlModel.set('value', value); - }, - - getValue: function () { - return this.controlModel.get('value'); - }, - - onValueChanging: function (handler) { - this.controlModel.onValueChanging(handler); - }, - - onValueChanged: function (handler) { - this.controlModel.onValueChanged(handler); - } -}; -//####app/controls/_base/editorBase/editorBaseModelMixin.js -var editorBaseModelMixin = { - - defaults_editorBaseModel: { - value: null, - hintText: null, - errorText: null, - warningText: null, - labelFloating: false - }, - - initialize_editorBaseModel: function(){ - this.eventManager = new EventManager(); - this.isInited = true; - }, - - transformValue: function (value) { - return value; - }, - - _applyDefaultValue: function (value) { - var defaults = _.result(this, 'defaults'); - return typeof value === 'undefined' ? defaults['value'] : value; - }, - - _setValue: function(value, options) { - value = this.transformValue(value); - - value = this._applyDefaultValue(value); - - var - oldValue = this.get('value'), - message = { - oldValue: oldValue, - newValue: value - }; - - if (value === oldValue) { - return; - } - - if(this.isInited){ - if (this.eventManager.trigger('onValueChanging', message)) { - ContainerModel.prototype.set.call(this, 'value', value, options || {}); - this.trigger('onValueChanged', message); - } - }else{ - ContainerModel.prototype.set.call(this, 'value', value, options || {}); - } - - }, - - set: function (key, value, options) { - var attributes, options; - if (key === null) { - return this; - } - - if (typeof key === 'object') { - attributes = key; - options = value; - } else { - (attributes = {})[key] = value; - } - - options = options || {}; - - if ('value' in attributes) { - this._setValue(attributes.value, options); - delete attributes.value; - } - - var hasAttributes = false; - - for (var i in attributes) { - hasAttributes = true; - break; - } - - if (hasAttributes) { - return ContainerModel.prototype.set.call(this, attributes, options); - } - - return false; - }, - - getValue: function () { - return this.get('value'); - }, - - isSetValue: function (value) { - return value !== null && typeof value !== 'undefined' && value !== ''; - }, - - onValueChanging: function (handler) { - this.eventManager.on('onValueChanging', handler); - }, - - onValueChanged: function (handler) { - this.on('onValueChanged', handler); - } -}; - -//####app/controls/_base/editorBase/editorBaseViewMixin.js -var editorBaseViewMixin = { - UI: { - hintText: '.pl-control-hint-text', - warningText: '.pl-control-warning-text', - errorText: '.pl-control-error-text' - }, - - getData: function () { - var model = this.model; - - return { - guid: model.get('guid') - } - }, - - initHandlersForProperties: function(){ - this.listenTo(this.model, 'onValueChanged', this.updateValue); - this.listenTo(this.model, 'change:hintText', this.updateHintText); - this.listenTo(this.model, 'change:errorText', this.updateErrorText); - this.listenTo(this.model, 'change:warningText', this.updateWarningText); - }, - - updateProperties: function(){ - this.updateValue(); - this.updateLabelFloating(); - this.updateHintText(); - this.updateErrorText(); - this.updateWarningText(); - }, - - - updateValue: function(){ - throw 'editorBaseViewMixin.updateValue В потомке editorBaseViewMixin не реализовано обновление данных.'; - }, - - updateValueState: function(){ - var value = this.model.get('value'); - var isEmpty = _.isEmpty(value) && !(_.isNumber(value)); - this.$el.toggleClass("pl-empty-text-editor", isEmpty); - }, - - updateLabelFloating: function () { - var labelFloating = this.model.get('labelFloating'); - this.$el.toggleClass("pl-label-floating", labelFloating === true); - }, - - updateHintText: function(){ - var hintText = this.model.get('hintText'); - if(hintText){ - this.ui.hintText - .text(hintText) - .removeClass('hidden'); - }else{ - this.ui.hintText - .text('') - .addClass('hidden'); - } - - }, - - updateErrorText: function(){ - var errorText = this.model.get('errorText'); - if(errorText){ - this.ui.errorText - .text(errorText) - .removeClass('hidden'); - }else{ - this.ui.errorText - .text('') - .addClass('hidden'); - } - - }, - - updateWarningText: function(){ - var warningText = this.model.get('warningText'); - if(warningText){ - this.ui.warningText - .text(warningText) - .removeClass('hidden'); - }else{ - this.ui.warningText - .text('') - .addClass('hidden'); - } - - }, - - updateEnabled: function () { - ControlView.prototype.updateEnabled.call(this); - - if(this.ui.control){ - var isEnabled = this.model.get('enabled'); - this.ui.control.prop('disabled', !isEnabled); - } - - }, - - onInvalidHandler: function (model, error) { - // что ита??? - // вот ето - @see {@link http://backbonejs.org/#Model-validate} !!! - - - //@TODO Можно ли использовать поля из API или реализовывать вывод ошибок отдельно? - //this.model.set('errorText', error); - } -}; - -//####app/controls/_base/listEditorBase/listEditorBaseControl.js -function ListEditorBaseControl(viewMode) { - _.superClass(ListEditorBaseControl, this, viewMode); - this.initialize_editorBaseControl(); -} - -_.inherit(ListEditorBaseControl, ContainerControl); - -_.extend(ListEditorBaseControl.prototype, { - - onSelectedItemChanged: function (handler) { - this.controlModel.onSelectedItemChanged(handler); - } -}, editorBaseControlMixin); -//####app/controls/_base/listEditorBase/listEditorBaseModel.js -var ListEditorBaseModel = ContainerModel.extend( _.extend({ - - defaults: _.defaults({ - multiSelect: false, - disabledItemCondition: null - }, ContainerModel.prototype.defaults), - - initialize: function () { - var that = this; - this.hashValueByItem = new HashMap(); - ContainerModel.prototype.initialize.apply(this, arguments); - this.initialize_editorBaseModel(); - - this.bindSelectedItemsWithValue(); - - this.get('items').onChange(function(){ - that.hashValueByItem.clear(); - }); - }, - - onSelectedItemChanged: function (handler) { - this.on('change:selectedItem', function(source, newSelectedItem){ - handler({value: newSelectedItem}); - }); - }, - - toggleValue: function (value, toggle) { - var - currentValue = this.get('value'), - multiSelect = this.get('multiSelect'), - index, clonedValue; - - if(multiSelect){ - currentValue = Array.isArray(currentValue) ? currentValue : []; - - var valueAsString = JSON.stringify(value); - - var newValue = currentValue.filter(function(val) { - return JSON.stringify(val) !== valueAsString; - }); - - if (typeof toggle === 'undefined' || toggle === true) { - if (newValue.length === currentValue.length) { - newValue.push(value); - } - } - - this.set('value', newValue); - - }else{ - if(value != currentValue){ - this.set('value', value); - } - } - }, - - bindSelectedItemsWithValue: function(){ - return; - //this.on('change:selectedItem', function (model, newSelectedItem) { - // var value = this.get('value'), - // newItemValue = this.valueByItem(newSelectedItem); - // - // if(!this.get('multiSelect') && !this.isStringifyEqualValues(newItemValue, value)){ - // this.set('value', newItemValue); - // } - //}, this); - // - //this.on('change:value', function (model, newValue) { - // var selectedItem = this.get('selectedItem'), - // newSelectedItem = this.itemByValue(newValue); - // - // if(!this.get('multiSelect') && selectedItem != newSelectedItem){ - // this.set('selectedItem', newSelectedItem); - // } - //}, this); - }, - - valueByItem: function(item){ - var valueSelector = this.get('valueSelector'); - if(!valueSelector){ - return item; - }else{ - return valueSelector(undefined, {value: item}); - } - }, - - itemInfoByValue: function(value){ - if (this.hashValueByItem.length === 0) { - this.updateHashValueByItem(); - } - var info, - index, - item = this.hashValueByItem.getKeyByValue(value); - - if (typeof item !== 'undefined') { - info = { - item: item, - index: this.hashValueByItem.keys.indexOf(item) - } - } else { - var text = JSON.stringify(value); - index = this.hashValueByItem.findIndex(function (item, value) { - return JSON.stringify(value) === text; - }); - - if (index !== -1) { - info = { - index: index, - item: this.hashValueByItem.keys[index] - } - } - } - - return info; - }, - - itemByValue: function(value){ - var itemInfo = this.itemInfoByValue(value); - - if(!itemInfo){ - return undefined; - }else{ - return itemInfo.item; - } - }, - - itemIndexByValue: function(value){ - var itemInfo = this.itemInfoByValue(value); - - if(!itemInfo){ - return -1; - }else{ - return itemInfo.index; - } - }, - - itemIndexByItem: function(item){ - var value = this.valueByItem(item); - return this.itemIndexByValue(value); - }, - - isDisabledItem: function(item){ - var disabledItemCondition = this.get('disabledItemCondition'); - return (disabledItemCondition != null) && disabledItemCondition(undefined, {value: item}); - }, - - updateHashValueByItem: function () { - var items = this.get('items'), - value; - this.hashValueByItem.clear(); - items.forEach(function (item) { - value = this.valueByItem(item); - this.hashValueByItem.add(item, value); - }, this); - } - -}, editorBaseModelMixin)); - -//####app/controls/_base/listEditorBase/listEditorBaseView.js -var ListEditorBaseView = ContainerView.extend( _.extend( {}, editorBaseViewMixin, { - - initHandlersForProperties: function(){ - ContainerView.prototype.initHandlersForProperties.call(this); - editorBaseViewMixin.initHandlersForProperties.call(this); - - this.listenTo(this.model, 'change:selectedItem', this.updateSelectedItem); - this.listenTo(this.model, 'change:multiSelect', this.updateMultiSelect); - this.listenTo(this.model, 'change:disabledItemCondition', this.updateDisabledItem); - }, - - updateProperties: function(){ - ContainerView.prototype.updateProperties.call(this); - editorBaseViewMixin.updateProperties.call(this); - - this.updateSelectedItem(); - this.updateMultiSelect(); - this.updateDisabledItem(); - }, - - updateMultiSelect: function () { - - } - -})); -//####app/controls/_base/textEditorBase/textEditorBaseControl.js -/** - * - * @param parent - * @constructor - * @augments Control - * @mixes editorBaseControlMixin - */ -function TextEditorBaseControl(parent) { - _.superClass(TextEditorBaseControl, this, parent); - this.initialize_editorBaseControl(); -} - -_.inherit(TextEditorBaseControl, Control); - -_.extend(TextEditorBaseControl.prototype, editorBaseControlMixin); -//####app/controls/_base/textEditorBase/textEditorBaseModel.js -/** - * @class - * @augments ControlModel - * @mixes editorBaseModelMixin - */ -var TextEditorBaseModel = ControlModel.extend(/** @lends TextEditorBaseModel.prototype */ { - defaults: _.defaults({ - labelText: null, - displayFormat: null, - editMask: null - }, - editorBaseModelMixin.defaults_editorBaseModel, - ControlModel.prototype.defaults), - - initialize: function () { - ControlModel.prototype.initialize.apply(this, arguments); - this.initialize_editorBaseModel(); - } -}); - -_.extend(TextEditorBaseModel.prototype, editorBaseModelMixin); - - -//####app/controls/_base/textEditorBase/textEditorBaseView.js -/** - * @class TextEditorBaseView - * @augments ControlView - * @mixed editorBaseViewMixin - */ - - -var TextEditorBaseView = ControlView.extend(/** @lends TextEditorBaseView.prototype */ _.extend({}, editorBaseViewMixin, { - - UI: _.extend({}, editorBaseViewMixin.UI, { - control: '.pl-control', - //editor: '.pl-control-editor', - editor: '.pl-editor', - label: '.pl-control-label', - textbox: '.pl-text-box-input' - }), - - events: { - - }, - - initialize: function () { - ControlView.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - }, - - initHandlersForProperties: function(){ - ControlView.prototype.initHandlersForProperties.call(this); - editorBaseViewMixin.initHandlersForProperties.call(this); - - this.listenTo(this.model, 'change:labelText', this.updateLabelText); - this.listenTo(this.model, 'change:labelFloating', this.updateLabelFloating); - this.listenTo(this.model, 'change:displayFormat', this.updateDisplayFormat); - this.listenTo(this.model, 'change:editMask', this.updateEditMask); - this.listenTo(this.model, 'change:inputType', this.updateInputType); - }, - - updateProperties: function(){ - ControlView.prototype.updateProperties.call(this); - editorBaseViewMixin.updateProperties.call(this); - - this.updateLabelText(); - this.updateInputType(); - }, - - updateFocusable: function () { - var focusable = this.model.get('focusable'); - - if (!focusable) { - this.ui.editor.attr('tabindex', -1); - } else { - this.ui.editor.removeAttr('tabindex'); - } - }, - - updateInputType: function () { - var inputType = this.model.get('inputType'); - var $editor = this.ui.editor; - var tagName = $editor.prop('tagName'); - if (inputType && tagName.toLowerCase() === 'input') { - $editor.attr('type', inputType); - } - }, - - updateEditMask: function(){ - this.updateValue(); - }, - - setFocus: function () { - this.ui.editor.focus(); - }, - - updateValue: function(){ - editorBaseViewMixin.updateValueState.call(this); - this.ui.control.val(this.getDisplayValue()); - }, - - updateLabelText: function(){ - var labelText = this.model.get('labelText'); - if(labelText){ - this.ui.label - .text(labelText) - .removeClass('hidden'); - }else{ - this.ui.label - .text('') - .addClass('hidden'); - } - - }, - - updateDisplayFormat: function(){ - this.updateValue(); - }, - - /** - * Рендеринг редактора значений - * - */ - renderControlEditor: function () { - var model = this.model; - var editor = model.get('editor'); - if (editor) { - editor.render(this.ui.editor); - } - }, - - getData: function () { - var model = this.model; - - return _.extend({}, - ControlView.prototype.getData.call(this), - editorBaseViewMixin.getData.call(this), { - labelText: model.get('labelText'), - labelFloating: model.get('labelFloating'), - value: this.getDisplayValue() - }); - }, - - getDisplayValue: function () { - var - model = this.model, - value = model.get('value'), - displayFormat = model.get('displayFormat'); - - return displayFormat ? displayFormat(null, {value: value}) : value; - } - -})); - -//####app/controls/_base/eventManager.js -function EventManager() { - this.handlers = {}; -} - -EventManager.prototype.on = function (name, handler) { - if (typeof this.handlers[name] === 'undefined') { - this.handlers[name] = []; - } - this.handlers[name].push(handler); - return this; -}; - -EventManager.prototype.trigger = function (name, message, context) { - var eventHandlers = this.handlers[name]; - var response = true; - if (Array.isArray(eventHandlers)) { - response = eventHandlers - .map(function (handler) { - return handler.call(context, message); - }) - .every(function (result) { - return result !== false; - }); - } - return response; -}; - -//####app/controls/_base/highlightMixin.js -var highlightMixin = { - - attributeName: '_highlight', - - highlightClassName: 'active', - - control: { - - setHighlight: function (highlight) { - this.controlModel.set(highlightMixin.attributeName, highlight); - }, - - getHighlight: function () { - return this.controlModel.get(highlightMixin.attributeName); - } - - }, - - controlView: { - - initHighlightMixin: function () { - this.listenTo(this.model, 'change:' + highlightMixin.attributeName, function () { - var model = this.model; - this.$el.toggleClass(highlightMixin.highlightClassName, model.get(highlightMixin.attributeName)); - this.$el.parent().toggleClass(highlightMixin.highlightClassName, model.get(highlightMixin.attributeName)); - }); - } - - } -}; - - -//####app/controls/_base/textEditor/textEditorModel.js -/** - * @TODO Если маска заполнена не полностью - не выходить из режима редактирования - */ -var TextEditorModel = Backbone.Model.extend({ - - Mode: { - Edit: 'edit', - Display: 'display' - }, - - initialize: function () { - - this.initEditMode(); - - this.on('change:originalValue', this.onChangeOriginalValueHandler); - this.on('change:value', this.onChangeValueHandler); - this.on('change:mode', this.onChangeModeHandler); - this.on('change:text', this.onChangeTextHandler); - }, - - onChangeTextHandler: function (model, value, options) { - var modeStrategy = this.get('modeStrategy'); - modeStrategy.onChangeTextHandler(model, value, options); - }, - - convertValue: function (value) { - var getConverter = this.get('valueConverter'); - var converter = getConverter.call(null); - return (typeof converter === 'function') ? converter.call(this, value) : value; - }, - - initEditMode: function () { - this.modeStrategies = {}; - this.modeStrategies[this.Mode.Edit] = new TextEditorModelEditModeStrategy(); - this.modeStrategies[this.Mode.Display] = new TextEditorModelDisplayModeStrategy(); - - this.updateEditModeStrategy(); - }, - - defaults: function () { - return { - mode: this.Mode.Display - }; - }, - - updateEditModeStrategy: function () { - var mode = this.get('mode'); - this.set('modeStrategy', this.modeStrategies[mode]); - }, - - onChangeModeHandler: function (model, mode, options) { - var prevMode = this.previous('mode'); - if (options.cancel) { - this.cancelChanges(); - } else if (mode === this.Mode.Display && prevMode === this.Mode.Edit) { - //При успешном переходе из режима редактирования в режим отображения - обновляем исходное значение - this.applyChanges(); - } - - this.updateEditModeStrategy(); - this.updateText(); - }, - - /** - * - * @param {boolean} [cancel = false] - * @param {boolean} [validate = true] - */ - setDisplayMode: function (cancel, validate) { - cancel = !!cancel; - validate = (typeof validate === 'undefined') ? true : !!validate; - - this.set('mode', this.Mode.Display, { - cancel: cancel, - validate: validate - }); - - }, - - applyChanges: function () { - this.set('originalValue', this.get('value')); - }, - - cancelChanges: function () { - this.set('value', this.get('originalValue')); - }, - - /** - * - * @param text - * @param {boolean} [ui = false] - */ - setText: function (text, ui) { - var modeStrategy = this.get('modeStrategy'); - modeStrategy.setText(this, text, ui); - }, - - getEditMask: function () { - return this.get('editMask'); - }, - - getValue: function () { - return this.get('value'); - // - // - //var editMask = this.getEditMask(); - //var value; - // - //if (editMask) { - // value = editMask.getValue() - //} else { - // value = this.$el.val(); - //} - - //return value; - }, - - getDisplayFormat: function () { - return this.get('displayFormat'); - }, - - setEditMode: function () { - this.set('mode', this.Mode.Edit); - }, - - validate: function (attrs, options) { - - //@TODO Если меняется Mode Edit => Display, проверить введенное значение!!! - var validateValue = this.get('validateValue'), - value = this.getValue(); - - if (_.isFunction(validateValue)) { - return validateValue.call(null, value); - } - }, - - updateText: function () { - var modeStrategy = this.get('modeStrategy'); - modeStrategy.updateText(this); - }, - - onChangeValueHandler: function (model, value, options) { - if (!options.ui) { - this.updateText(); - } - - }, - - onChangeOriginalValueHandler: function (model, value) { - model.set('value', value, {originalValue: true}); - } - -}); -//####app/controls/_base/textEditor/textEditorView.js -var TextEditorView = Backbone.View.extend({ - - /** - * @member {TextEditorModel} model - */ - - classNameError: 'has-error', - - events: { - 'focusin': 'onFocusinHandler', - 'focusout': 'onFocusoutHandler', - 'keydown': 'onKeydownHandler', - 'change': 'onChangeHandler', - 'input': 'onInputHandler', - 'keyup': 'onKeyupHandler', //trigger OnKeyDown Event - 'click': 'onClickHandler', - 'drop': 'onDropHandler', - 'dragstart': 'OnDragstartHandler', - 'dragend': 'OnDragendHandler', - 'dragover': 'OnDragoverHandler', - 'dragleave': 'OnDragleaveHandler', - 'dragenter': 'OnDragenterHandler', - 'paste': 'onPasteHandler' - }, - - updateModelTextFromEditor: function () { - var model = this.model, - editMask = model.getEditMask(); - - if (!editMask) { - model.setText(this.$el.val(), true); - } - }, - - onChangeHandler: function () { - //Обработка для корректной обработки автозаполняемых полей - this.updateModelTextFromEditor(); - }, - - onInputHandler: function () { - var editMask = this.model.getEditMask(); - if (!editMask) { - this.updateModelTextFromEditor(); - } - }, - - onKeydownHandler: function (event) { - if (event.ctrlKey || event.altKey) { - return; - } - - if (event.which === InfinniUI.Keyboard.KeyCode.ESCAPE) { - //Отменить изменения и выйти из режима редактирования - this.model.setDisplayMode(true, false); - this.$el.blur(); - return; - } - - var editMask = this.model.getEditMask(); - if (!editMask) { - //model.text будет изменено в обработчике onInputHandler - return; - } - - var model = this.model; - var position; - - switch (event.which) { - case InfinniUI.Keyboard.KeyCode.TAB: - break; - case InfinniUI.Keyboard.KeyCode.HOME: - if (!event.shiftKey) { - position = editMask.moveToPrevChar(0); - if (position !== false) { - event.preventDefault(); - this.setCaretPosition(position); - } - } - - break; - - case InfinniUI.Keyboard.KeyCode.LEFT_ARROW: - if (!event.shiftKey) { - position = editMask.moveToPrevChar(this.getCaretPosition()); - if (position !== false) { - event.preventDefault(); - this.setCaretPosition(position); - } - } - break; - - case InfinniUI.Keyboard.KeyCode.RIGHT_ARROW: - if (!event.shiftKey) { - position = editMask.moveToNextChar(this.getCaretPosition()); - if (position !== false) { - event.preventDefault(); - this.setCaretPosition(position); - } - } - break; - - case InfinniUI.Keyboard.KeyCode.END: - if (!event.shiftKey) { - position = editMask.moveToNextChar(this.$el.val().length); - if (position !== false) { - event.preventDefault(); - this.setCaretPosition(position); - } - } - break; - - case InfinniUI.Keyboard.KeyCode.UP_ARROW: - if (!event.shiftKey) { - position = editMask.setNextValue(this.getCaretPosition()); - if (position !== false) { - event.preventDefault(); - model.setText(editMask.getText()); - this.setCaretPosition(position); - } - } - break; - - case InfinniUI.Keyboard.KeyCode.DOWN_ARROW: - if (!event.shiftKey) { - position = editMask.setPrevValue(this.getCaretPosition()); - if (position !== false) { - event.preventDefault(); - this.model.setText(editMask.getText()); - this.setCaretPosition(position); - } - } - break; - - case InfinniUI.Keyboard.KeyCode.DELETE: - event.preventDefault(); - position = editMask.deleteCharRight(this.getCaretPosition(), this.getSelectionLength()); - - this.model.setText(editMask.getText()); - if (position !== false) { - this.setCaretPosition(position); - } - break; - - case InfinniUI.Keyboard.KeyCode.BACKSPACE: - event.preventDefault(); - position = editMask.deleteCharLeft(this.getCaretPosition(), this.getSelectionLength()); - - this.model.setText(editMask.getText()); - if (position !== false) { - this.setCaretPosition(position); - } - break; - - case InfinniUI.Keyboard.KeyCode.SPACE: - if (editMask.value instanceof Date) { - event.preventDefault(); - position = editMask.getNextItemMask(this.getCaretPosition()); - if (position !== false) { - this.setCaretPosition(position); - } - } - break; - - default: - //замена выделенного текста, по нажатию - var char = InfinniUI.Keyboard.getCharByKeyCode(event.keyCode); - event.preventDefault(); - if (this.getSelectionLength() > 0) { - position = editMask.deleteSelectedText(this.getCaretPosition(), this.getSelectionLength(), char); - } else { - //Ввод символа - position = editMask.setCharAt(char, this.getCaretPosition(), this.getSelectionLength()); - } - - this.model.setText(editMask.getText()); - if (position !== false) { - this.setCaretPosition(position); - } - break; - } - - - }, - - onKeyupHandler: function (event) { - - this.trigger('onKeyDown', { - keyCode: event.which, - value: this.model.getValue() - }); - }, - - onClickHandler: function (event) { - this.checkCurrentPosition(); - event.preventDefault(); - }, - - onPasteHandler: function (event) { - var originalEvent = event.originalEvent; - var text = originalEvent.clipboardData.getData('text/plain'); - var editMask = this.model.getEditMask(); - - if (editMask) { - event.preventDefault(); - this.textTyping(text); - } - }, - - OnDragstartHandler: function (event) { - var originalEvent = event.originalEvent; - originalEvent.dataTransfer.effectAllowed = 'copy'; - this.$el.attr('data-dragged', true); - }, - - OnDragendHandler: function (/*event*/) { - this.$el.removeAttr('data-dragged', false); - }, - - OnDragoverHandler: function (event) { - event.preventDefault(); - }, - - OnDragenterHandler: function (event) { - var dragged = this.$el.attr('data-dragged'); - - if (!dragged && this.getCanChange()) { - this.model.setEditMode(); - } - }, - - OnDragleaveHandler: function (event) { - var dragged = this.$el.attr('data-dragged'); - - if (!dragged) { - this.model.setDisplayMode(); - } - }, - - onDropHandler: function (event) { - event.preventDefault(); - event.stopPropagation(); - var dragged = this.$el.attr('data-dragged'); - - if (dragged) { //prevent drop on self - return; - } - - if (!this.getCanChange()) { - return; - } - - var originalEvent = event.originalEvent; - var text = originalEvent.dataTransfer.getData('text/plain'); - - - - this.textTyping(text, 0); - this.$el.focus(); - }, - - getCanChange: function () { - var disabled = this.$el.prop('disabled'); - - return disabled === false; - }, - - /** - * @description Заполняет поле ввода строкой text начиная с позиции position - * @protected - * - * @param {string} text - * @param {number} [position] - */ - textTyping: function (text, position) { - var editMask = this.model.getEditMask(); - var newText = text; - - if (editMask) { - text.split('') - .reduce(function (pos, char) { - return editMask.setCharAt(char, pos); - }, _.isNumber(position) ? position : this.getCaretPosition()); - - newText = editMask.getText(); - } - - this.model.setText(newText); - }, - - checkCurrentPosition: function (currentPosition) { - - if (!this.canCaretPosition()) { - return; - } - var editMask = this.model.getEditMask(); - if (!editMask) { - return; - } - - if (typeof currentPosition === 'undefined') { - currentPosition = this.getCaretPosition(); - } - - var position = currentPosition === 0 ? editMask.moveToPrevChar(0) : editMask.moveToNextChar(currentPosition - 1); - if (position !== currentPosition) { - this.setCaretPosition(position); - } - - }, - - getSelectionLength: function () { - var el = this.el, - len = 0; - - if (this.canCaretPosition()) { - var startPos = parseInt(el.selectionStart, 10), - endPos = parseInt(el.selectionEnd, 10); - - if (!isNaN(startPos) && !isNaN(endPos)) { - len = endPos - startPos; - } - } - - return len; - }, - - canCaretPosition: function () { - return (/text|password|search|tel|url/).test(this.el.type); - }, - - setCaretPosition: function (caretPosition) { - - if (_.isNumber(caretPosition) && this.canCaretPosition()) { - var el = this.el; - - //IE9+ - if (typeof el.selectionStart !== 'undefined') { - el.setSelectionRange(caretPosition, caretPosition); - } - } - - }, - - /** - * @private - * Получение позиции курсора в поле редактирования - * @returns {number} - */ - getCaretPosition: function () { - /** @var {HTMLInputElement} **/ - var el = this.el; - - var position = 0; - - if (this.canCaretPosition()) { - position = el.selectionStart; - } - - return position; - }, - - initialize: function () { - this.applyAutocomplete(); - this.listenTo(this.model, 'change:mode', this.onChangeModeHandler); - this.listenTo(this.model, 'change:text', this.onChangeTextHandler); - this.listenTo(this.model, 'invalid', this.onInvalidHandler); - }, - - /** - * @description Для элементов с маской ввода отключаем поддержку автозаполнения - */ - applyAutocomplete: function () { - var editMask = this.model.getEditMask(); - if (editMask) { - this.$el.attr('autocomplete', 'off'); - } - }, - - onInvalidHandler: function (model, error) { - this.$el.toggleClass(this.classNameError, true); - }, - - onFocusinHandler: function (/* event */) { - this.model.setEditMode(); - setTimeout(this.setCaretPosition.bind(this, 0), 4); - }, - - onFocusoutHandler: function (/* event */) { - this.model.setDisplayMode(); - }, - - onChangeModeHandler: function (model, mode) { - this.checkCurrentPosition(); - }, - - onChangeTextHandler: function (model, text) { - var $input = this.$el; - var position = this.getCaretPosition(); - - $input.toggleClass(this.classNameError, false); - - if($input.val() !== text) { - $input.val(text); - } - - var editMask = this.model.getEditMask(); - - if (editMask) { - if ($input.is(':focus')) { - this.checkCurrentPosition(position); - } - } - - } - -}); -//####app/controls/_base/textEditor/_mode/textEditorModelBaseModeStrategy.js -/** - * - * @constructor - */ -function TextEditorModelBaseModeStrategy() { -} - -/** - * Отображает текстовое представление значения элемента - * @abstract - * @param {TextEditorModel} model - */ -TextEditorModelBaseModeStrategy.prototype.updateText = function (model) { - -}; - - -/** - * Устанавливает значение поля оторажения/ввода значения - * @param {TextEditorModel} model - * @param {string} text - * @param {boolean} ui Признак исзменения со стороны UI - */ -TextEditorModelBaseModeStrategy.prototype.setText = function (model, text, ui) { - -}; - - -/** - * @param model - * @param value - */ -TextEditorModelBaseModeStrategy.prototype.onChangeTextHandler = function (model, value, options) { - -}; - - -//####app/controls/_base/textEditor/_mode/textEditorModelDisplayModeStrategy.js -/** - * @augments TextEditorModelBaseModeStrategy - * @constructor - */ -function TextEditorModelDisplayModeStrategy() { - TextEditorModelBaseModeStrategy.call(this); -} - -TextEditorModelDisplayModeStrategy.prototype = Object.create(TextEditorModelBaseModeStrategy.prototype); -TextEditorModelDisplayModeStrategy.prototype.constructor = TextEditorModelDisplayModeStrategy; - -TextEditorModelDisplayModeStrategy.prototype.updateText = function (model) { - var displayFormat = model.getDisplayFormat(); - var value = model.get('value'); - - var text; - - if (_.isFunction(displayFormat)) { - text = displayFormat.call(null, null, {value: value}); - } else { - text = value; - } - - model.set('text', text); -}; - -TextEditorModelDisplayModeStrategy.prototype.setText = function (model, text, ui) { - if (ui) { - //Изменение значения в поле ввода для режима просмотра - результат срабатывания автозаполнения браузера - model.set('text', text, {ui: ui}); - } -}; - -TextEditorModelDisplayModeStrategy.prototype.onChangeTextHandler = function (model, text, options) { - if (options.ui) { - var value = model.convertValue(text); - model.set('value', value, {ui: options.ui}); - } - model.applyChanges(); -}; -//####app/controls/_base/textEditor/_mode/textEditorModelEditModeStrategy.js -/** - * @augments TextEditorModelBaseModeStrategy - * @constructor - */ -function TextEditorModelEditModeStrategy() { - TextEditorModelBaseModeStrategy.call(this); -} - -TextEditorModelEditModeStrategy.prototype = Object.create(TextEditorModelBaseModeStrategy.prototype); -TextEditorModelEditModeStrategy.prototype.constructor = TextEditorModelBaseModeStrategy; - -TextEditorModelEditModeStrategy.prototype.updateText = function (model) { - var editMask = model.getEditMask(); - var value = model.get('value'); - var text; - - if (!editMask) { - text = value; - } else { - editMask.reset(value); - text = editMask.getText(); - } - - if (typeof text === 'undefined' || text === null) { - model.set('text', ''); - } else { - model.set('text', text.toString()); - } - -}; - -TextEditorModelEditModeStrategy.prototype.setText = function (model, text, ui) { - model.set('text', text, {ui: ui}); -}; - -TextEditorModelEditModeStrategy.prototype.onChangeTextHandler = function (model, newValue, options) { - var editMask = model.getEditMask(); - var value = editMask ? editMask.getData() : newValue; - model.set('value', model.convertValue(value), {silent: !!editMask, ui: options.ui}); -}; - - -//####app/controls/textBox/textBoxControl.js -/** - * - * @param parent - * @constructor - * @augments TextEditorBaseControl - */ -function TextBoxControl(parent) { - _.superClass(TextBoxControl, this, parent); -} - -_.inherit(TextBoxControl, TextEditorBaseControl); - -_.extend(TextBoxControl.prototype, { - - createControlModel: function () { - return new TextBoxModel(); - }, - - createControlView: function (model) { - return new TextBoxView({model: model}); - } -}); - - -//####app/controls/textBox/textBoxModel.js -/** - * @class - * @augments TextEditorBaseModel - */ -var TextBoxModel = TextEditorBaseModel.extend(/** @lends TextBoxModel.prototype */{ - defaults: _.extend( - {}, - TextEditorBaseModel.prototype.defaults, - { - multiline: false, - inputType: 'text' - } - ), - - initialize: function () { - TextEditorBaseModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - } - -}); -//####app/controls/textBox/textBoxView.js -/** - * @class - * @augments TextEditorBaseView - */ -var TextBoxView = TextEditorBaseView.extend(/** @lends TextBoxView.prototype */{ - - template: { - oneline: InfinniUI.Template["controls/textBox/template/oneline.tpl.html"], - multiline: InfinniUI.Template["controls/textBox/template/multiline.tpl.html"] - }, - - className: 'pl-textbox form-group', - - UI: _.extend({}, TextEditorBaseView.prototype.UI), - - events: _.extend({}, TextEditorBaseView.prototype.events, { - - }), - - initHandlersForProperties: function(){ - TextEditorBaseView.prototype.initHandlersForProperties.call(this); - - this.listenTo(this.model, 'change:multiline', this.updateMultiline); - this.listenTo(this.model, 'change:lineCount', this.updateLineCount); - }, - - updateProperties: function(){ - TextEditorBaseView.prototype.updateProperties.call(this); - - this.updateLineCount(); - }, - - updateMultiline: function(){ - this.rerender(); - }, - - updateLineCount: function(){ - var lineCount = this.model.get('lineCount'); - this.ui.editor.attr('rows', lineCount); - }, - - render: function () { - this.prerenderingActions(); - - var model = this.model; - var template = model.get('multiline') ? this.template.multiline : this.template.oneline; - - this.renderTemplate(template); - this.renderTextBoxEditor(); - - this.updateProperties(); - - this.trigger('render'); - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, - - getData: function () { - var data = TextEditorBaseView.prototype.getData.call(this); - var model = this.model; - return _.extend( - data, - { - multiline: model.get('multiline'), - lineCount: model.get('lineCount') - } - ); - }, - - renderTextBoxEditor: function () { - this.renderControlEditor(); - } - -}); - -//####app/controls/dateTimePicker/_modes/dateTimePickerMode.date.js -var dateTimePickerModeDate = { - getTemplate: function () { - return InfinniUI.Template["controls/dateTimePicker/template/date.tpl.html"]; - }, - - onClickDropdownHandler: function (event) { - var model = this.model; - var calendar = new SelectDate({ - model: model - }); - calendar.render(); - $('body').append(calendar.$el); - - calendar.updatePosition(this.el); - - this.listenTo(calendar, 'date', function (date) { - model.set('value', this.convertValue(date)); - }); - }, - - convertValue: function (value) { - return InfinniUI.DateUtils.toISO8601(value, {timezoneOffset: this.model.get('timeZone')}); - } -}; - -//####app/controls/dateTimePicker/_modes/dateTimePickerMode.dateTime.js -var dateTimePickerModeDateTime = { - getTemplate: function () { - return InfinniUI.Template["controls/dateTimePicker/template/dateTime.tpl.html"]; - }, - - onClickDropdownHandler: function (event) { - var model = this.model; - var calendar = new SelectDateTime({ - model: model - }); - calendar.render(); - $('body').append(calendar.$el); - - calendar.updatePosition(this.el); - - this.listenTo(calendar, 'date', function (date) { - model.set('value', this.convertValue(date)); - }); - }, - - convertValue: function (value) { - return InfinniUI.DateUtils.toISO8601(value, {timezoneOffset: this.model.get('timeZone')}); - } -}; - -//####app/controls/dateTimePicker/_modes/dateTimePickerMode.time.js -var dateTimePickerModeTime = { - getTemplate: function () { - return InfinniUI.Template["controls/dateTimePicker/template/time.tpl.html"]; - }, - - onClickDropdownHandler: function (event) { - var model = this.model; - var calendar = new SelectTime({ - model: model - }); - calendar.render(); - $('body').append(calendar.$el); - - calendar.updatePosition(this.el); - - this.listenTo(calendar, 'date', function (date) { - model.set('value', this.convertValue(date)); - }); - }, - - convertValue: function (value) { - return InfinniUI.DateUtils.toISO8601(value, {timezoneOffset: this.model.get('timeZone')}); - } -}; - -//####app/controls/dateTimePicker/components/base/selectComponent.js -var SelectComponent = Backbone.View.extend({ - - modelClass: Backbone.Model, - - initialize: function (options) { - var modelClass = this.modelClass; - - this.model = new modelClass({ - today: options.today || new Date(), - value: options.value, - date: options.value || options.today, - max: options.max, - min: options.min - }); - this.render(); - return this; - }, - - show: function () { - this.$el.css('display', 'block'); - }, - - hide: function () { - this.$el.css('display', 'none'); - }, - - /** - * @description Установка текущего положения списка выбора значений - * Если устанавливается недействительная дата - используется текущая - * @param date - */ - setDate: function (date) { - this.model.setDate(date); - } - -}); - - -_.extend(SelectComponent.prototype, bindUIElementsMixin); -//####app/controls/dateTimePicker/components/base/selectComponentModel.js -var SelectComponentModel = Backbone.Model.extend({ - - defaults: function () { - var today = new Date(); - - return { - today: today, - todayMonth: today.getMonth(), - todayDay: today.getDate(), - todayYear: today.getFullYear(), - hour: today.getHours(), - minute: today.getMinutes(), - second: today.getSeconds(), - millisecond: today.getMilliseconds() - } - }, - - initialize: function () { - this.updateDateParts(); - this.on('change:date', this.onChangeDateHandler, this); - }, - - updateDateParts: function () { - var date = this.get('date'); - - if (date instanceof Date) { - this.set({ - year: date.getFullYear(), - month: date.getMonth(), - day: date.getDate(), - hour: date.getHours(), - minute: date.getMinutes(), - second: date.getSeconds(), - millisecond: date.getMilliseconds() - }); - } else { - this.set({ - year: null, - month: null, - day: null, - hour: null, - minute: null, - second: null, - millisecond: null - }); - } - - }, - - onChangeDateHandler: function (model, value) { - if (typeof value !== 'undefined' && value !== null) { - model.set({ - year: moment(value).year(), - month: moment(value).month(), - day: moment(value).date(), - hour: moment(value).hour(), - minute: moment(value).minute(), - second: moment(value).second(), - millisecond: moment(value).millisecond() - }) - } else { - model.set({ - year: null, - month: null, - day: null, - hour: null, - minute: null, - second: null, - millisecond: null - }); - } - }, - - updateDatePart: function (datePart, model, value) { - var - d = this.get('date'), - date = InfinniUI.DateUtils.createDate(d) || this.get('today'), - data = this.toJSON(); - - - switch (datePart) { - case 'hour': - case 'minute': - case 'second': - date.setHours(data.hour, data.minute, data.second); - break; - case 'year': - case 'month': - case 'day': - date.setFullYear(data.year, data.month, data.day); - break; - } - - this.set('date', date); - }, - - checkRange: function (date, precision) { - var min = this.get('min'), - max = this.get('max'); - - return InfinniUI.DateUtils.checkRangeDate(date, min, max, precision); - }, - - keepDateInRange: function () { - if (this.isValid()) { - return; - } - var date = InfinniUI.DateUtils.getNearestDate(this.get('date'), this.get('min'), this.get('max')); - this.set('date', date); - }, - - /** - * @description Установка текущего положения списка выбора значений - * Если устанавливается недействительная дата - используется текущая - * @param date - */ - setDate: function (date) { - if (typeof date === 'undefined' || date === null){ - var value = this.get('value'), - today = this.get('date'); - - date = value || today; - } - - if (date instanceof Date) { - date = new Date(date.getTime()); - } - this.set('date', date); - } - - -}); - - -//####app/controls/dateTimePicker/components/selectDays.js -var SelectDaysModel = SelectComponentModel.extend({ - - initialize: function () { - SelectComponentModel.prototype.initialize.call(this); - this.on('change:year', this.updateDatePart.bind(this, 'year')); - this.on('change:month', this.updateDatePart.bind(this, 'month')); - this.on('change:day', this.updateDatePart.bind(this, 'day')); - }, - - today: function () { - this.set({ - year: this.get('todayYear'), - month: this.get('todayMonth') - }); - }, - - nextMonth: function () { - var - month = this.get('month'), - year = this.get('year'); - - this.set({ - month: month === 11 ? 0 : month + 1, - year: month === 11 ? year + 1 : year - }); - - this.keepDateInRange(); - }, - - prevMonth: function () { - var - month = this.get('month'), - year = this.get('year'); - - this.set({ - month: month === 0 ? 11 : month - 1, - year: month === 0 ? year - 1 : year - }); - - this.keepDateInRange(); - } - -}); - -var SelectDays = SelectComponent.extend({ - - modelClass: SelectDaysModel, - - template: InfinniUI.Template["controls/dateTimePicker/template/date/days.tpl.html"], - - UI: { - headerDays: '.weekdays-head .day', - calendarDays: '.day-calendar', - year: '.years-year', - month: '.years-month' - }, - - events: { - 'click .years': 'onYearsClickHandler', - 'click .btn-month-prev': 'prevMonth', - 'click .btn-month-next': 'nextMonth', - 'click .today-date': 'showToday', - 'click .day-calendar:not(".day-unavailable")': 'useDay', - 'click .time': 'showTime' - }, - - render: function () { - var template = this.template(); - this.$el.html(template); - this.bindUIElements(); - this.fillLegend(); - this.fillCalendar(); - this.renderMonth(); - this.renderYear(); - this.initOnChangeHandlers(); - }, - - initOnChangeHandlers: function () { - this.listenTo(this.model, 'change:month', this.onChangeMonthHandler); - this.listenTo(this.model, 'change:year', this.onChangeYearHandler); - this.listenTo(this.model, 'change:day', this.onChangeDayHandler); - }, - - renderMonth: function () { - var month = this.model.get('month'); - var dateTimeFormatInfo = localized.dateTimeFormatInfo; - this.ui.month.text(dateTimeFormatInfo.monthNames[month]); - }, - - renderYear: function () { - var year = this.model.get('year'); - this.ui.year.text(year); - }, - - onChangeMonthHandler: function (model, value) { - this.renderMonth(); - this.fillCalendar(); - }, - - onChangeYearHandler: function (model, value) { - this.renderYear(); - this.fillCalendar(); - }, - - fillLegend: function () { - var dateTimeFormatInfo = localized.dateTimeFormatInfo; - var firstDayOfWeek = dateTimeFormatInfo.firstDayOfWeek; - var days = dateTimeFormatInfo.abbreviatedDayNames.map(function (day, i) { - return i; - }); - - if (firstDayOfWeek > 0) { - days = days.splice(firstDayOfWeek).concat(days); - } - - this.ui.headerDays.each(function (i, el) { - var $el = $(el); - var index = days[i]; - $el.text(dateTimeFormatInfo.abbreviatedDayNames[index]); - markWeekend($el, index); - }); - - this.ui.calendarDays.each(function (i, el) { - var $el = $(el); - var index = days[i % 7]; - markWeekend($el, index); - }); - - function markWeekend($el, weekday) { - $el.toggleClass('day-weekend', weekday === 0 || weekday === 6); - } - }, - - fillCalendar: function () { - var model = this.model; - var valueDate = model.get('value'); - var month = model.get('month'); - var year = model.get('year'); - var day = model.get('day'); - var min = model.get('min'); - var max = model.get('max'); - var firstDayOfMonth = new Date(year, month); - var weekday = firstDayOfMonth.getDay(); - var dateTimeFormatInfo = localized.dateTimeFormatInfo; - var firstDayOfWeek = dateTimeFormatInfo.firstDayOfWeek; - - var weekdays = [0,1,2,3,4,5,6]; - Array.prototype.push.apply(weekdays, weekdays.splice(0, firstDayOfWeek)); - var start = new Date(year, month, 1 - weekdays.indexOf(weekday)); - - var startYear = start.getFullYear(), - startMonth = start.getMonth(), - startDate = start.getDate(); - - this.ui.calendarDays.each(function (i, el) { - var $el = $(el); - var d = new Date(startYear, startMonth, startDate + i); - $el.text(d.getDate()); - $el.attr('data-date', d); - markActiveMonth($el, d.getMonth() === month); - markToday($el, d); - markSelected($el, d); - markAvailable($el, d); - }); - - function markActiveMonth($el, active) { - $el.toggleClass('day-inactive', !active); - } - - function markToday($el, date) { - var today = date.getMonth() === model.get('todayMonth') - && date.getFullYear() === model.get('todayYear') - && date.getDate() === model.get('todayDay'); - - $el.toggleClass('day-today', today); - } - - function markSelected($el, value) { - var selected = false; - - if (valueDate) { - selected = moment(valueDate).isSame(value, 'day'); - } - - $el.toggleClass('day-selected', selected); - } - - function markAvailable($el, value) { - $el.toggleClass('day-unavailable', !model.checkRange(value, 'day')); - } - - }, - - onYearsClickHandler: function (event) { - var date = this.model.get('date'); - - this.trigger('year', date); - }, - - prevMonth: function () { - this.model.prevMonth(); - }, - - nextMonth: function () { - this.model.nextMonth(); - }, - - showToday: function () { - this.today(); - }, - - today: function () { - this.model.today(); - }, - - showTime: function () { - this.trigger('time', this.model.get('date')); - }, - - useDay: function (event) { - var $el = $(event.target), - date = new Date($el.attr('data-date')); - - this.model.set({ - year: date.getFullYear(), - month: date.getMonth(), - day: date.getDate() - }); - - this.trigger('date', this.model.get('date')); - } - -}); - -//####app/controls/dateTimePicker/components/selectHours.js -var SelectHoursModel = SelectComponentModel.extend({ - - initialize: function () { - SelectComponentModel.prototype.initialize.call(this); - this.on('change:hour', this.updateDatePart.bind(this, 'hour')); - } - -}); - -var SelectHours = SelectComponent.extend({ - - modelClass: SelectHoursModel, - - template: InfinniUI.Template["controls/dateTimePicker/template/time/hours.tpl.html"], - - events: { - "click .hour:not('.hour-unavailable')": "useHour" - }, - - UI: { - hour: '.hour' - }, - - render: function () { - var template = this.template(); - this.$el.html(template); - this.bindUIElements(); - this.fillHoursTable(); - this.initOnChangeHandlers(); - }, - - fillHoursTable: function () { - //@TODO Заполнять в зависимости от формата 12/24 - var - model = this.model; - var date = model.get('date') || model.get('today'); - var now = new Date(); - - this.ui.hour.each(function (i, el) { - var $el = $(el); - var hour = stringUtils.padLeft(i, 2, '0'); - - $el.attr('data-hour', i); - $el.text(hour); - markNow($el, i); - markSelected($el, i); - markAvailable($el, i); - }); - - function markSelected($el, value) { - $el.toggleClass('hour-selected', date.getHours() === value); - } - - function markNow($el, value) { - var selected = moment(now).isSame(value, 'hour'); - $el.toggleClass('hour-today', selected); - } - - function markAvailable($el, value) { - var date = moment(model.get('date')).hour(value); - $el.toggleClass('hour-unavailable', !model.checkRange(date, 'hour')); - } - }, - - initOnChangeHandlers: function () { - this.listenTo(this.model, 'change:date', this.fillHoursTable); - }, - - useHour: function (event) { - var - $el = $(event.target), - model = this.model, - date = model.get('date'), - hour = parseInt($el.attr('data-hour'), 10); - - var newDate = InfinniUI.DateUtils.cloneDate(date); - newDate.setHours(hour); - model.set('date', newDate); - - this.trigger('hour', newDate); - } - -}); - -//####app/controls/dateTimePicker/components/selectMinutes.js -var SelectMinutesModel = SelectComponentModel.extend({ - - initialize: function () { - SelectComponentModel.prototype.initialize.call(this); - this.on('change:minute', this.updateDatePart.bind(this, 'minute')); - } - -}); - -var SelectMinutes = SelectComponent.extend({ - - modelClass: SelectMinutesModel, - - template: InfinniUI.Template["controls/dateTimePicker/template/time/minutes.tpl.html"], - - events: { - "click .minute:not('.minute-unavailable')": "useMinute" - }, - - UI: { - minute: '.minute' - }, - - render: function () { - var template = this.template(); - this.$el.html(template); - this.bindUIElements(); - this.fillMinutesTable(); - this.initOnChangeHandlers(); - }, - - fillMinutesTable: function () { - var - model = this.model, - minute = model.get('minute'); - - this.ui.minute.each(function (i, el) { - var $el = $(el); - var minute = $el.attr('data-minute'); - markSelected($el, parseInt(minute, 10)); - markAvailable($el, parseInt(minute, 10)) - }); - - function markSelected($el, value) { - $el.toggleClass('minute-selected', value === minute); - } - - function markAvailable($el, value) { - var date = moment(model.get('date')).minute(value); - $el.toggleClass('minute-unavailable', !model.checkRange(date, 'minute')); - } - }, - - initOnChangeHandlers: function () { - this.listenTo(this.model, 'change:date', this.fillMinutesTable); - }, - - useMinute: function (event) { - var - $el = $(event.target), - model = this.model, - date = model.get('date'), - minute = parseInt($el.attr('data-minute'), 10); - - var newDate = InfinniUI.DateUtils.cloneDate(date); - newDate.setMinutes(minute); - this.trigger('minute', newDate); - } - -}); - -//####app/controls/dateTimePicker/components/selectMonths.js -var SelectMonthsModel = SelectComponentModel.extend({ - - initialize: function () { - SelectComponentModel.prototype.initialize.call(this); - this.on('change:month', this.updateDatePart.bind(this, 'month')); - this.on('change:year', this.updateDatePart.bind(this, 'year')); - }, - - - - nextYear: function () { - var year = this.get('year'); - this.set('year', year + 1); - this.keepDateInRange(); - }, - - prevYear: function () { - var year = this.get('year'); - this.set('year', year - 1); - this.keepDateInRange(); - }, - - today: function () { - this.set({ - month: this.get('todayMonth'), - year: this.get('todayYear') - }); - } -}); - -var SelectMonths = SelectComponent.extend({ - - modelClass: SelectMonthsModel, - - template: InfinniUI.Template["controls/dateTimePicker/template/date/months.tpl.html"], - - events: { - "click .btn-year-prev": "prevYear", - "click .btn-year-next": "nextYear", - "click .month:not('.month-unavailable')": "useMonth", - "click .year": "selectYear", - "click .today-month": "showToday" - }, - - UI: { - month: '.month', - year: '.year' - }, - - render: function () { - var template = this.template(); - this.$el.html(template); - this.bindUIElements(); - this.fillMonthsTable(); - this.initOnChangeHandlers(); - }, - - fillMonthsTable: function () { - this.ui.year.text(this.model.get('year')); - - var - model = this.model, - dateTimeFormatInfo = localized.dateTimeFormatInfo, - todayMonth = model.get('todayMonth'), - month = model.get('month'); - - this.ui.month.each(function (i, el) { - var $el = $(el); - $el.text(dateTimeFormatInfo.abbreviatedMonthNames[i]); - $el.attr('data-month', i); - markTodayMonth($el, i); - markSelected($el, i); - markAvailable($el, i); - }); - - function markTodayMonth($el, value) { - var date = moment([model.get('year'), value]); - var today = model.get('today'); - - $el.toggleClass('month-today', moment(date).isSame(today, 'month')); - } - - function markSelected($el, value) { - var date = moment([model.get('year'), value]); - var selected = model.get('value'); - - $el.toggleClass('month-selected', moment(date).isSame(selected, 'month')); - } - - function markAvailable($el, value) { - var date = moment([model.get('year'), value]); - $el.toggleClass('month-unavailable', !model.checkRange(date, 'month')); - } - }, - - initOnChangeHandlers: function () { - this.listenTo(this.model, 'change:year', this.fillMonthsTable); - }, - - prevYear: function () { - this.model.prevYear(); - }, - - nextYear: function () { - this.model.nextYear(); - }, - - useMonth: function (event) { - var - $el = $(event.target), - model = this.model; - - model.set({ - year: parseInt(model.get('year'), 10), - month: parseInt($el.attr('data-month'), 10) - }); - this.trigger('month', model.get('date')); - }, - - selectYear: function () { - var - model = this.model; - - this.trigger('year', model.get('data')); - }, - - showToday: function () { - this.today(); - }, - - today: function () { - this.model.today(); - } - - - -}); - -//####app/controls/dateTimePicker/components/selectSeconds.js -var SelectSecondsModel = SelectComponentModel.extend({ - - initialize: function () { - SelectComponentModel.prototype.initialize.call(this); - this.on('change:second', this.updateDatePart.bind(this, 'second')); - } - -}); - -var SelectSeconds = SelectComponent.extend({ - - modelClass: SelectSecondsModel, - - template: InfinniUI.Template["controls/dateTimePicker/template/time/seconds.tpl.html"], - - events: { - "click .second:not('.second-unavailable')": "useSecond" - }, - - UI: { - second: '.second' - }, - - render: function () { - var template = this.template(); - this.$el.html(template); - this.bindUIElements(); - this.fillSecondsTable(); - this.initOnChangeHandlers(); - }, - - fillSecondsTable: function () { - var - model = this.model, - second = model.get('second'); - - this.ui.second.each(function (i, el) { - var $el = $(el); - var second = $el.attr('data-second'); - markSelected($el, parseInt(second, 10)); - markAvailable($el, parseInt(second, 10)) - }); - - function markSelected($el, value) { - $el.toggleClass('second-selected', value === second); - } - - function markAvailable($el, value) { - var date = moment(model.get('date')).seconds(value); - $el.toggleClass('second-unavailable', !model.checkRange(date)); - } - }, - - initOnChangeHandlers: function () { - this.listenTo(this.model, 'change:date', this.fillSecondsTable); - }, - - useSecond: function (event) { - var - $el = $(event.target), - model = this.model, - date = model.get('date'), - second = parseInt($el.attr('data-second'), 10); - - var newDate = InfinniUI.DateUtils.cloneDate(date); - - newDate.setSeconds(second); - this.trigger('second', newDate); - } - -}); - -//####app/controls/dateTimePicker/components/selectTimes.js -var SelectTimesModel = SelectComponentModel.extend({ - - initialize: function () { - SelectComponentModel.prototype.initialize.call(this); - this.on('change:hour', this.updateDatePart.bind(this, 'hour')); - this.on('change:minute', this.updateDatePart.bind(this, 'minute')); - this.on('change:second', this.updateDatePart.bind(this, 'second')); - this.on('change:millisecond', this.updateDatePart.bind(this, 'millisecond')); - }, - - nextHour: function () { - var hour = this.get('hour'); - hour += 1; - - //@TODO Границу использовать в зависимости от 12/24 формата записи даты из настроек локализации - if (hour > 23) { - return; - } - - this.set('hour', hour); - this.keepDateInRange(); - }, - - prevHour: function () { - var hour = this.get('hour'); - hour -= 1; - - if (hour < 0) { - return; - } - - this.set('hour', hour); - this.keepDateInRange(); - }, - - nextMinute: function () { - var minute = this.get('minute'); - minute += 1; - - if (minute >= 60) { - return; - } - - this.set('minute', minute); - this.keepDateInRange(); - }, - - prevMinute: function () { - var minute = this.get('minute'); - minute -= 1; - - if (minute < 0) { - return; - } - - this.set('minute', minute); - this.keepDateInRange(); - }, - - nextSecond: function () { - var second = this.get('second'); - second += 1; - - if (second >= 60) { - return; - } - - this.set('second', second); - this.keepDateInRange(); - }, - - prevSecond: function () { - var second = this.get('second'); - second -= 1; - - if (second < 0) { - return; - } - - this.set('second', second); - this.keepDateInRange(); - }, - - validate: function (attr, options) { - var value = InfinniUI.DateUtils.cloneDate(attr.date); - value.setHours(attr.hour, attr.minute, attr.second, attr.millisecond); - - if (!this.checkRange(value)) { - return 'Out of range'; - } - } - -}); - -var SelectTimes = SelectComponent.extend({ - - modelClass: SelectTimesModel, - - template: InfinniUI.Template["controls/dateTimePicker/template/time/time.tpl.html"], - - events: { - "click .time-spin-down.time-spin-hour": "prevHour", - "click .time-spin-up.time-spin-hour": "nextHour", - - "click .time-spin-down.time-spin-minute": "prevMinute", - "click .time-spin-up.time-spin-minute": "nextMinute", - - "click .time-spin-down.time-spin-second": "prevSecond", - "click .time-spin-up.time-spin-second": "nextSecond", - - "click .time-segment-hour": "selectHour", - "click .time-segment-minute": "selectMinute", - "click .time-segment-second": "selectSecond", - "click .days": "selectDay" - }, - - UI: { - month: '.month', - year: '.year', - hour: '.time-segment-hour', - minute: '.time-segment-minute', - second: '.time-segment-second' - }, - - render: function () { - var template = this.template(); - this.$el.html(template); - this.bindUIElements(); - this.updateHour(); - this.updateMinute(); - this.updateSecond(); - this.initOnChangeHandlers(); - }, - - selectHour: function () { - var - model = this.model, - date = model.get('date'), - hour = model.get('hour'), - minute = model.get('minute'), - second = model.get('second'); - - date.setHours(hour, minute, second); - this.trigger('hour', date); - }, - - selectMinute: function () { - var - model = this.model, - date = model.get('date'), - hour = model.get('hour'), - minute = model.get('minute'), - second = model.get('second'); - - date.setHours(hour, minute, second); - this.trigger('minute', date); - }, - - selectSecond: function () { - var - model = this.model, - date = model.get('date'), - hour = model.get('hour'), - minute = model.get('minute'), - second = model.get('second'); - - date.setHours(hour, minute, second); - this.trigger('second', date); - }, - - initOnChangeHandlers: function () { - this.listenTo(this.model, 'change:hour', this.updateHour); - this.listenTo(this.model, 'change:minute', this.updateMinute); - this.listenTo(this.model, 'change:second', this.updateSecond); - this.listenTo(this.model, 'change:date', this.useTime); - }, - - updateHour: function () { - var hour = this.model.get('hour'); - this.ui.hour.text(stringUtils.padLeft(hour, 2, '0')); - }, - - updateMinute: function () { - var minute = this.model.get('minute'); - this.ui.minute.text(stringUtils.padLeft(minute, 2, '0')); - }, - - updateSecond: function () { - var second = this.model.get('second'); - this.ui.second.text(stringUtils.padLeft(second, 2, '0')); - }, - - prevHour: function () { - this.model.prevHour(); - }, - - nextHour: function () { - this.model.nextHour(); - }, - - prevMinute: function () { - this.model.prevMinute(); - }, - - nextMinute: function () { - this.model.nextMinute(); - }, - - prevSecond: function () { - this.model.prevSecond(); - }, - - nextSecond: function () { - this.model.nextSecond(); - }, - - useTime: function () { - var - date = this.model.get('date'); - - this.trigger('date', date); - }, - - selectDay: function () { - var - date = this.model.get('date'); - - this.trigger('day', date); - - } - -}); - -//####app/controls/dateTimePicker/components/selectYears.js -var SelectYearsModel = SelectComponentModel.extend({ - - defaults: function () { - var defaults = SelectComponentModel.prototype.defaults.call(this); - - return _.defaults({ - pageSize: 20, - page: 0 - }, defaults); - }, - - initialize: function () { - SelectComponentModel.prototype.initialize.call(this); - this.on('change:year', this.updateDatePart.bind(this, 'year')); - this.on('change:year', this.onChangeYearHandler); - }, - - prevPage: function () { - var page = this.get('page'); - this.set('page', page - 1); - }, - - nextPage: function () { - var page = this.get('page'); - this.set('page', page + 1); - }, - - resetPage: function () { - this.set('page', 0); - }, - - onChangeYearHandler: function (model, value) { - this.keepDateInRange(); - model.set('page', 0); - } - -}); - -var SelectYears = SelectComponent.extend({ - - modelClass: SelectYearsModel, - - template: InfinniUI.Template["controls/dateTimePicker/template/date/years.tpl.html"], - - events: { - 'click .btn-year-prev': "prevPage", - 'click .btn-year-next': "nextPage", - 'click .today-year': "showTodayYear", - 'click .year:not(".year-unavailable")': "useYear" - }, - - UI: { - years: '.year', - yearBegin: '.year-begin', - yearEnd: '.year-end' - }, - - initOnChangeHandlers: function () { - this.listenTo(this.model, 'change:page', this.fillYearsTable); - this.listenTo(this.model, 'change:year', this.fillYearsTable); - }, - - render: function () { - var template = this.template(); - this.$el.html(template); - this.bindUIElements(); - //this.fillCalendar(); - this.fillYearsTable(); - this.initOnChangeHandlers(); - }, - - fillYearsTable: function () { - var - model = this.model, - page = model.get('page'), - pageSize = model.get('pageSize'), - year = model.get('year'), - todayYear = model.get('todayYear'), - //startYear = Math.ceil((year || todayYear) - pageSize / 2) + page * pageSize; - startYear = Math.ceil(year - pageSize / 2) + page * pageSize; - - this.ui.years.each(function (i, el) { - var $el = $(el); - var year = startYear + i; - $el.text(year); - $el.attr('data-year', year); - markTodayYear($el, year); - markSelected($el, year); - markAvailable($el, year); - }); - - this.ui.yearBegin.text(startYear); - this.ui.yearEnd.text(startYear + pageSize - 1); - - function markTodayYear($el, value) { - $el.toggleClass('year-today', value === todayYear); - } - - function markSelected($el, value) { - $el.toggleClass('year-selected', value === year); - } - function markAvailable($el, value) { - var date = moment([value]); - $el.toggleClass('year-unavailable', !model.checkRange(date, 'year')); - } - - }, - - prevPage: function () { - this.model.prevPage(); - }, - - nextPage: function () { - this.model.nextPage(); - }, - - showTodayYear: function () { - this.today(); - }, - - today: function () { - this.model.resetPage(); - }, - - useYear: function (event) { - var $el = $(event.target), - model = this.model; - - model.set({ - year: parseInt($el.attr('data-year'), 10) - }); - - this.trigger('year', model.get('date')); - } - -}); - -//####app/controls/dateTimePicker/dateTimePickerControl.js -/** - * - * @param parent - * @constructor - * @augments TextEditorBaseControl - */ -function DateTimePickerControl(parent) { - _.superClass(DateTimePickerControl, this, parent); -} - -window.InfinniUI.DateTimePickerControl = DateTimePickerControl; - -_.inherit(DateTimePickerControl, TextEditorBaseControl); - -_.extend(DateTimePickerControl.prototype, { - - createControlModel: function () { - return new DateTimePickerModel(); - }, - - createControlView: function (model) { - return new DateTimePickerView({model: model}); - } -}); - - -//####app/controls/dateTimePicker/dateTimePickerModel.js -/** - * @class - * @augments TextEditorBaseModel - */ -var DateTimePickerModel = TextEditorBaseModel.extend(/** @lends DateTimePickerModel.prototype */{ - defaults: _.extend( - {}, - TextEditorBaseModel.prototype.defaults, - { - mode: "Date" - //today: new Date() - } - ), - - initialize: function () { - TextEditorBaseModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - this.set('today', new Date()); - this.set('timeZone', InfinniUI.DateUtils.getDefaultTimeZone()); - }, - - validate: function (attributes, options) { - var - min = attributes.minValue, - max = attributes.maxValue; - - return InfinniUI.DateUtils.checkRangeDate(attributes.value, attributes.minValue, attributes.maxValue); - } - - -}); -//####app/controls/dateTimePicker/dateTimePickerStrategy.js -var dateTimePickerStrategy = (function () { - - return { - Date: dateTimePickerModeDate, - DateTime: dateTimePickerModeDateTime, - Time: dateTimePickerModeTime - }; - -})(); - - -//####app/controls/dateTimePicker/dateTimePickerView.js -/** - * @class - * @augments TextEditorBaseView - */ -var DateTimePickerView = TextEditorBaseView.extend(/** @lends DateTimePickerView.prototype */{ - - className: "pl-datepicker form-group", - - template: InfinniUI.Template["controls/dateTimePicker/template/date.tpl.html"], - - UI: _.extend({}, TextEditorBaseView.prototype.UI, { - dropdownButton: '.pl-datepicker-calendar', - controlWrap: '.control-wrap', - editorWrap: '.editor-wrap' - }), - - events: _.extend({}, TextEditorBaseView.prototype.events, { - 'click .pl-datepicker-calendar': 'onClickDropdownHandler' - }), - - initialize: function () { - TextEditorBaseView.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - this.updateMode(); - this.listenTo(this.model, 'change:mode', this.updateMode); - }, - - initHandlersForProperties: function(){ - TextEditorBaseView.prototype.initHandlersForProperties.call(this); - - this.listenTo(this.model, 'change:minValue', this.updateMinValue); - this.listenTo(this.model, 'change:maxValue', this.updateMaxValue); - }, - - updateProperties: function(){ - TextEditorBaseView.prototype.updateProperties.call(this); - }, - - updateMode: function(){ - var mode = this.model.get('mode'); - _.extend(this, dateTimePickerStrategy[mode]); - - this.rerender(); - }, - - updateMinValue: function(){ - var mode = this.model.get('mode'); - _.extend(this, dateTimePickerStrategy[mode]); - - this.rerender(); - }, - - updateMaxValue: function(){ - var mode = this.model.get('mode'); - _.extend(this, dateTimePickerStrategy[mode]); - - this.rerender(); - }, - - updateEnabled: function(){ - TextEditorBaseView.prototype.updateEnabled.call(this); - - var isEnabled = this.model.get('enabled'); - this.ui.dropdownButton.prop('disabled', !isEnabled); - }, - - render: function () { - this.prerenderingActions(); - - this.renderTemplate(this.getTemplate()); - this.updateProperties(); - this.renderDateTimePickerEditor(); - - this.trigger('render'); - - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, - - getData: function () { - var - model = this.model; - - return _.extend({}, - TextEditorBaseView.prototype.getData.call(this), { - minValue: model.get('minValue'), - maxValue: model.get('maxValue'), - mode: model.get('mode') - }); - }, - - renderDateTimePickerEditor: function () { - var model = this.model; - this.renderControlEditor(); - return this; - }, - - getTemplate: function () { - throw new Error('Не перекрыт getTemplate'); - }, - - onClickDropdownHandler: function (event) {} - -}); - -//####app/controls/dateTimePicker/selectDate.js -var SelectDate = Backbone.View.extend({ - - className: 'pl-datepicker-dropdown pl-dropdown-container', - - template: InfinniUI.Template["controls/dateTimePicker/template/select.date.tpl.html"], - - UI: { - days: '.days', - months: '.months', - years: '.years' - }, - - events: { - 'click .backdrop': 'onClickBackdropHandler', - 'click .datepicker-clear': 'onClickClearValueHandler', - 'click .today-date': 'onClickTodayHandler' - }, - - render: function () { - var template = this.template(); - this.$el.html(template); - this.bindUIElements(); - this.renderComponents(); - }, - - renderComponents: function () { - var model = this.model; - var value = InfinniUI.DateUtils.createDate(model.get('value')); - var today = InfinniUI.DateUtils.createDate(model.get('today')); - var timeZone = model.get('timeZone'); - var m = moment(value); - - if (m.isValid()) { - value = m.toDate(); - } else { - value = null; - } - - value = InfinniUI.DateUtils.changeTimezoneOffset(value, timeZone); - - var options = { - value: value, - today: today || new Date(), - //date: value, - max: model.get('maxValue'), - min: model.get('minValue') - }; - - options.el = this.ui.months; - var months = new SelectMonths(options); - - options.el = this.ui.years; - var years = new SelectYears(options); - - options.el = this.ui.days; - var days = new SelectDays(options); - - this.months = months; - this.years = years; - this.days = days; - - this.workflow(days, months, years, value)(value); - }, - - onClickBackdropHandler: function (event) { - this.remove(); - }, - - onClickClearValueHandler: function () { - this.clearValue(); - }, - - clearValue: function () { - this.useValue(null); - }, - - useValue: function (date) { - var model = this.model; - var timeZone = model.get('timeZone'); - - var min = model.get('minValue'), - max = model.get('maxValue'); - - if (!InfinniUI.DateUtils.checkRangeDate(date, min, max)) { - date = InfinniUI.DateUtils.getNearestDate(date, min, max); - } - - this.trigger('date', InfinniUI.DateUtils.restoreTimezoneOffset(date, timeZone)); - this.remove(); - }, - - workflow: function (days, months, years) { - - this - .listenTo(days, 'date', this.useValue) - .listenTo(days, 'year', function (date) { - showYears(date);//Needed select year from list - }) - .listenTo(years, 'year', function (date) { - showMonths(date);//Needed select month for year - }) - .listenTo(months, 'year', function (date) { - showYears(date);//Needed select year from list - }) - .listenTo(months, 'month', function (date) { - showDays(date);//Needed select day from calendar - }); - - return showDays; - - function showDays(date) { - days.setDate(date); - - years.hide(); - months.hide(); - days.show(); - } - - function showMonths(date) { - months.setDate(date); - - days.hide(); - years.hide(); - months.show(); - } - - function showYears(date) { - years.setDate(date); - - days.hide(); - months.hide(); - years.show(); - } - - }, - - onClickTodayHandler: function () { - this.useValue(new Date()); - }, - - updatePosition: function (parentDOMElement) { - var direction = this.getDropdownDirection(parentDOMElement); - this.setPositionFor(parentDOMElement, direction ); - }, - - setPositionFor: function (parentDOMElement, direction) { - clearInterval(this._intervalId); - - this.applyStyle(parentDOMElement, direction); - this._intervalId = setInterval(this.applyStyle.bind(this, parentDOMElement, direction), 100); - }, - - remove: function () { - clearInterval(this._intervalId); - return Backbone.View.prototype.remove.apply(this, arguments); - }, - - getDropdownDirection: function (parentDOMElement) { - - var windowHeight = $(window).height(); - var rect = parentDOMElement.getBoundingClientRect(); - var height = this.$el.height(); - - var direction = 'bottom'; - if (rect.bottom + height + 30 > windowHeight && rect.bottom > windowHeight / 2 && rect.top > height) { - direction = 'top'; - } - - return direction; - }, - - applyStyle: function (parentDOMElement, direction) { - var rect = parentDOMElement.getBoundingClientRect(); - - var rectDropdown = this.el.getBoundingClientRect(); - - //@TODO Вынести общие стили в css - var style = { - position: "absolute", - left: window.pageXOffset + rect.right - Math.round(rectDropdown.width) - }; - - if (direction === 'bottom') { - style.top = window.pageYOffset + rect.bottom; - } else { - style.top = window.pageYOffset + rect.top - this.$el.height(); - } - - this.$el.css(style); - } - - -}); - -_.extend(SelectDate.prototype, bindUIElementsMixin); - -//####app/controls/dateTimePicker/selectDateTime.js -var SelectDateTime = SelectDate.extend({ - - className: 'pl-datepicker-dropdown pl-dropdown-container', - - template: InfinniUI.Template["controls/dateTimePicker/template/select.dateTime.tpl.html"], - - UI: { - days: '.days', - months: '.months', - years: '.years', - times: '.times', - hours: '.hours', - minutes: '.minutes' - }, - - onClickToggleDateHandler: function () { - this.trigger('days'); - }, - - onClickToggleTimeHandler: function () { - this.trigger('time'); - }, - - - renderComponents: function () { - var model = this.model; - var value = InfinniUI.DateUtils.createDate(model.get('value')); - var today = InfinniUI.DateUtils.createDate(model.get('today')); - var timeZone = model.get('timeZone'); - var m = moment(value); - - if (m.isValid()) { - value = m.toDate(); - } else { - value = null; - } - - value = InfinniUI.DateUtils.changeTimezoneOffset(value, timeZone); - - var options = { - value: value, - today: today || new Date(), - //date: value, - max: model.get('maxValue'), - min: model.get('minValue') - }; - - options.el = this.ui.months; - var months = new SelectMonths(options); - - options.el = this.ui.years; - var years = new SelectYears(options); - - options.el = this.ui.days; - var days = new SelectDays(options); - - options.el = this.ui.times; - var time = new SelectTimes(options); - //time.setDate(undefined); - - options.el = this.ui.hours; - var hours = new SelectHours(options); - - options.el = this.ui.minutes; - var minutes = new SelectMinutes(options); - - - this.workflow(days, months, years, time, hours, minutes)(value); - }, - - useTime: function (date) { - var model = this.model; - var timeZone = model.get('timeZone'); - - var min = model.get('minValue'), - max = model.get('maxValue'); - - if (!InfinniUI.DateUtils.checkRangeDate(date, min, max)) { - date = InfinniUI.DateUtils.getNearestDate(date, min, max); - } - - this.trigger('date', InfinniUI.DateUtils.restoreTimezoneOffset(date, timeZone)); - - return date; - }, - - workflow: function (days, months, years, time, hours, minutes) { - var useTime = this.useTime.bind(this); - var components = Array.prototype.slice.call(arguments); - - this - .listenTo(days, 'date', this.useValue) - .listenTo(days, 'year', function (date) { - showYears(date);//Needed select year from list - }) - .listenTo(days, 'time', function (date) { - showTime(date); - }) - .listenTo(years, 'year', function (date) { - showMonths(date);//Needed select month for year - }) - .listenTo(months, 'year', function (date) { - showYears(date);//Needed select year from list - }) - .listenTo(months, 'month', function (date) { - showDays(date);//Needed select day from calendar - }); - - this.listenTo(time, 'hour', function (date) { - showHours(date); - }) - .listenTo(time, 'minute', function (date) { - showMinutes(date); - }) - .listenTo(time, 'day', function (date) { - showDays(date); - }) - .listenTo(time, 'date', function (date) { - useTime(date); - }) - .listenTo(hours, 'hour', function (date) { - var newDate = useTime(date); - showTime(newDate); - }) - .listenTo(minutes, 'minute', function (date) { - var newDate = useTime(date); - showTime(newDate); - }); - - //Переключатель режима Date/Time - this - .on('days', function (date) { - showDays(date); - }) - .on('time', function (date) { - showTime(date); - }); - - return showDays; - - function switchComponent(component) { - components.forEach(function (c) { - if (c !== component) { - c.hide(); - } - }); - component.show(); - } - - function showDays(date) { - days.setDate(date); - switchComponent(days); - } - - function showMonths(date) { - months.setDate(date); - switchComponent(months); - } - - function showYears(date) { - years.setDate(date); - switchComponent(years); - } - - function showHours(date) { - hours.setDate(date); - switchComponent(hours); - } - - function showMinutes(date) { - minutes.setDate(date); - switchComponent(minutes); - } - - function showTime(date) { - time.setDate(date); - switchComponent(time); - } - - } - -}); -//####app/controls/dateTimePicker/selectTime.js -var SelectTime = SelectDate.extend({ - - className: 'pl-timepicker-dropdown pl-dropdown-container', - - template: InfinniUI.Template["controls/dateTimePicker/template/select.time.tpl.html"], - - UI: { - times: '.times', - hours: '.hours', - minutes: '.minutes', - seconds: '.seconds' - }, - - renderComponents: function () { - var model = this.model; - var value = InfinniUI.DateUtils.createDate(model.get('value')); - var today = InfinniUI.DateUtils.createDate(model.get('today')); - var timeZone = model.get('timeZone'); - var m = moment(value); - - if (m.isValid()) { - value = m.toDate(); - } else { - value = null; - } - - value = InfinniUI.DateUtils.changeTimezoneOffset(value, timeZone); - //if (value === null || typeof value === 'undefined') { - // value = today; - //} - - var options = { - value: value, - today: today, - //date: date, - max: model.get('maxValue'), - min: model.get('minValue') - }; - - options.el = this.ui.times; - var time = new SelectTimes(options); - - options.el = this.ui.hours; - var hours = new SelectHours(options); - - options.el = this.ui.minutes; - var minutes = new SelectMinutes(options); - - options.el = this.ui.seconds; - var seconds = new SelectSeconds(options); - - this.workflow(time, hours, minutes, seconds)(value); - }, - - useTime: function (date) { - var model = this.model; - var timeZone = model.get('timeZone'); - - var min = model.get('minValue'), - max = model.get('maxValue'); - - if (!InfinniUI.DateUtils.checkRangeDate(date, min, max)) { - date = InfinniUI.DateUtils.getNearestDate(date, min, max); - } - - this.trigger('date', InfinniUI.DateUtils.restoreTimezoneOffset(date, timeZone)); - return date; - }, - - workflow: function (time, hours, minutes, seconds) { - var useTime = this.useTime.bind(this); - var components = Array.prototype.slice.call(arguments); - - this.listenTo(time, 'hour', function (date) { - showHours(date); - }) - .listenTo(time, 'minute', function (date) { - showMinutes(date); - }) - .listenTo(time, 'second', function (date) { - showSeconds(date); - }) - .listenTo(time, 'date', function (date) { - useTime(date); - }) - .listenTo(hours, 'hour', function (date) { - var value = useTime(date); - showTime(value); - }) - .listenTo(minutes, 'minute', function (date) { - var value = useTime(date); - showTime(value); - }) - .listenTo(seconds, 'second', function (date) { - var value = useTime(date); - showTime(value); - }); - - return showTime; - - function switchComponent(component) { - components.forEach(function (c) { - if (c !== component) { - c.hide(); - } - }); - component.show(); - } - - function showHours(date) { - hours.setDate(date); - switchComponent(hours); - } - - function showMinutes(date) { - minutes.setDate(date); - switchComponent(minutes); - } - - function showSeconds(date) { - seconds.setDate(date); - switchComponent(seconds); - } - - function showTime(date) { - time.setDate(date); - switchComponent(time); - } - - } - -}); -//####app/controls/datePicker/datePickerControl.js -function DatePickerControl(parent) { - _.superClass(DatePickerControl, this, parent); -} - -_.inherit(DatePickerControl, DateTimePickerControl); - -_.extend(DatePickerControl.prototype, { - - createControlModel: function () { - return new DatePickerModel(); - }, - - createControlView: function (model) { - return new DatePickerView({model: model}); - } -}); - - -//####app/controls/datePicker/datePickerModel.js -var DatePickerModel = DateTimePickerModel.extend({ - - initialize: function () { - DateTimePickerModel.prototype.initialize.apply(this, arguments); - - - } - -}); -//####app/controls/datePicker/datePickerView.js -var DatePickerView = DateTimePickerView .extend({ - -}); -//####app/controls/datePicker/dateTimePickerMode.datePicker.js -console.assert(dateTimePickerModeDate, "dateTimePickerModeDate is undefined"); - -var dateTimePickerModeDatePicker = _.extend({}, dateTimePickerModeDate, { - - convertValue: function (value) { - var _value = null; - if (value && value.constructor === Date) { - _value = InfinniUI.DateUtils.dateToTimestamp(value); - } - - return _value; - } -}); - -dateTimePickerStrategy['DatePicker'] = dateTimePickerModeDatePicker; - -//####app/controls/timePicker/dateTimePickerMode.timePicker.js -console.assert(dateTimePickerModeTime, "dateTimePickerModeTime is undefined"); - -var dateTimePickerModeTimePicker = _.extend({}, dateTimePickerModeTime, { - - convertValue: function (value) { - var _value = null; - if (value && value.constructor === Date) { - _value = InfinniUI.DateUtils.dateToTimestampTime(value); - } - - return _value; - } - -}); - -dateTimePickerStrategy['TimePicker'] = dateTimePickerModeTimePicker; -//####app/controls/timePicker/timePickerControl.js -function TimePickerControl(parent) { - _.superClass(TimePickerControl, this, parent); -} - -_.inherit(TimePickerControl, DateTimePickerControl); - -_.extend(TimePickerControl.prototype, { - - createControlModel: function () { - return new TimePickerModel(); - }, - - createControlView: function (model) { - return new TimePickerView({model: model}); - } -}); - - -//####app/controls/timePicker/timePickerModel.js -var TimePickerModel = DateTimePickerModel.extend({ - - initialize: function () { - DateTimePickerModel.prototype.initialize.apply(this, arguments); - var date = new Date(); - date.setFullYear(1970, 0, 1); - this.set('today', date); - } - -}); -//####app/controls/timePicker/timePickerView.js -var TimePickerView = DateTimePickerView .extend({ - - className: "pl-datepicker pl-timepicker form-group" - -}); -//####app/controls/application/statusBar/statusBar.js -var StatusBarControl = function () { - _.superClass(StatusBarControl, this); -}; -_.inherit(StatusBarControl, Control); -_.extend(StatusBarControl.prototype, { - createControlModel: function () { - return new StatusBarModel(); - }, - createControlView: function (model) { - return new StatusBarView({model: model}); - } -}); - -var StatusBarModel = ControlModel.extend({ - defaults: _.defaults({}, ControlModel.prototype.defaults, { - time: '', - date: '', - result: null - }) -}); - -var StatusBarView = ControlView.extend({ - className: 'pl-status-bar', - - events: { - 'click .signIn': 'signInHandler', - 'click .signOut': 'signOutHandler', - 'click .status-bar-menu': 'openMenuHandler' - }, - - template: InfinniUI.Template['controls/application/statusBar/template.tpl.html'], - loginTemplate: InfinniUI.Template['controls/application/statusBar/authentication/loginTemplate.tpl.html'], - - enterTemplate: InfinniUI.Template['controls/application/statusBar/authentication/enterTemplate.tpl.html'], - successTemplate: InfinniUI.Template['controls/application/statusBar/authentication/successTemplate.tpl.html'], - - initialize: function () { - var self = this; - self.model.set('time', moment().format('HH:mm')); - self.model.set('date', moment().format('D MMMM')); - - window.setInterval(function () { - self.model.set('time', moment().format('HH:mm')); - self.model.set('date', moment().format('D MMMM')); - self.dateRender(); - }, 10 * 1000); - - getUserInfo(this); - this.listenTo(this.model, 'change:result', this.render); - }, - - dateRender: function () { - this.$el.find('.time').text(this.model.get('time')); - this.$el.find('.date').text(this.model.get('date')); - }, - - signInHandler: function () { - var self = this; - if (!this.$modal) { - this.$modal = $(this.loginTemplate({})); - this.$modal.appendTo('body'); - } - - this.$modal.modal('show'); - this.$modal.on('hidden.bs.modal', function () { - $(this).find('#password, #userName').val(''); - $(this).find('#remember').attr('checked', false); - }); - this.$modal.find('.post').on('click', function () { - signInInternal(self); - }) - }, - openMenuHandler: function(){ - var menu = $('.app-area').find('.pl-menu'); - var area = menu.closest('.app-area'); - - if(menu.length && area.length) { - if($(area).is(':visible')) { - area.css({ - 'display': 'none' - }); - }else{ - area.css({ - 'position': 'absolute', - 'width': '100%', - 'display': 'block', - 'overflow': 'hidden' - }); - } - } - }, - - signOutHandler: function () { - signOut(this); - }, - - render: function () { - var result = this.model.get('result');debugger; - var header = InfinniUI.config.configName; - var $wrap = $(this.template({header: header})); - var $loginTemplate, - self = this; - - window.adjustLoginResult(result).then(function(r){ - if (result) { - $loginTemplate = $(self.successTemplate({ - displayName: r.UserName, - activeRole: r.ActiveRole, - roles: _.pluck(result.Roles, 'DisplayName').join(', ') - })); - } else { - $loginTemplate = $(self.enterTemplate({})); - } - - $wrap.find('.page-header-inner').prepend($loginTemplate); - self.$el - .empty() - .append($wrap); - }); - - this.$el.find('.calendar').datepicker({ - todayHighlight: true, - language: 'ru' - }); - - //~fix DatePicker auto close - this.$el.find('.dropdown-toggle').on('click.bs.dropdown', function() { - var clicks = $(this).data('clicks'); - if (clicks) { - $(this).parent('.dropdown').off('hide.bs.dropdown'); - } else { - $(this).parent('.dropdown').on('hide.bs.dropdown', function () {return false;}); - } - $(this).data("clicks", !clicks); - }); - - return this; - } -}); -//####app/controls/application/statusBar/authentication/SignInSuccessView.js -jQuery(document).ready(function () { - if( InfinniUI.config.disableGetCurrentUser !== false ) { - InfinniUI.user = { - onReadyDeferred: $.Deferred(), - onReady: function(handler){ - this.onReadyDeferred.done(handler); - } - }; - - refreshUserInfo(); - } -}); - -function getUserInfo(self){ - var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); - authProvider.getCurrentUser( - function (result) { - self.model.set('result', result); - }, - function (error) { - showObject('#signInInternalResult', error); - } - ); -} - -function refreshUserInfo() { - var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); - authProvider.getCurrentUser( - function (result) { - InfinniUI.user.onReadyDeferred.resolve(result); - }, - function (error) { - InfinniUI.user .onReadyDeferred.resolve(null); - } - ); -} - -function changePassword() { - var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); - - authProvider.changePassword( - $('#oldPassword').val(), - $('#newPassword').val(), - function (result) { - refreshUserInfo(); - }, - function (error) { - showObject('#changePasswordResult', error); - } - ); -} - -function changeProfile() { - var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); - - authProvider.changeProfile( - $('#displayName').val(), - $('#description').val(), - function (result) { - refreshUserInfo(); - }, - function (error) { - showObject('#changeProfileResult', error); - } - ); -} - -function changeActiveRole() { - var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); - - authProvider.changeActiveRole( - $('#activeRole').val(), - function (result) { - refreshUserInfo(); - }, - function (error) { - showObject('#сhangeActiveRoleResult', error); - } - ); -} - -function getLinkExternalLoginForm() { - var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); - - authProvider.getLinkExternalLoginForm( - getAbsoluteUri('/Home/SignInSuccess'), - getAbsoluteUri('/Home/SignInFailure'), - function (result) { - $('#linkExternalLoginForm').append(result); - }, - function (error) { - showObject('#linkExternalLoginResult', error); - } - ); -} - -function unlinkExternalLogin(provider, providerKey) { - var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); - - authProvider.unlinkExternalLogin( - provider, - providerKey, - function (result) { - refreshUserInfo(); - }, - function (error) { - showObject('#unlinkExternalLoginResult', error); - } - ); -} - -function signOut(self) { - var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); - - onSuccessSignOut(getHomePageContext()); - - authProvider.signOut( - function (result) { - - - window.getCurrentUserName = function(){ - return null; - }; - - //self.model.set('result', result); - self.model.set('result', null); - location.reload(); -// window.location = '/Home/SignIn'; - }, - function (error) { - showObject('#getCurrentUserResult', error.responseJSON); - } - ); -} - -function setUserInfo(userInfo) { - //showObject('#getCurrentUserResult', userInfo); - //$('#displayName').val(userInfo.DisplayName); - //$('#description').val(userInfo.Description); - //$('#activeRole').val(userInfo.ActiveRole); - - if (userInfo.Logins !== null && userInfo.Logins !== undefined) { - var externalLogins = $('#externalLogins'); - - for (var i = 0; i < userInfo.Logins.length; ++i) { - var loginInfo = userInfo.Logins[i]; - var provider = loginInfo.Provider; - var providerKey = loginInfo.ProviderKey; - - var unlinkButton = $(document.createElement('input')); - unlinkButton.attr('type', 'button'); - unlinkButton.attr('value', provider); - unlinkButton.attr('onclick', 'unlinkExternalLogin(\'' + provider + '\', \'' + providerKey + '\')'); - externalLogins.append(unlinkButton); - } - } - getLinkExternalLoginForm(); -} - -function getAbsoluteUri(relativeUri) { - return location.protocol + '//' + location.host + relativeUri; -} - -function showObject(element, object) { - var text = formatObject(object); - $(element).text(text); -} - -function formatObject(object) { - return JSON.stringify(object, null, 4); -} - -//####app/controls/application/statusBar/authentication/SignInView.js -jQuery(document).ready(function () { - if( InfinniUI.config.disableSignInExternalForm !== false ) { - getSignInExternalForm(); - } -}); - -function signInInternal(self) { - var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); - authProvider.signInInternal( - $('#userName').val(), - $('#password').val(), - $('#remember').is(':checked'), - function (result) { - - - window.getCurrentUserName = function(){ - return result.UserName; - }; - - self.model.set('result', result); - self.$modal.modal('hide'); - location.reload(); - }, - function (error) { - if(error.Error.indexOf('Invalid username or password') > -1){ - toastr.error('Неверный логин или пароль', "Ошибка!"); - } - showObject('#signInInternalResult', error); - } - ); -} - -function getSignInExternalForm() { - var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); - authProvider.getSignInExternalForm( - getAbsoluteUri('/Home/SignInSuccess'), - getAbsoluteUri('/Home/SignInFailure'), - function (result) { - $('#signInExternalForm').append(result); - }, - function (error) { - showObject('#signInExternalResult', error); - } - ); -} - -function getAbsoluteUri(relativeUri) { - return location.protocol + '//' + location.host + relativeUri; -} - -function showObject(element, object) { - var text = formatObject(object); - $(element).text(text); -} - -function formatObject(object) { - return JSON.stringify(object, null, 4); -} - -//####app/controls/application/statusBar/authentication/authenticationProvider.js -/** -  * Провайдер аутентификации. -  * -  * @constructor -  */ -function AuthenticationProvider(baseAddress) { - this.baseAddress = baseAddress; -} - - -_.extend(AuthenticationProvider.prototype, { - handlers: { - onActiveRoleChanged: $.Callbacks(), - onSignInInternal: $.Callbacks(), - onSignOut: $.Callbacks() - }, - - /** -      * Возвращает информацию о текущем пользователе. -      * -      * @public -      */ - getCurrentUser: function(resultCallback, errorCallback) { - this.sendPostRequestForServiceResult('/Auth/GetCurrentUser', {}, resultCallback, errorCallback); - }, - - /** -      * Изменяет пароль текущего пользователя. -      * -      * @public -      */ - changePassword: function (oldPassword, newPassword, resultCallback, errorCallback) { - var changePasswordForm = { - OldPassword: oldPassword, - NewPassword: newPassword - }; - - this.sendPostRequestForServiceResult('/Auth/ChangePassword', changePasswordForm, resultCallback, errorCallback); - }, - - /** -      * Изменяет персональную информацию текущего пользователя. -      * -      * @public -      */ - changeProfile: function (displayName, description, resultCallback, errorCallback) { - var changeProfileForm = { - DisplayName: displayName, - Description: description - }; - - this.sendPostRequestForServiceResult('/Auth/ChangeProfile', changeProfileForm, resultCallback, errorCallback); - }, - - /** -      * Изменяет активную роль текущего пользователя. -      * -      * @public -      */ - changeActiveRole: function (activeRole, resultCallback, errorCallback) { - var changeActiveRoleForm = { - ActiveRole: activeRole - }; - - this.sendPostRequestForServiceResult('/Auth/ChangeActiveRole', changeActiveRoleForm, function(){ - var args = _.toArray(arguments); - args.push(activeRole); - if(resultCallback){ - resultCallback.apply(this, args); - } - - this.handlers.onActiveRoleChanged.fire.apply(this.handlers.onActiveRoleChanged, args); - }, errorCallback); - }, - - /** -      * Осуществляет вход пользователя в систему через внутренний провайдер. -      * -      * @public -      */ - signInInternal: function (userName, password, remember, resultCallback, errorCallback) { - var signInInternalForm = { - UserName: userName, - Password: password, - Remember: remember - }; - - this.sendPostRequestForServiceResult('/Auth/SignInInternal', signInInternalForm, resultCallback, errorCallback); - }, - - /** -      * Возвращает форму входа пользователя в систему через внешний провайдер. -      * -      * @public -      */ - getSignInExternalForm: function (successUrl, failureUrl, resultCallback, errorCallback) { - this.getExternalLoginForm('/Auth/SignInExternal', successUrl, failureUrl, resultCallback, errorCallback); - }, - - /** -      * Возвращает форму добавления текущему пользователю имени входа у внешнего провайдера. -      * -      * @public -      */ - getLinkExternalLoginForm: function (successUrl, failureUrl, resultCallback, errorCallback) { - this.getExternalLoginForm('/Auth/LinkExternalLogin', successUrl, failureUrl, resultCallback, errorCallback); - }, - - /** -      * Удаляет у текущего пользователя имя входа у внешнего провайдера. -      * -      * @public -      */ - unlinkExternalLogin: function (provider, providerKey, resultCallback, errorCallback) { - var unlinkExternalLoginForm = { - Provider: provider, - ProviderKey: providerKey - }; - - this.sendPostRequest('/Auth/UnlinkExternalLogin', unlinkExternalLoginForm, resultCallback, errorCallback); - }, - - /** -      * Выход пользователя из системы. -      * -      * @public -      */ - signOut: function (resultCallback, errorCallback) { - var signOutInternalForm = { - "id" : null, - "changesObject" : {}, - "replace" : false - }; - - this.sendPostRequestForServiceResult('/Auth/SignOut', null, function(){ - InfinniUI.user.onReadyDeferred = $.Deferred(); - InfinniUI.user.onReadyDeferred.resolve(null); - - var args = _.toArray(arguments); - if(resultCallback){ - resultCallback.apply(this, args); - } - - this.handlers.onSignOut.fire.apply(this.handlers.onSignOut, args); - - }.bind(this), errorCallback); - }, - - getExternalLoginForm: function (requestUri, successUrl, failureUrl, resultCallback, errorCallback) { - var url = this.baseAddress + requestUri; - this.sendPostRequest('/Auth/GetExternalProviders', {}, - function (result) { - var formElement = $(document.createElement('form')); - formElement.attr('method', 'POST'); - formElement.attr('action', url); - - var successUrlElement = $(document.createElement('input')); - successUrlElement.attr('type', 'hidden'); - successUrlElement.attr('name', 'SuccessUrl'); - successUrlElement.attr('value', successUrl); - formElement.append(successUrlElement); - - var failureUrlElement = $(document.createElement('input')); - failureUrlElement.attr('type', 'hidden'); - failureUrlElement.attr('name', 'FailureUrl'); - failureUrlElement.attr('value', failureUrl); - formElement.append(failureUrlElement); - - if (result !== null && result !== undefined) { - for (var i = 0; i < result.length; ++i) { - var providerInfo = result[i]; - var providerType = providerInfo.Type; - var providerName = providerInfo.Name; - - var loginButton = $(document.createElement('button')); - loginButton.attr('type', 'submit'); - loginButton.attr('name', 'Provider'); - loginButton.attr('value', providerType); - loginButton.text(providerName); - formElement.append(loginButton); - } - } - - resultCallback(formElement); - }, - errorCallback - ); - }, - - sendGetRequest: function (requestUri, resultCallback, errorCallback) { - $.ajax(this.baseAddress + requestUri, { - type: 'GET', - xhrFields: { - withCredentials: true - }, - beforeSend: this.onBeforeRequest(), - success: this.onSuccessRequest(resultCallback), - error: this.onErrorRequest(function (error) { - if(errorCallback) { - errorCallback(error.responseJSON); - } - }) - }); - }, - - sendPostRequest: function (requestUri, requestData, resultCallback, errorCallback) { - var that = this; - - if (requestData !== null) { - requestData = JSON.stringify(requestData); - } - $.ajax(this.baseAddress + requestUri, { - type: 'POST', - xhrFields: { - withCredentials: true - }, - data: requestData, - contentType: 'application/json', - beforeSend: this.onBeforeRequest(), - success: this.onSuccessRequest(resultCallback), - error: this.onErrorRequest(function (error) { - if(error.status != 200) { - if(errorCallback) { - errorCallback(error.responseJSON); - } - } else { - that.onSuccessRequest(resultCallback).apply(that, arguments); - } - }) - }); - }, - - sendPostRequestForServiceResult: function (requestUri, requestData, successCallback, errorCallback) { - var resultCallback = function(){ - var args = _.toArray(arguments), - serviceResult = args[0]; - - if(serviceResult['Success']){ - args[0] = serviceResult['Result']; - - if( _.isFunction(successCallback) ){ - successCallback.apply(this, args); - } - } else { - args[0] = serviceResult['Error']; - - if( _.isFunction(errorCallback) ){ - errorCallback.apply(this, args); - } - } - }; - - this.sendPostRequest(requestUri, requestData, resultCallback, errorCallback); - }, - - onActiveRoleChanged: function(handler){ - this.handlers.onActiveRoleChanged.add(handler); - }, - - onSignInInternal: function(handler){ - this.handlers.onSignInInternal.add(handler); - }, - - onSignOut: function(handler){ - this.handlers.onSignOut.add(handler); - } -}); - -_.extend(AuthenticationProvider.prototype, ajaxRequestMixin); - -InfinniUI.global.session = new AuthenticationProvider(InfinniUI.config.serverUrl); -//####app/controls/button/commonView/buttonView.js -/** - * @class ButtonView - * @augments ControlView - */ -var CommonButtonView = ControlView.extend({ - - className: 'pl-button', - - template: InfinniUI.Template["controls/button/commonView/template/button.tpl.html"], - - UI: { - button: 'button' - }, - - events: { - 'click button': 'onClickHandler' - }, - - initialize: function () { - ControlView.prototype.initialize.apply(this, arguments); - this.initHighlightMixin(); - }, - - updateProperties: function(){ - ControlView.prototype.updateProperties.call(this); - - this.updateContent(); - this.updateType(); - }, - - updateType: function() { - var type = this.model.get('type'); - this.getButtonElement().attr('type', type); - }, - - updateContent: function(){ - var contentTemplate = this.model.get('contentTemplate'); - var content = this.model.get('content'); - var args = { - content: content - }; - var contentElement; - var $button = this.getButtonElement(); - - if(contentTemplate){ - contentElement = contentTemplate(null, args); - $button.html(contentElement.render()); - - }else if(content !== undefined && content !== null){ - $button.html(content); - } - }, - - updateText: function(){ - var textForButton = this.model.get('text'); - if (typeof textForButton == 'string'){ - this.getButtonElement().html(textForButton); - } - }, - - updateFocusable: function () { - var focusable = this.model.get('focusable'); - - if (!focusable) { - this.getButtonElement().attr('tabindex', -1); - } else { - this.getButtonElement().removeAttr('tabindex'); - } - }, - - updateEnabled: function(){ - ControlView.prototype.updateEnabled.call(this); - - var isEnabled = this.model.get('enabled'); - this.getButtonElement().prop('disabled', !isEnabled); - }, - - updateBackground: function () { - var customStyle = this.model.get('background'); - - if (this.currentBackground) { - this.getButtonElement() - .removeClass(this.valueToBackgroundClassName(this.currentBackground)); - } - - if (customStyle) { - this.getButtonElement() - .addClass(this.valueToBackgroundClassName(customStyle)); - } - - this.currentBackground = customStyle; - }, - - render: function () { - this.prerenderingActions(); - - this.renderTemplate(this.template); - this.updateProperties(); - this.trigger('render'); - - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, - - getButtonElement: function(){ - return this.ui.button; - }, - - setFocus: function () { - this.getButtonElement().focus(); - } - - - -}); - -_.extend(CommonButtonView.prototype, highlightMixin.controlView); - - -InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.Button.common', CommonButtonView); - -//####app/controls/button/linkView/buttonView.js -/** - * @class ButtonView - * @augments ControlView - */ -var LinkButtonView = CommonButtonView.extend({ - - tagName: 'a', - - className: 'pl-button', - - attributes: { - href: 'javascript:;' - }, - - events: { - 'click': 'onClickHandler' - }, - - template: function(){return '';}, - - UI: { - }, - - getButtonElement: function(){ - return this.$el; - } - -}); - -InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.Button.link', LinkButtonView); - -//####app/controls/button/buttonControl.js -/** - * - * @param parent - * @constructor - * @augments Control - */ -function ButtonControl(viewMode) { - _.superClass(ButtonControl, this, viewMode); -} - -_.inherit(ButtonControl, Control); - -_.extend( - ButtonControl.prototype, - highlightMixin.control, { - - createControlModel: function () { - return new ButtonModel(); - }, - - createControlView: function (model, viewMode) { - if (!viewMode || !viewMode in window.InfinniUI.viewModes.Button) { - viewMode = 'common'; - } - - var ViewClass = window.InfinniUI.viewModes.Button[viewMode]; - - return new ViewClass({model: model}); - }, - - setType: function(type) { - this.controlModel.set('type', type); - }, - - getType: function() { - return this.controlModel.get('type'); - } - - }, buttonControlMixin); - - -//####app/controls/button/buttonModel.js -/** - * @class - * @augments ControlModel - */ -var ButtonModel = ControlModel.extend({ - - defaults: _.defaults({ - content: null, - contentTemplate: null, - horizontalAlignment: 'Left', - type: 'button' - }, ControlModel.prototype.defaults), - - initialize: function () { - ControlModel.prototype.initialize.apply(this, arguments); - } - -}); - -//####app/controls/button/menuItemView/buttonView.js -/** - * @class ButtonView - * @augments ControlView - */ -var MenuItemButtonView = LinkButtonView.extend({ - - updateHorizontalAlignment: function(){ - var horizontalAlignment = this.model.get('horizontalAlignment'); - var that = this; - var $el; - - domHelper.whenReady( - function(){ - $el = that.$el.parent().parent(); - return $el.length > 0; - }, - - function(){ - if(horizontalAlignment == 'Right'){ - $el - .addClass('pull-right'); - }else{ - $el - .removeClass('pull-right'); - } - } - ); - - } - -}); - -InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.Button.menuItem', MenuItemButtonView); -//####app/controls/buttonEdit/buttonEditControl.js -/** - * - * @param parent - * @constructor - * @augments TextBoxControl - */ -function ButtonEditControl(parent) { - _.superClass(ButtonEditControl, this, parent); -} - -_.inherit(ButtonEditControl, TextBoxControl); - -_.extend(ButtonEditControl.prototype, { - - createControlModel: function () { - return new ButtonEditModel(); - }, - - createControlView: function (model) { - return new ButtonEditView({model: model}); - }, - - onButtonClick: function (handler) { - this.controlView.on('buttonClick', handler); - } -}); - - -//####app/controls/buttonEdit/buttonEditModel.js -var ButtonEditModel = TextBoxModel.extend({ - - defaults: _.defaults({ - showClear: true, - readOnly: true - }, TextBoxModel.prototype.defaults), - - initialize: function () { - TextBoxModel.prototype.initialize.apply(this, arguments); - }, - - clearValue: function () { - var enabled = this.get('enabled'); - - if (enabled) { - this.set('value', null); - } - } - -}); -//####app/controls/buttonEdit/buttonEditView.js -var ButtonEditView = TextBoxView.extend(/** @lends ButtonEditView.prototype */{ - - template: { - oneline: InfinniUI.Template["controls/buttonEdit/template/textBoxInput.tpl.html"], - multiline: InfinniUI.Template["controls/buttonEdit/template/textBoxArea.tpl.html"] - }, - - className: 'pl-button-edit form-group', - - UI: _.extend({}, TextBoxView.prototype.UI, { - iconAction: '.pl-button-edit-button__icon_action', - buttonClear: '.pl-button-edit-button_clear', - buttons: '.pl-button-edit-button' - }), - - events: _.extend({}, TextBoxView.prototype.events, { - 'click .pl-button-edit-button_action': 'onClickButtonHandler', - 'click .pl-button-edit-button_clear': 'onClickClearHandler' - }), - - initHandlersForProperties: function () { - TextBoxView.prototype.initHandlersForProperties.call(this); - this.listenTo(this.model, 'change:icon', this.updateIcon); - this.listenTo(this.model, 'change:showClear', this.updateShowClear); - this.listenTo(this.model, 'change:readOnly', this.updateReadOnly); - }, - - updateProperties: function () { - TextBoxView.prototype.updateProperties.call(this); - this.updateIcon(); - this.updateShowClear(); - this.updateReadOnly(); - }, - - updateIcon: function () { - var icon = this.model.get('icon'); - this.switchClass('fa', icon, this.ui.iconAction); - }, - - updateShowClear: function () { - var showClear = this.model.get('showClear'); - var value = this.model.get('value'); - - this.ui.buttonClear.toggleClass('hidden', !showClear || _.isEmpty(value)); - }, - - updateReadOnly: function () { - var readOnly = this.model.get('readOnly'); - - this.ui.control.prop('readonly', readOnly); - }, - - updateEnabled: function () { - var enabled = this.model.get('enabled'); - TextBoxView.prototype.updateEnabled.call(this); - - //@TODO Update button states - this.ui.buttons.toggleClass('pl-button-edit-button_disabled', !enabled); - }, - - updateValue: function () { - TextBoxView.prototype.updateValue.call(this); - this.updateShowClear(); - }, - - onClickButtonHandler: function (event) { - var enabled = this.model.get('enabled'); - - if (enabled) { - this.trigger('buttonClick', event); - } - }, - - onClickClearHandler: function (event) { - this.model.clearValue(); - } - -}); -//####app/controls/comboBox/dropdown/comboBoxDropdownView.js -var ComboBoxDropdownView = Backbone.View.extend({ - - className: "pl-dropdown-container", - events: { - 'click .backdrop': 'onClickBackdropHandler', - 'keyup .pl-combobox-filter-text': 'onKeyUpHandler', - 'keydown .pl-combobox-filter-text': 'onFilterKeyDownHandler' - }, - - UI: { - items: '.pl-combobox-items', - filter: '.pl-combobox-filter', - text: '.pl-combobox-filter-text', - noItems: '.pl-combobox-items-empty', - search: '.pl-combobox-items-empty > span' - }, - - initialize: function () { - var isGrouped = this.model.get('groupValueSelector') != null; - - if (isGrouped) { - this.strategy = new ComboBoxGroupViewStrategy(this); - } else { - this.strategy = new ComboBoxPlainViewStrategy(this); - } - - this.listenTo(this.model, 'change:dropdown', this.onChangeDropdownHandler); - this.listenTo(this.model, 'change:autocompleteValue', this.onChangeSearchHandler); - this.listenTo(this.model, 'change:autocomplete', this.updateAutocomplete); - this.listenTo(this.model, 'change:selectedItem', this.onChangeSelectedItem); - this.listenTo(this.strategy, 'click', this.onClickItemHandler); - this.listenTo(this.strategy, 'mouseenter', this.onMouseEnterItemHandler); - this.model.onValueChanged(this.onChangeValueHandler.bind(this)); - - var items = this.model.get('items'); - - var view = this; - items.onChange(function () { - view.renderItems(); - }); - }, - - updateProperties: function () { - this.updateAutocomplete(); - }, - - render: function () { - var template = this.strategy.getTemplate(); - this.$el.html(template({ - multiSelect: this.model.get('multiSelect') - })); - this.bindUIElements(); - this.updateProperties(); - this.renderItems(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this.$el; - }, - - renderItems: function () { - this.$el.hide(); - var $items = this.strategy.renderItems(); - this.$items = $items; - var items = this.model.get('items'); - - var noItems = (items && items.length == 0); - this.ui.noItems.toggleClass('hidden', !noItems); - - this.markSelectedItems(); - this.markCheckedItems(); - - this.trigger('itemsRendered2'); - this.$el.show(); - }, - - setItemsContent: function (content) { - var $items = this.ui.items; - $items.empty(); - $items.append(content); - }, - - close: function () { - this.model.set('dropdown', false); - }, - - setSearchFocus: function () { - this.ui.text.focus(); - }, - - onClickBackdropHandler: function () { - this.close(); - }, - - onChangeValueHandler: function () { - this.markCheckedItems(); - }, - - markSelectedItems: function () { - var model = this.model; - if (!Array.isArray(this.$items)) { - return; - } - - var $container = this.ui.items; - var $items = this.$items; - var selectedItem = model.getSelectedItem(); - - $items.forEach(function ($item) { - var selected = selectedItem === $item.data('pl-data-item'); - $item.toggleClass('pl-combobox-selected', selected); - }); - - this.ensureVisibleSelectedItem(); - - }, - - ensureVisibleSelectedItem: function () { - var model = this.model; - if (!Array.isArray(this.$items)) { - return; - } - - var $container = this.ui.items; - var $items = this.$items; - var selectedItem = model.getSelectedItem(); - - $items.some(function ($item) { - var selected = selectedItem === $item.data('pl-data-item'); - if (selected) { - ensureItem($container, $item); - } - return selected; - }); - - function ensureItem($container, $item) { - var newScrollTop; - - var scrollTop = $container.scrollTop(); - var itemTop = $item.position().top; - var itemHeight = $item.outerHeight(); - var viewHeight = $container.innerHeight(); - if (itemTop + itemHeight > viewHeight) { - newScrollTop = scrollTop + itemTop + itemHeight - viewHeight; - } else if (itemTop < 0) { - newScrollTop = scrollTop + itemTop; - } - - if (typeof newScrollTop !== 'undefined') { - $container.scrollTop(newScrollTop); - } - } - }, - - - markCheckedItems: function () { - var model = this.model; - var value = model.getValue(); - - if (!Array.isArray(this.$items)) { - return; - } - - var $items = this.$items; - var isMultiSelect = !!model.get('multiSelect'); - var items = []; - - if (isMultiSelect && Array.isArray(value)) { - items = value.map(function (val) { - return model.itemByValue(val); - }); - } else { - items = [model.itemByValue(value)]; - } - - $items.forEach(function ($item) { - var selected = items.indexOf($item.data('pl-data-item')) !== -1; - $item.toggleClass('pl-combobox-checked', selected); - }); - }, - - onChangeDropdownHandler: function (model, dropdown) { - if (!dropdown) { - this.remove(); - } - }, - - updateAutocomplete: function () { - var autocomplete = this.model.get('autocomplete'); - this.ui.filter.toggleClass('hidden', !autocomplete); - }, - - onMouseEnterItemHandler: function (item) { - this.model.setSelectedItem(item); - }, - - onClickItemHandler: function (item) { - var isEnabled = !this.model.isDisabledItem(item); - if(isEnabled) { - this.model.toggleItem(item); - this.close(); - } - }, - - onKeyUpHandler: function (event) { - //@TODO grow input - var text = this.ui.text.val(); - this.trigger('search', text); - }, - - onKeyDownHandler: function (event) { - var model = this.model; - event.preventDefault(); - this.onFilterKeyDownHandler(event); - }, - - onFilterKeyDownHandler: function (event) { - var model = this.model; - switch (event.which) { - case 36://Home; - model.selectFirstItem(); - break; - case 35: //End - model.selectLastItem(); - break; - case 38: //Up - model.selectPrevItem(); - break; - case 40: //Down - model.selectNextItem(); - break; - case 13: - this.onClickItemHandler(model.getSelectedItem()); - break; - case 9: - this.close(); - break; - case 27://Escape - this.close(); - event.stopPropagation(); - break; - } - }, - - onChangeSearchHandler: function (model, value) { - this.ui.search.text(value); - }, - - onChangeSelectedItem: function (model, value) { - this.markSelectedItems(); - }, - - updatePosition: function (parentDOMElement) { - var direction = this.getDropdownDirection(parentDOMElement); - this.setPositionFor(parentDOMElement, direction ); - }, - - setPositionFor: function (parentDOMElement, direction) { - clearInterval(this._intervalId); - - this.applyStyle(parentDOMElement, direction); - this._intervalId = setInterval(this.applyStyle.bind(this, parentDOMElement, direction), 100); - }, - - remove: function () { - clearInterval(this._intervalId); - return Backbone.View.prototype.remove.apply(this, arguments); - }, - - getDropdownDirection: function (parentDOMElement) { - - var windowHeight = $(window).height(); - var rect = parentDOMElement.getBoundingClientRect(); - var height = this.$el.height(); - - var direction = 'bottom'; - if (rect.bottom + height + 30 > windowHeight && rect.bottom > windowHeight / 2) { - direction = 'top'; - } - - return direction; - }, - - applyStyle: function (parentDOMElement, direction) { - var rect = parentDOMElement.getBoundingClientRect(); - - var style = { - left: window.pageXOffset + rect.left, - width: Math.round(rect.width) - 1 - }; - - if (direction === 'bottom') { - style.top = window.pageYOffset + rect.bottom; - } else { - style.top = window.pageYOffset + rect.top - this.$el.height(); - } - - this.$el.css(style); - } - -}); - -_.extend(ComboBoxDropdownView.prototype, bindUIElementsMixin); - -//####app/controls/comboBox/dropdown/viewBaseStrategy.js -/** - * @abstract - * @param dropdownView - * @constructor - */ -function ComboBoxBaseViewStrategy(dropdownView) { - this.dropdownView = dropdownView; -} - -/** - * - * @param {string} attributeName - * @returns {*} - */ -ComboBoxBaseViewStrategy.prototype.getModelAttribute = function (attributeName) { - var model = this.dropdownView.model; - - return model.get(attributeName); -}; - -ComboBoxBaseViewStrategy.prototype.isEnabledItem = function (item) { - return !this.dropdownView.model.isDisabledItem(item); -}; - -/** - * @description Рендеринг элементов списка - * @abstract - * @returns {Array.} Элементы списка - */ -ComboBoxBaseViewStrategy.prototype.renderItems = function () { - throw new Error('Method renderItems not implemented'); -}; - -/** - * @abstract - */ -ComboBoxBaseViewStrategy.prototype.getTemplate = function () { - -}; - -/** - * Рендеринг заданных элементов списка - * @param {Array.} items - * @returns {Array.} - * @private - */ -ComboBoxBaseViewStrategy.prototype._renderItems = function (items) { - var - $items, - collection = this.getModelAttribute('items'), - itemTemplate = this.getModelAttribute('itemTemplate'); - - $items = items.map(function (item) { - var itemEl = itemTemplate(undefined, { - value: item, - index: collection.indexOf(item) - }); - var $item = itemEl.render(); - - if (typeof item !== 'undefined') { - $item.data('pl-data-item', item); - } - - this.addOnClickEventListener($item, item); - this.addOnHoverEventListener($item, item); - - itemEl.setEnabled( this.isEnabledItem(item) ); - - return $item; - }, this); - - return $items; -}; - -/** - * - * @param {jQuery} $el - */ -ComboBoxBaseViewStrategy.prototype.addOnClickEventListener = function ($el) { - var el = $el[0]; - var params = Array.prototype.slice.call(arguments, 1); - var handler = this.trigger.bind(this, 'click'); - el.addEventListener('click', function () { - handler.apply(this, params); - }); -}; - - -ComboBoxBaseViewStrategy.prototype.addOnHoverEventListener = function ($el) { - var el = $el[0]; - var params = Array.prototype.slice.call(arguments, 1); - var handler = this.trigger.bind(this, 'mouseenter'); - $el.on('mouseenter', function () { - handler.apply(this, params); - }); -}; - -_.extend(ComboBoxBaseViewStrategy.prototype, Backbone.Events); -//####app/controls/comboBox/dropdown/viewGroupStrategy.js -/** - * - * @param {ComboBoxDropdownView} dropdownView - * @augments ComboBoxBaseViewStrategy - * @constructor - */ -function ComboBoxGroupViewStrategy(dropdownView) { - ComboBoxBaseViewStrategy.call(this, dropdownView); -} - -ComboBoxGroupViewStrategy.prototype = Object.create(ComboBoxBaseViewStrategy.prototype); -ComboBoxGroupViewStrategy.prototype.constructor = ComboBoxGroupViewStrategy; - -ComboBoxGroupViewStrategy.prototype.template = InfinniUI.Template["controls/comboBox/dropdown/template/group/template.tpl.html"]; - -ComboBoxGroupViewStrategy.prototype.renderItems = function () { - var - collection = this.getModelAttribute('items'), - groupingFunction = this.getModelAttribute('groupValueSelector'), - groups = {}, - $items; - - collection.forEach(function (item, index) { - var groupKey = groupingFunction(undefined, {value: item, index: index}); - - if (!(groupKey in groups)) { - groups[groupKey] = []; - } - - groups[groupKey].push(item); - }); - - $items = this.renderGroups(groups); - return $items; -}; - -/** - * @description Рендереинг группированных элементов - * @param {Array.} groups - * @returns {Array.} Элементы групп - */ -ComboBoxGroupViewStrategy.prototype.renderGroups = function (groups) { - var - groupItemTemplate = this.getModelAttribute('groupItemTemplate'), - collection = this.getModelAttribute('items'), - $items= [], - $groupItems, - $groups = []; - - for (var name in groups) { - var items = groups[name]; - //Шаблонизированный заголовок группы - var $header = groupItemTemplate(undefined, { - index: collection.indexOf(items[0]), - item: items[0] - } - ); - //Шаблонизированные элементы группы - var $groupItems = this._renderItems(items); - - var groupView = new ComboBoxGroupView({ - header: $header.render(), - items: $groupItems - }); - - Array.prototype.push.apply($items, $groupItems); - $groups.push(groupView.render()); - } - - this.dropdownView.setItemsContent($groups); - - return $items; -}; - - -ComboBoxGroupViewStrategy.prototype.getTemplate = function () { - return this.template; -}; - - -//####app/controls/comboBox/dropdown/viewPlainStrategy.js -/** - * - * @param {ComboBoxDropdownView} dropdownView - * @augments ComboBoxBaseViewStrategy - * @constructor - */ -function ComboBoxPlainViewStrategy(dropdownView) { - ComboBoxBaseViewStrategy.call(this, dropdownView); -} - -ComboBoxPlainViewStrategy.prototype = Object.create(ComboBoxBaseViewStrategy.prototype); -ComboBoxPlainViewStrategy.prototype.constructor = ComboBoxPlainViewStrategy; - -ComboBoxPlainViewStrategy.prototype.renderItems = function () { - var - $items = [], - items = this.getModelAttribute('items'); - - if (items) { - $items = this._renderItems(items.toArray()); - } - - this.dropdownView.setItemsContent($items); - - return $items; -}; - -ComboBoxPlainViewStrategy.prototype.template = InfinniUI.Template["controls/comboBox/dropdown/template/plain/template.tpl.html"]; - -ComboBoxPlainViewStrategy.prototype.getTemplate = function () { - return this.template; -}; - -//####app/controls/comboBox/dropdown/group/groupView.js -var ComboBoxGroupView = Backbone.View.extend({ - - template: InfinniUI.Template["controls/comboBox/dropdown/group/template/template.tpl.html"], - - UI: { - header: '.pl-combobox-group__header', - items: '.pl-combobox-group__items' - }, - - initialize: function (options) { - this.options = { - header: options.header, - items: options.items - }; - - }, - - render: function () { - var options = this.options; - this.$el.html(this.template()); - this.bindUIElements() - this.ui.header.append(options.header); - this.ui.items.append(options.items); - - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - - return this.$el; - } - -}); - -_.extend(ComboBoxGroupView.prototype, bindUIElementsMixin); - -//####app/controls/comboBox/values/comboBoxValue.js -var ComboBoxValueModel = Backbone.Model.extend({ - -}); - -var ComboBoxValue = Backbone.View.extend({ - - template: InfinniUI.Template["controls/comboBox/values/template/value.tpl.html"], - - tagName: 'li', - - className: 'pl-combobox-value', - - events: { - "click .pl-combobox-value-remove": "onClickRemoveHandler" - }, - - UI: { - item: '.pl-combobox-value-item' - }, - - initialize: function (options) { - this.model = new ComboBoxValueModel(options); - }, - - render: function () { - this.$el.html(this.template()); - - this.bindUIElements(); - var $value = this.model.get('$value'); - this.ui.item.append($value); - return this.$el; - }, - - onClickRemoveHandler: function () { - var value = this.model.get('value'); - this.trigger('remove', value); - } - -}); - -_.extend(ComboBoxValue.prototype, bindUIElementsMixin); -//####app/controls/comboBox/values/comboBoxValues.js -var ComboBoxValuesModel = Backbone.Model.extend({ - defaults: { - enabled: true - }, - - initialize: function () { - this.items = []; - } -}); - -var ComboBoxValues = Backbone.View.extend({ - - tagName: 'ul', - - className: 'pl-combobox-values', - - template: InfinniUI.Template["controls/comboBox/values/template/values.tpl.html"], - - events: { - 'keypress .pl-combobox-search-text': 'onKeyPressHandler', - 'keydown .pl-combobox-search-text': 'onKeyDownHandler', - 'keyup .pl-combobox-search-text': 'onKeyUpHandler', - 'click': 'onClickHandler' - }, - - UI: { - search: ".pl-combobox-search", - text: ".pl-combobox-search-text" - }, - - initialize: function (options) { - this.model = new ComboBoxValuesModel(options); - }, - - render: function () { - - this.$el.empty(); - - this.$el.html(this.template()); - this.bindUIElements(); - - var model = this.model; - var $items = - model.get('items') - .map(function(item) { - var view = new ComboBoxValue({ - "$value": item.$value, - "value": item.value - }); - - this.listenTo(view, 'remove', this.onRemoveValueHandler); - return view.render(); - }, this); - - this.ui.search.before($items); - - return this.$el; - }, - - KeyCode: { - enter: 13, - backspace: 8, - left: 37, - right: 39, - home: 36, - end: 35, - tab: 9 - }, - - setFocus: function () { - this.ui.text.focus(); - }, - - onKeyPressHandler: function (event) { - var key = event.which; - - if (key === this.KeyCode.enter) { - - } - - console.log('onKeyPressHandler', event.which, this.ui.text.val()); - }, - - onKeyDownHandler: function (event) { - //handle left/right/tab/Shift-tab/backspace/end/home - var key = event.which; - if (key === this.KeyCode.left) { - - } else { - - } - console.log('onKeyDownHandler', event.which, this.ui.text.val()); - }, - - onKeyUpHandler: function (event) { - //@TODO grow input - var text = this.ui.text.val(); - this.trigger('search', text); - }, - - onRemoveValueHandler: function (value) { - this.trigger('remove', value); - }, - - onClickHandler: function (event) { - this.setFocus(); - } - -}); - -_.extend(ComboBoxValues.prototype, bindUIElementsMixin); -//####app/controls/dataGrid/dataGridControl.js -/** - * - * @constructor - * @augments ListEditorBaseControl - */ -function DataGridControl() { - _.superClass(DataGridControl, this); -} - -_.inherit(DataGridControl, ListEditorBaseControl); - -_.extend(DataGridControl.prototype, { - - createControlModel: function () { - return new DataGridModel(); - }, - - createControlView: function (model) { - return new DataGridView({model: model}); - }, - - onCheckAllChanged: function (handler) { - this.controlModel.onCheckAllChanged(handler); - }, - - setEnabled: function(value) { - this.controlModel.set('enabled', value); - }, - - onRowClick: function(callback) { - this.controlView.$el.on('click', '.pl-datagrid__body .pl-datagrid-row', callback); - }, - - onRowDoubleClick: function(callback) { - this.controlView.$el.on('dblclick', '.pl-datagrid__body .pl-datagrid-row', callback); - } -}); - - -//####app/controls/dataGrid/dataGridModel.js -/** - * @constructor - * @augments ListEditorBaseModel - */ -var DataGridModel = ListEditorBaseModel.extend({ - defaults: _.defaults({ - showSelectors: true, - checkAllVisible: false, - checkAll: false, - focusable: false, - sortedColumn: null - }, ListEditorBaseModel.prototype.defaults), - - initialize: function () { - ListEditorBaseModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - this.initColumns(); - }, - - toggleCheckAll: function () { - this.set('checkAll', !this.get('checkAll')); - }, - - onCheckAllChanged: function (handler) { - this.on('change:checkAll', function (model, checkAll) { - handler.call(null, {value: checkAll}); - }); - }, - - /** - * @protected - */ - initColumns: function () { - this.set('columns', new Collection()); - } -}); - -//####app/controls/dataGrid/dataGridView.js -/** - * @constructor - * @augments ListEditorBaseView - */ -var DataGridView = ListEditorBaseView.extend({ - - template: { - "grid": InfinniUI.Template["controls/dataGrid/template/dataGrid.tpl.html"], - "gridStretched": InfinniUI.Template["controls/dataGrid/template/dataGridStretched.tpl.html"], - "headerCell": InfinniUI.Template["controls/dataGrid/template/headerCell.tpl.html"], - "sizeCell": InfinniUI.Template["controls/dataGrid/template/sizeCell.tpl.html"] - }, - - className: 'pl-datagrid', - - events: _.extend({}, - ListEditorBaseView.prototype.events, - { - "click .pl-datagrid-toggle_all": "onClickCheckAllHandler", - 'click thead .pl-datagrid-row__cell': 'onClickToHeaderCellHandler' - } - ), - - UI: _.defaults({ - body: ".pl-datagrid__body", - head: ".pl-datagrid__head", - headContainer: ".pl-datagrid-container_head", - - header: '.pl-datagrid-row_header', - firstRows: '.pl-datagrid-row_first', - toggleCell: ".pl-toggle-cell", - checkAll: ".pl-datagrid-toggle__button", - items: 'tbody' - }, ListEditorBaseView.prototype.UI), - - initialize: function (options) { - ListEditorBaseView.prototype.initialize.call(this, options); - this.rowElements = new HashMap(); - }, - - initHandlersForProperties: function(){ - ListEditorBaseView.prototype.initHandlersForProperties.call(this); - - this.listenTo(this.model, 'change:showSelectors', this.updateShowSelectors); - this.listenTo(this.model, 'change:checkAllVisible', this.updateCheckAllVisible); - this.listenTo(this.model, 'change:checkAll', this.updateCheckAll); - - /** Update hash item => element when item changed **/ - var rowElements = this.rowElements; - var model = this.model; - this.model.get('items').onChange(function(event){ - if (event.action === 'replace') { - event.oldItems.forEach(function (oldItem, index) { - rowElements.add(event.newItems[index], rowElements.get(oldItem)); - rowElements.remove(oldItem); - }); - } - }); - }, - - updateProperties: function () { - ListEditorBaseView.prototype.updateProperties.call(this); - this.updateShowSelectors(); - this.updateCheckAllVisible(); - this.updateCheckAll(); - this.updateDisabledItem(); - }, - - updateShowSelectors: function () { - var showSelectors = this.model.get('showSelectors'); - this.$el.toggleClass('pl-datagrid_selectors_show', showSelectors); - this.$el.toggleClass('pl-datagrid_selectors_hide', !showSelectors); - }, - - updateGrouping: function () { - - }, - - updateVerticalAlignment: function () { - ListEditorBaseView.prototype.updateVerticalAlignment.call(this); - this.switchClass('verticalAlignment', this.model.get('verticalAlignment'), this.ui.body, false); - }, - - updateCheckAll: function () { - var checkAll = this.model.get('checkAll'); - this.ui.checkAll.prop('checked', checkAll); - }, - - getHorizontalScrollBarWidth: function () { - - if (typeof DataGridView.scrollbarWidth === 'undefined') { - var scrollDiv = document.createElement('div'); - var body = document.body; - - scrollDiv.className = 'modal-scrollbar-measure'; - var style = { - position: "absolute", - top: "-9999px", - width: "50px", - height: "50px", - overflow: "scroll" - }; - - for(var name in style) { - scrollDiv.style[name] = style[name] - } - - body.appendChild(scrollDiv); - DataGridView.scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; - body.removeChild(scrollDiv); - } - - return DataGridView.scrollbarWidth; - }, - - updateCheckAllVisible: function () { - var checkAllVisible = this.model.get('checkAllVisible'); - this.ui.checkAll.toggleClass('hidden', !checkAllVisible); - }, - - updateMultiSelect: function () { - ListEditorBaseView.prototype.updateMultiSelect.call(this); - - var multiSelect = this.model.get('multiSelect'); - this.$el.toggleClass('pl-datagrid_select_multi', multiSelect === true); - this.$el.toggleClass('pl-datagrid_select_single', multiSelect !== true); - }, - - updateValue: function () { - var - model = this.model, - value = model.get('value'), - indices = [], - items = model.get('items'); - - if(!model.get('multiSelect') && value !== undefined && value !== null){ - value = [value]; - } - - if (Array.isArray(value)) { - indices = value.map(function (val) { - return model.itemIndexByValue(val); - }) - .filter(function (index) { - return index !== -1; - }); - } - - this.rowElements.forEach(function (rowElement, item) { - var index = items.indexOf(item); - var toggle = indices.indexOf(index) !== -1; - rowElement.toggle(toggle); - }); - - }, - - updateSelectedItem: function () { - var model = this.model, - selectedItem = model.get('selectedItem'); - - this.rowElements.forEach(function (rowElement, item) { - rowElement.setSelected(item === selectedItem); - }); - }, - - updateDisabledItem: function () { - var model = this.model, - disabledItemCondition = model.get('disabledItemCondition'), - isEnabled; - - if( disabledItemCondition != null ) { - this.rowElements.forEach(function (rowElement, item) { - isEnabled = !disabledItemCondition( undefined, {value: item} ); - if( rowElement.getSelected() === item && isEnabled === false ) { - model.set('selectedItem', null); - } - rowElement.setEnabled(isEnabled); - }); - } else { - this.rowElements.forEach(function (rowElement, item) { - rowElement.setEnabled(true); - }); - } - }, - - updateEnabled: function() { - var isEnabled = this.model.get('enabled'); - if( isEnabled ) { - this.updateDisabledItem(); - } else { - this.disableDataGridItems(); - } - }, - - disableDataGridItems: function() { - this.model.set('selectedItem', null); - this.rowElements.forEach(function (rowElement, item) { - rowElement.setEnabled(false); - }); - }, - - render: function () { - var that = this; - this.prerenderingActions(); - - var verticalAlignment = this.model.get('verticalAlignment'); - var template = (verticalAlignment === 'Stretch') ? this.template.gridStretched : this.template.grid; - this.$el.html(template()); - - this.bindUIElements(); - - this.renderHeaders(); - this.renderItems(); - - this.trigger('render'); - - this.applyColumnWidth(); - this.syncBodyAndHead(); - this.postrenderingActions(); - setTimeout(function() { - that.updateProperties(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: that}); - //devblockstop - }, 0); - return this; - }, - - applyColumnWidth: function () { - var columns = this.model.get('columns'); - var fixedTableLayout = false; - - this.ui.firstRows.children().each(function (i, el) { - var columnIndex = i % (columns.length + 1); - - if (columnIndex === 0) { - //skip columns with checkbox/radiobutton - return; - } - - var column = columns.getByIndex(columnIndex - 1); - var width = column && column.getWidth(); - - if (width) { - $(el).css('width', width); - fixedTableLayout = true; - } - }); - - this.$el.toggleClass('pl-datagrid_layout_fixed', fixedTableLayout); - }, - - syncBodyAndHead: function () { - //var $body = this.ui.body; - var $head = this.ui.head; - - $head.css('padding-right', this.getHorizontalScrollBarWidth() + "px"); - - this.ui.body - .off('scroll') - .on('scroll', this.onScrollBodyHandler.bind(this)); - - }, - - onScrollBodyHandler: function () { - this.ui.headContainer.scrollLeft(this.ui.body.scrollLeft()); - }, - - renderHeaders: function () { - var that = this; - var columns = this.model.get('columns'); - var templateHeaderCell = this.template.headerCell; - var sizeCells = []; - var templateSizeCells = this.template.sizeCell; - - var $headers = columns.toArray().map(function (column) { - - sizeCells.push(templateSizeCells()); - var $th = $(templateHeaderCell()); - - var headerTemplate = column.getHeaderTemplate(); - var header = column.getHeader(); - - $th.data('pl-column', column); - - if( column.getSortable() ) { - $th.addClass('sortable'); - - if( column.getSortDirection() ) { - setTimeout(function() { - that.setUpColumnSort(column, $th, column.getSortDirection(), false); - }, 0); - } - } - - var headerElement; - - if (headerTemplate) { - headerElement = headerTemplate(null, {value: header}); - $th.append(headerElement.render()); - - } else { - $th.append(header); - } - return $th; - }); - - this.ui.header.append($headers); - this.ui.firstRows.append(sizeCells); - }, - - renderItems: function () { - var - model = this.model, - valueSelector = model.get('valueSelector'), - itemTemplate = model.get('itemTemplate'), - items = model.get('items'), - $items = this.ui.items, - that = this; - - this.removeRowElements(); - - items.forEach(function (item, index) { - setTimeout(function() { - var element = itemTemplate(undefined, {index: index, item: item}); - - element.onBeforeClick(function() { - var items = model.get('items'), - item = items.getByIndex(index), - rowItem = that.rowElements.get(item); - if( rowItem.getEnabled() !== false ) { - model.set('selectedItem', item); - } - }); - - element.onToggle(function() { - var enabled = this.model.get('enabled'); - var items = model.get('items'); - - if(enabled){ - model.toggleValue(valueSelector(undefined, {value:items.getByIndex(index)})); - } - }); - element.childElements = element.control.controlView.childElements; - that.addRowElement(item, element); - - var $element = element.render(); - $items.append($element); - }, 0); - }, this); - - }, - - updateFocusable: function () { - var focusable = this.model.get('focusable'); - - this.rowElements.values.forEach(function (element) { - if (focusable) { - element.control.controlView.$el.attr('tabindex', 0); - } else { - element.control.controlView.$el.removeAttr('tabindex'); - } - }) - }, - - addRowElement: function(item, element){ - this.addChildElement(element); - this.rowElements.add(item, element); - }, - - removeRowElements: function () { - this.removeChildElements(); - this.rowElements.clear(); - }, - - onClickCheckAllHandler: function () { - this.model.toggleCheckAll(); - }, - - onClickToHeaderCellHandler: function (e) { - var $th = $(e.currentTarget), - column = $th.data('pl-column'); - - if( column && column.isSortable() ){ - if(column.getSortDirection() === null) { - this.resetSort(); - this.setUpColumnSort(column, $th, 'asc'); - } else if( column.getSortDirection() === 'asc' ) { - this.resetSort('asc'); - this.setUpColumnSort(column, $th, 'desc'); - } else if( column.getSortDirection() === 'desc' ) { - this.resetSort('desc'); - this.setUpColumnSort(column, $th, 'asc'); - } - } - }, - - setUpColumnSort: function(column, $th, direction, triggerEvent) { - column.setSortDirection(direction); - this.model.set('sortedColumn', column); - if( !column.getIsHeaderTemplateEmpty() ) { - $th.addClass('sorted headerTemplate-sorted-' + direction); - } else { - $th.addClass('sorted sorted-' + direction); - } - if( triggerEvent !== false ) { - column.trigger('onSort', {sortDirection: direction}); - } - }, - - resetSort: function(direction) { - if( !direction ) { - var $sortableCell = this.$el.find('.sorted'); - $sortableCell.removeClass('sorted headerTemplate-sorted-asc headerTemplate-sorted-desc sorted-asc sorted-desc'); - var sortedCell = this.model.get('sortedColumn'); - if( sortedCell ) { - sortedCell.setSortDirection(null); - } - } else { - var $sortableCell = this.$el.find('.sorted'); - $sortableCell.removeClass('headerTemplate-sorted-' + direction + ' sorted-' + direction); - } - } - - -}); - - - -//####app/controls/dataGrid/dataGridRow/dataGridRowControl.js -/** - * - * @constructor - * @augments ListEditorBaseControl - */ -function DataGridRowControl() { - _.superClass(DataGridRowControl, this); -} - -_.inherit(DataGridRowControl, Control); - -_.extend(DataGridRowControl.prototype, { - - onToggle: function (handler) { - this.controlView.on('toggle', handler); - }, - - createControlModel: function () { - return new DataGridRowModel(); - }, - - createControlView: function (model) { - return new DataGridRowView({model: model}); - } -}); - - -//####app/controls/dataGrid/dataGridRow/dataGridRowModel.js -var DataGridRowModel = ControlModel.extend({ - -}); -//####app/controls/dataGrid/dataGridRow/dataGridRowView.js -var DataGridRowView = ControlView.extend({ - - className: 'pl-datagrid-row pl-datagrid-row_data', - - classNameSelected: 'info', - - tagName: 'tr', - - events: {}, - - template: { - singleSelect: InfinniUI.Template["controls/dataGrid/dataGridRow/template/singleSelect.tpl.html"], - multiSelect: InfinniUI.Template["controls/dataGrid/dataGridRow/template/multiSelect.tpl.html"], - dataCell: InfinniUI.Template["controls/dataGrid/dataGridRow/template/dataCell.tpl.html"] - }, - - UI: { - toggleCell: '.pl-datagrid-row__cell_toggle', - toggle: '.pl-datagrid-toggle', - toggleControl: '.pl-datagrid-toggle input' - }, - - initialize: function () { - ControlView.prototype.initialize.call(this); - this.childElements = []; - this.on('render', function () { - this.ui.toggleCell.on('click', this.onToggleHandler.bind(this)); - }, this); - }, - - initHandlersForProperties: function () { - ControlView.prototype.initHandlersForProperties.call(this); - this.listenTo(this.model, 'change:toggle', this.updateToggle); - this.listenTo(this.model, 'change:selected', this.updateSelected); - }, - - updateProperties: function () { - ControlView.prototype.updateProperties.call(this); - this.updateToggle(); - this.updateSelected(); - this.updateShowSelectors(); - }, - - updateVerticalAlignment: function () { - //Use Vertical alignment for DataGrid - }, - - render: function () { - this.prerenderingActions(); - var $el = this.$el; - var row = this; - - var templateName = this.model.get('multiSelect') ? 'multiSelect' : 'singleSelect'; - var template = this.template[templateName]; - $el.html(template()); - this.bindUIElements(); - - var templates = this.model.get('cellTemplates'); - var templateDataCell = this.template.dataCell; - if (Array.isArray(templates)) { - templates.forEach(function (template, index) { - var $cell = $(templateDataCell()); - var cellElement = template(); - $cell.append(cellElement.render()); - $el.append($cell); - row.addChildElement(cellElement); - }); - } - this.updateProperties(); - - this.trigger('render'); - - this.postrenderingActions(); - return this; - }, - - updateShowSelectors: function () { - var showSelectors = this.model.get('showSelectors'); - this.ui.toggleCell.toggleClass('hidden', !showSelectors); - }, - - updateToggle: function () { - var toggle = this.model.get('toggle'); - this.ui.toggleControl.prop('checked', !!toggle); - }, - - updateSelected: function () { - var selected = this.model.get('selected'); - this.$el.toggleClass(this.classNameSelected, !!selected); - }, - - updateEnabled: function () { - ControlView.prototype.updateEnabled.call(this); - - var enabled = this.model.get('enabled'); - this.ui.toggleControl.attr('disabled', enabled ? null : 'disabled'); - }, - - onToggleHandler: function (event) { - this.trigger('toggle'); - }, - - addChildElement: function (element) { - this.childElements.push(element); - }, - - removeChildElements: function () { - this.childElements.forEach(function (element) { - element.remove(); - }); - - this.childElements.length = 0; - }, - - remove: function () { - this.removeChildElements(); - ControlView.prototype.remove.call(this); - } - - -}); - - -//####app/controls/dataNavigation/buttons/dataNavigationBaseButton.js -var DataNavigationBaseButtonModel = Backbone.Model.extend({ - - initialize: function () { - this.on('change:parent', this.subscribeToParent, this); - }, - - subscribeToParent: function () { - - } -}); - -var DataNavigationBaseButton = Backbone.View.extend({ - - tagName: 'li', - - initialize: function (options) { - Backbone.View.prototype.initialize.call(this, options); - this.once('render', function () { - this.initHandlersForProperties() - }, this); - }, - - initHandlersForProperties: function () { - - }, - - updateProperties: function () { - - }, - - getData: function () { - return this.model.toJSON(); - }, - - setParent: function (parent) { - this.model.set('parent', parent); - this.subscribeForParent(parent); - }, - - render: function () { - var template = this.template(this.getData()); - this.$el.html(template); - this.trigger('render'); - this.updateProperties(); - return this; - }, - - subscribeForParent: function (parent) { - - } - -}); - - -//####app/controls/dataNavigation/buttons/dataNavigationNextButton.js -var DataNavigationNextButton = DataNavigationBaseButton.extend({ - - template: InfinniUI.Template["controls/dataNavigation/buttons/template/next.tpl.html"], - - events: { - "click": "onClickHandler" - }, - - initialize: function (options) { - this.model = new DataNavigationBaseButtonModel(); - DataNavigationBaseButton.prototype.initialize.call(this, options); - }, - - onClickHandler: function (event) { - this.trigger('command', "next"); - } - -}); - -//####app/controls/dataNavigation/buttons/dataNavigationPageButton.js -var DataNavigationPageButton = DataNavigationBaseButton.extend({ - template: InfinniUI.Template["controls/dataNavigation/buttons/template/page.tpl.html"], - - events: { - "click": "onClickHandler" - }, - - initialize: function (options) { - this.model = new DataNavigationPageButtonModel(); - DataNavigationBaseButton.prototype.initialize.call(this, options); - this.model.set('pageNumber', options.pageNumber); - }, - - initHandlersForProperties: function () { - DataNavigationBaseButton.prototype.initHandlersForProperties.call(this); - this.listenTo(this.model, 'change:isCurrent', this.updateIsCurrent); - }, - - updateProperties: function () { - DataNavigationBaseButton.prototype.updateProperties.call(this); - this.updateIsCurrent(); - }, - - updateIsCurrent: function () { - this.$el.toggleClass('active', this.model.get('isCurrent')); - }, - - onClickHandler: function (event) { - this.trigger('command', "page", {pageNumber: this.model.get('pageNumber')}); - } - -}); - - -var DataNavigationPageButtonModel = DataNavigationBaseButtonModel.extend({ - - defaults: { - isCurrent: false - }, - - subscribeToParent: function () { - DataNavigationBaseButtonModel.prototype.subscribeToParent.call(this); - - var parent = this.get('parent'); - this.listenTo(parent.model, 'change:pageNumber', function () { - this.updateIsCurrent(); - }); - this.updateIsCurrent(); - }, - - updateIsCurrent: function () { - var parent = this.get('parent'); - var isCurrent = parent.model.get('pageNumber') === this.get('pageNumber'); - this.set("isCurrent", isCurrent); - } - -}); -//####app/controls/dataNavigation/buttons/dataNavigationPrevButton.js -var DataNavigationPrevButton = DataNavigationBaseButton.extend({ - - template: InfinniUI.Template["controls/dataNavigation/buttons/template/prev.tpl.html"], - - events: { - "click": "onClickHandler" - }, - - initialize: function (options) { - this.model = new DataNavigationBaseButtonModel(); - DataNavigationBaseButton.prototype.initialize.call(this, options); - }, - - onClickHandler: function (event) { - this.trigger('command', "prev"); - } - -}); - -//####app/controls/dataNavigation/dataNavigationButtonFactory.js -function DataNavigationButtonFactory (dataNavigation) { - - this._dataNavigation = dataNavigation; -} - -DataNavigationButtonFactory.prototype.buttons = { - "prev": DataNavigationPrevButton, - "page": DataNavigationPageButton, - "next": DataNavigationNextButton -}; - -DataNavigationButtonFactory.prototype.createButton = function (type, options) { - - var buttonConstructor = this.buttons[type]; - if (typeof buttonConstructor !== 'function') { - console.error('Wrong button type: ' + type); - return; - } - - var button = new buttonConstructor(options); - button.setParent(this._dataNavigation); - return button; -}; -//####app/controls/dataNavigation/dataNavigationControl.js -function DataNavigationControl (parent) { - _.superClass(DataNavigationControl, this, parent); -} - -_.inherit(DataNavigationControl, Control); - -_.extend(DataNavigationControl.prototype, { - - createControlModel: function () { - return new DataNavigationModel(); - }, - - createControlView: function (model) { - return new DataNavigationView({model: model}); - }, - - onPageNumberChanged: function (handler) { - this.controlModel.onPageNumberChanged(handler); - }, - - onPageSizeChanged: function (handler) { - this.controlModel.onPageSizeChanged(handler); - } - -}); -//####app/controls/dataNavigation/dataNavigationModel.js -var DataNavigationModel = ControlModel.extend({ - - defaults: _.defaults({ - pageNumber: 0, - pageStart: 0, - _buttonsCount: 5, - _buttonsTemplate: ['prev', 'page', 'next'], - pageCount: null, - isDataReady: false - }, - ControlModel.prototype.defaults - ), - - initialize: function () { - ControlModel.prototype.initialize.apply(this, arguments); - this.set('availablePageSizes', new Collection()); - this.on('change:pageNumber', this.updatePageStart, this); - this.on('change:pageSize', this.updatePageSize, this); - }, - - updatePageStart: function () { - var - pageNumber = this.get('pageNumber'), - pageStart = this.get('pageStart'), - buttonsCount = this.get('_buttonsCount'); - - if (pageNumber + 1 >= pageStart + buttonsCount) { - //Выбрана последняя страница по кнопкам навигации. переместить ее в центр - pageStart = pageStart + Math.floor(buttonsCount / 2); - } else if (pageNumber === pageStart) { - //Сдвинуть кнопки навигации вправо, чтобы выбранная страница была в центре - pageStart = Math.max(0, pageStart - Math.floor(buttonsCount / 2)); - } else if (pageNumber + 1 < pageStart) { - pageStart = Math.max(0, pageNumber - 1); - } - this.set('pageStart', pageStart); - }, - - updatePageSize: function () { - //сьрос навигации - this.set('pageNumber', 0); - }, - - nextPage: function () { - var pageNumber = this.get('pageNumber'); - this.set('pageNumber', pageNumber + 1); - }, - - prevPage: function () { - var pageNumber = this.get('pageNumber'); - if (pageNumber > 0) { - this.set('pageNumber', pageNumber - 1); - } - }, - - onPageNumberChanged: function (handler) { - this.on('change:pageNumber', function (model, value) { - handler.call(null, {value: value}); - }); - }, - - onPageSizeChanged: function (handler) { - this.on('change:pageSize', function (model, value) { - handler.call(null, {value: value}); - }); - } - -}); -//####app/controls/dataNavigation/dataNavigationView.js -var DataNavigationView = ControlView.extend({ - - template: InfinniUI.Template["controls/dataNavigation/template/dataNavigation.tpl.html"], - - className: 'pl-data-navigation', - - UI: { - buttons: 'ul', - sizes: '.pl-page-size' - }, - - initialize: function (options) { - ControlView.prototype.initialize.call(this, options); - this._childViews = []; - this.buttonsFactory = new DataNavigationButtonFactory(this); - this._pageSizes = new DataNavigationPageSizes(); - this._pageSizes.setParent(this); - }, - - initHandlersForProperties: function() { - ControlView.prototype.initHandlersForProperties.call(this); - this.listenTo(this.model, 'change:pageStart', this.updateButtons); - this.listenTo(this.model, 'change:pageCount', this.updateButtons); - this.listenTo(this.model, 'change:isDataReady', this.updateButtons); - }, - - updateProperties: function() { - ControlView.prototype.updateProperties.call(this); - this.updateButtons(); - }, - - render: function () { - this.prerenderingActions(); - - this.renderTemplate(this.template); - this.updateProperties(); - this.trigger('render'); - this.renderPageSizes(); - this.postrenderingActions(); - - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, - - renderPageSizes: function () { - this.ui.sizes.append(this._pageSizes.render().$el); - }, - - renderButtons: function () { - var - template = this.model.get('_buttonsTemplate'), - buttonsCount = this.model.get('_buttonsCount'), - pageCount = this.model.get('pageCount'), - pageNumber = this.model.get('pageNumber'), - pageStart = this.model.get('pageStart'), - isDataReady = this.model.get('isDataReady'), - buttons, - nowManyElementsRemove; - - this._removeChildViews(); - - if(!isDataReady){ - return; - } - - var - buttonsFactory = this.buttonsFactory, - model = this.model; - - buttons = template.reduce(function (buttons, buttonType) { - if (buttonType === 'page') { - for (var i = 0; i < buttonsCount; i = i + 1) { - var button = buttonsFactory.createButton(buttonType, {pageNumber: pageStart + i}); - buttons.push(button) - } - } else { - var button = buttonsFactory.createButton(buttonType); - buttons.push(button); - } - - return buttons; - }, []); - - if(typeof pageCount == 'number' && pageStart + buttonsCount >= pageCount){ - nowManyElementsRemove = pageStart + buttonsCount - pageCount + 1; - - if(pageCount == 0){ - nowManyElementsRemove += 1; - } - - buttons.splice(buttons.length - nowManyElementsRemove, 100); - } - - var $buttons = buttons.map(function (button) { - this.listenTo(button, 'command', this.onCommandHandler); - this._appendChildView(button); - return button.render().$el; - }, this); - - this.ui.buttons.append($buttons); - }, - - updateButtons: function () { - this.renderButtons() - }, - - onCommandHandler: function (name, options) { - switch (name) { - case "prev": - this.model.prevPage(); - break; - case "next": - this.model.nextPage(); - break; - case "page": - this.model.set('pageNumber', options.pageNumber); - break; - } - }, - - _removeChildViews: function () { - this._childViews.forEach(function (view) { - this.stopListening(view); - view.remove(); - }, this); - this._childViews.length = 0; - }, - - _appendChildView: function (view) { - this._childViews.push(view); - } - -}); - -//####app/controls/dataNavigation/pageSizes/dataNavigationPageSizes.js -var DataNavigationPageSizes = Backbone.View.extend({ - - className: "btn-group", - - template: InfinniUI.Template["controls/dataNavigation/pageSizes/template/pageSizes.tpl.html"], - - events: { - "click button": "onClickButtonHandler" - }, - - setParent: function (parent) { - this.model = parent.model; - var collection = this.model.get('availablePageSizes'); - collection.onChange(this.onAvailablePageSizesChanged.bind(this)); - this.model.on('change:pageSize', this.renderButtons, this); - }, - - render: function () { - this.renderButtons(); - return this; - }, - - renderButtons: function () { - var collection = this.model.get('availablePageSizes'); - var pageSize = this.model.get('pageSize'); - - var html = collection.toArray().map(function (size) { - return this.template({size: size, active: pageSize === size}); - }, this); - - this.$el.html(html); - }, - - onAvailablePageSizesChanged: function () { - this.renderButtons(); - }, - - onClickButtonHandler: function (event) { - var $el = $(event.target); - - var pageSize = parseInt($el.attr('data-size'), 10); - this.model.set('pageSize', pageSize); - } - -}); - -//####app/controls/label/commonView/labelView.js -/** - * @class LabelView - * @augments ControlView - * @mixes editorBaseViewMixin - */ -var CommonLabelView = ControlView.extend(_.extend({}, editorBaseViewMixin, /** @lends LabelView.prototype */{ - className: 'pl-label', - - template: InfinniUI.Template["controls/label/commonView/template/label.tpl.html"], - - UI: _.extend({}, editorBaseViewMixin.UI, { - control: '.label-control' - }), - - initialize: function () { - ControlView.prototype.initialize.apply(this); - }, - - initHandlersForProperties: function(){ - ControlView.prototype.initHandlersForProperties.call(this); - editorBaseViewMixin.initHandlersForProperties.call(this); - - this.listenTo(this.model, 'change:displayFormat', this.updateDisplayFormat); - this.listenTo(this.model, 'change:textWrapping', this.updateTextWrapping); - this.listenTo(this.model, 'change:textTrimming', this.updateTextTrimming); - }, - - updateProperties: function(){ - ControlView.prototype.updateProperties.call(this); - editorBaseViewMixin.updateProperties.call(this); - - this.updateDisplayFormat(); - this.updateTextWrapping(); - this.updateTextTrimming(); - }, - - updateFocusable: function () { - var focusable = this.model.get('focusable'); - - if (focusable) { - this.ui.control.attr('tabindex', 0); - } else { - this.ui.control.removeAttr('tabindex'); - } - }, - - updateValue: function(){ - var escapeHtml = this.model.get('escapeHtml'); - var setContent = escapeHtml ? 'text' : 'html'; - var textForLabel = this.getLabelText(); - var $label = this.getLabelElement(); - - $label[setContent](textForLabel); - var title = String(textForLabel); - $label.attr('title', title.replace(/<\/?[^>]+>/g, '')); //strip html tags - }, - - updateDisplayFormat: function(){ - this.updateValue(); - }, - - updateTextWrapping: function(){ - var textWrapping = this.model.get('textWrapping'); - this.getLabelElement().toggleClass('pl-text-wrapping', textWrapping); - }, - - updateTextTrimming: function(){ - var textTrimming = this.model.get('textTrimming'); - this.getLabelElement().toggleClass('pl-text-trimming', textTrimming); - }, - - updateText: function () { - this.updateValue(); - }, - - getData: function () { - return _.extend( - {}, - ControlView.prototype.getData.call(this), - editorBaseViewMixin.getData.call(this), - { - text: this.getLabelText() - } - ); - }, - - render: function () { - this.prerenderingActions(); - this.renderTemplate(this.template); - - this.updateProperties(); - - this.trigger('render'); - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, - - getLabelText: function () { - var model = this.model; - var value = model.get('value'); - var text; - var format = model.get('displayFormat'); - - if (typeof value !== 'undefined' && value !== null) { - text = typeof format === 'function' ? format(null, {value: value}) : value; - }else{ - text = this.model.get('text'); - if (typeof text === 'undefined' || text == null) { - text = ''; - } - } - - return text; - }, - - getLabelElement: function(){ - return this.ui.control; - } - -})); - -InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.Label.common', CommonLabelView); - -//####app/controls/label/label.js -var LabelControl = function (viewMode) { - _.superClass(LabelControl, this, viewMode); - this.initialize_editorBaseControl(); -}; +window.InfinniUI.FilterItems = filterItems; -_.inherit(LabelControl, Control); -_.extend(LabelControl.prototype, { +filterItems.filterTreeBuilder = (function() { + var that = {}, + splitStringToArray = function(filter) { //filter is string + var tmpArr, + tmpNum, + tmpString, + tmpString2, + tmpRE, + reForDates = /date\(\'[0-9a-zA-Z\:\-\+\.\s]+\'\)/g, + reForParamAsArray = /\,[a-zA-Z0-9\'\,\_\.]+\)/g, + reForArrayFromOneElem = /\[[a-zA-Z0-9\'\_\.]+\]/g, + reForElemsOfTree = /[a-zA-Z]+[(]|\[[a-zA-Z0-9\S]+\]|[-\']{0,1}[a-zA-Z0-9_\.]+[\']{0,1}[,)$]/g, + reForClosingBrackets = /[)]/g, + reForRegExp = /\'([a-zA-Z0-9\S\W\D]+\s*)+\'/g, + reForSpaces = /\s+/g, + reForFewWordsInQuotes = /\'([a-zA-Z0-9\s]+\s*)+\'/g, + arr = []; + while( tmpArr = reForDates.exec(filter) ) { // search all dates and convert it to number of s [0.000] + tmpNum = Date.parse( tmpArr[0].slice(6, -2) ) / 1000 + ''; + filter = filter.slice(0, tmpArr.index) + tmpNum + filter.slice(tmpArr.index + tmpArr[0].length); + reForDates.lastIndex = tmpArr.index + tmpNum.length; + } + while( tmpArr = reForRegExp.exec(filter) ) { // search for regexp + tmpNum = tmpArr[0]; + if( tmpNum.search(reForSpaces) !== -1 || tmpNum.search(reForFewWordsInQuotes) !== -1 ) { + while( tmpString = reForFewWordsInQuotes.exec(tmpNum) ) { + tmpString2 = tmpString[0].replace(reForSpaces, '_'); + tmpNum = tmpNum.slice(0, tmpString.index) + tmpString2 + tmpNum.slice(tmpString.index + tmpString[0].length); + } + } else { + tmpRE = tmpNum.slice(1, -1); + tmpNum = 'tmpRE'; + } + filter = filter.slice(0, tmpArr.index) + tmpNum + filter.slice(tmpArr.index + tmpArr[0].length); + reForRegExp.lastIndex = tmpArr.index + tmpNum.length; + } + filter = filter.replace(/\s+/g, ''); + while( tmpArr = reForParamAsArray.exec(filter) ) { // search second param + tmpNum = '[' + tmpArr[0].slice(1, -1) + '])'; + filter = filter.slice(0, tmpArr.index + 1) + tmpNum + filter.slice(tmpArr.index + tmpArr[0].length); + reForParamAsArray.lastIndex = tmpArr.index + tmpNum.length; + } + while( tmpArr = reForArrayFromOneElem.exec(filter) ) { // convert array from 1 element to number or string or boolean + tmpNum = tmpArr[0].slice(1, -1); + filter = filter.slice(0, tmpArr.index) + tmpNum + filter.slice(tmpArr.index + tmpArr[0].length); + reForArrayFromOneElem.lastIndex = tmpArr.index + tmpNum.length; + } + while( tmpArr = reForElemsOfTree.exec(filter) ) { // search all functions and values with their index + if( tmpArr[0].length > 1 && (tmpArr[0].slice(-1) === ',' || tmpArr[0].slice(-1) === ')') ) { + tmpArr[0] = tmpArr[0].slice(0, -1); + } + if( tmpArr[0].length > 1 && tmpArr[0].slice(0, 1) === "'" ) { + tmpArr[0] = tmpArr[0].slice(1, -1); + } + if( tmpArr[0].search(/tmpRE/) !== -1 ) { + tmpArr[0] = tmpArr[0].slice(1, -1).split(','); + tmpArr[0][0] = tmpRE; + } + arr.push(tmpArr); + } + while( tmpArr = reForClosingBrackets.exec(filter) ) { // search all closing brackets with their index + arr.push(tmpArr); + } + arr.sort(function(a, b) { // sort arr by indexes to put all data in right order + return a.index - b.index; + }); + return arr; + }, + divideToFunctionsAndValues = function(arrayToDivide) { //arrayToDivide is array + var tmpArr = [], + values = [], + filterArr = [], + counter = 0, + that, + tmpSymbol, + thatValue, + firstPart; + // split all data to different functions + for( var i = 0, ii = arrayToDivide.length; i < ii; i += 1 ) { + if( typeof arrayToDivide[i][0] === 'string' ) { + tmpSymbol = arrayToDivide[i][0].slice(-1); + } else { + tmpSymbol = ']'; + } + if( tmpSymbol === '(' ) { // define functions from string + that = {}; + that.type = 'function'; + that.functionName = arrayToDivide[i][0].slice(0, -1); + that.index = arrayToDivide[i].index; + tmpArr.push( that ); + } else if( tmpSymbol === ')' ) { // define where end of function + filterArr[counter] = []; + firstPart = tmpArr.pop(); + firstPart.range = []; + firstPart.range.push( firstPart.index ); + firstPart.children = []; + firstPart.range.push( arrayToDivide[i].index ); + filterArr[counter] = firstPart; + counter += 1; + } else { // define params that are values + thatValue = {}; + thatValue.type = 'value'; + thatValue.valueName = arrayToDivide[i][0]; + thatValue.index = arrayToDivide[i].index; + values.push( thatValue ); + } + } + return [filterArr, values]; + }, + addValuesAsChildren = function(filterArr, values) { // filterArr, values are arrays + //add values to right place as children for functions + //define right place by range of index property + for( var i = 0, ii = values.length; i < ii; i += 1 ) { + for( var j = 0, jj = filterArr.length; j < jj; j += 1 ) { + if( values[i] !== null ) { + if( values[i].index > filterArr[j].range[0] && values[i].index < filterArr[j].range[1] ) { + filterArr[j].children.push( values[i] ); + values[i] = null; + } + } + } + } + return filterArr; + }, + filterArrToTree = function(filterArr) { // filterArr is array + // build up a filter tree + // by putting some functions as children for other + for( var i = 0; i < filterArr.length; i += 1 ) { + for( var j = 0; j < filterArr.length; j += 1 ) { + if( filterArr[j] !== null || filterArr[i] !== null ) { + //search for first result[j] where we can put result[i] as his child + //if find, put it and remove result[i] + if( filterArr[i].range[0] > filterArr[j].range[0] && filterArr[i].range[1] < filterArr[j].range[1] ) { + //if result[j] already have any children, check their indexes to define where put new child + if( filterArr[j].children[0] !== undefined && filterArr[j].children[0].index > filterArr[i].range[0] ) { + filterArr[j].children.unshift( filterArr[i] ); + filterArr.splice(i, 1); + i -= 1; + break; + } else { + filterArr[j].children.push( filterArr[i] ); + filterArr.splice(i, 1); + i -= 1; + break; + } + } + } + } + } + return filterArr[0]; + }; + that.buildUpFilterTree = function(filter) { // filter is string + var tmpArr; + tmpArr = splitStringToArray(filter); + tmpArr = divideToFunctionsAndValues(tmpArr); + tmpArr = addValuesAsChildren(tmpArr[0], tmpArr[1]); + return filterArrToTree(tmpArr); + }; + return that; +})(); - createControlModel: function () { - return new LabelModel(); - }, +//sub method for filterItems with filter methods +filterItems.filterMethods = (function() { + var that = {}; - createControlView: function (model, viewMode) { - if(!viewMode || ! (viewMode in window.InfinniUI.viewModes.Label)){ - viewMode = 'simple'; - } + that.eq = function(value, items, context) { // value is array: value[0] - param, value[1] - value + var tmpResult = [], + tmpResult2, + length, + globalUI = InfinniUI.ObjectUtils; + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + if( context ) { + tmpResult2 = []; + if( items[i][context] === undefined ) { + length = -1; + } else { + length = items[i][context].length; + } + for( var j = 0, jj = length; j < jj; j += 1 ) { + if( globalUI.getPropertyValue( items[i][context][j], value[0] ) === value[1] ) { + tmpResult2.push( items[i] ); + } + } + if( length === tmpResult2.length ) { + tmpResult.push( items[i] ); + } + } else { + if( globalUI.getPropertyValue( items[i], value[0] ) === value[1] ) { + tmpResult.push( items[i] ); + } + } + } + return tmpResult; + }; - var ViewClass = window.InfinniUI.viewModes.Label[viewMode]; + that.and = function(values, items, context) { + return _.intersection.apply(_, values); + }; - return new ViewClass({model: model}); - }, - - getDisplayValue: function () { - return this.controlView.getLabelText(); - } + that.or = function(values, items, context) { + return _.union.apply(_, values); + }; -}, editorBaseControlMixin); + that.not = function(values, items, context) { // values[0] is array + var tmpResult = items.slice(); + return _.difference(tmpResult, values[0]); + }; -//####app/controls/label/labelModel.js -var LabelModel = ControlModel.extend(_.extend({ + that.notEq = function(value, items, context) { + var tmpResult = [], + tmpResult2, + length, + globalUI = InfinniUI.ObjectUtils; - defaults: _.defaults({ - horizontalTextAlignment: 'Left', - verticalAlignment: 'Top', - textWrapping: true, - textTrimming: true, - escapeHtml: true, - focusable: false - }, ControlModel.prototype.defaults), + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + if( context ) { + tmpResult2 = []; + if( items[i][context] === undefined ) { + length = -1; + } else { + length = items[i][context].length; + } + for( var j = 0, jj = length; j < jj; j += 1 ) { + if( globalUI.getPropertyValue( items[i][context][j], value[0] ) !== value[1] ) { + tmpResult2.push( items[i] ); + } + } + if( length === tmpResult2.length ) { + tmpResult.push( items[i] ); + } + } else { + if( globalUI.getPropertyValue( items[i], value[0] ) !== value[1] ) { + tmpResult.push( items[i] ); + } + } + } + return tmpResult; + }; + // compare for numbers and dates + that.gt = function(value, items, context) { // value is array: value[0] - param, value[1] - value + var tmpResult = [], + tmpResult2, + length, + globalUI = InfinniUI.ObjectUtils; - initialize: function(){ - ControlModel.prototype.initialize.apply(this, arguments); - this.initialize_editorBaseModel(); - } -}, editorBaseModelMixin)); -//####app/controls/label/simpleView/labelView.js -/** - * @class SimpleLabelView - * @augments ControlView - * @mixes editorBaseViewMixin - */ -var SimpleLabelView = CommonLabelView.extend({ - tagName: 'span', + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + if( context ) { + tmpResult2 = []; + if( items[i][context] === undefined ) { + length = -1; + } else { + length = items[i][context].length; + } + for( var j = 0, jj = length; j < jj; j += 1 ) { + if( globalUI.getPropertyValue( items[i][context][j], value[0] ) > value[1] ) { + tmpResult2.push( items[i] ); + } + } + if( length === tmpResult2.length ) { + tmpResult.push( items[i] ); + } + } else { + if( globalUI.getPropertyValue( items[i], value[0] ) > value[1] ) { + tmpResult.push( items[i] ); + } + } + } + return tmpResult; + }; + // compare for numbers and dates + that.gte = function(value, items, context) { // value is array: value[0] - param, value[1] - value + var tmpResult = [], + tmpResult2, + length, + globalUI = InfinniUI.ObjectUtils; - template: function(){return '';}, - UI: _.extend({}, editorBaseViewMixin.UI, { + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + if( context ) { + tmpResult2 = []; + if( items[i][context] === undefined ) { + length = -1; + } else { + length = items[i][context].length; + } + for( var j = 0, jj = length; j < jj; j += 1 ) { + if( globalUI.getPropertyValue( items[i][context][j], value[0] ) >= value[1] ) { + tmpResult2.push( items[i] ); + } + } + if( length === tmpResult2.length ) { + tmpResult.push( items[i] ); + } + } else { + if( globalUI.getPropertyValue( items[i], value[0] ) >= value[1] ) { + tmpResult.push( items[i] ); + } + } + } + return tmpResult; + }; + // compare for numbers and dates + that.lt = function(value, items, context) { // value is array: value[0] - param, value[1] - value + var tmpResult = [], + tmpResult2, + length, + globalUI = InfinniUI.ObjectUtils; - }), + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + if( context ) { + tmpResult2 = []; + if( items[i][context] === undefined ) { + length = -1; + } else { + length = items[i][context].length; + } + for( var j = 0, jj = length; j < jj; j += 1 ) { + if( globalUI.getPropertyValue( items[i][context][j], value[0] ) < value[1] ) { + tmpResult2.push( items[i] ); + } + } + if( length === tmpResult2.length ) { + tmpResult.push( items[i] ); + } + } else { + if( globalUI.getPropertyValue( items[i], value[0] ) < value[1] ) { + tmpResult.push( items[i] ); + } + } + } + return tmpResult; + }; + // compare for numbers and dates + that.lte = function(value, items, context) { // value is array: value[0] - param, value[1] - value + var tmpResult = [], + tmpResult2, + length, + globalUI = InfinniUI.ObjectUtils; - updateFocusable: function () { - var focusable = this.model.get('focusable'); + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + if( context ) { + tmpResult2 = []; + if( items[i][context] === undefined ) { + length = -1; + } else { + length = items[i][context].length; + } + for( var j = 0, jj = length; j < jj; j += 1 ) { + if( globalUI.getPropertyValue( items[i][context][j], value[0] ) <= value[1] ) { + tmpResult2.push( items[i] ); + } + } + if( length === tmpResult2.length ) { + tmpResult.push( items[i] ); + } + } else { + if( globalUI.getPropertyValue( items[i], value[0] ) <= value[1] ) { + tmpResult.push( items[i] ); + } + } + } + return tmpResult; + }; - if (focusable) { - this.$el.attr('tabindex', 0); - } else { - this.$el.removeAttr('tabindex'); - } - }, + that.in = function(values, items, context) { // values[1] is array + var tmpResult = [], + tmpResult2, + length, + globalUI = InfinniUI.ObjectUtils; - getLabelElement: function(){ - return this.$el; - } + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + if( context ) { + tmpResult2 = []; + if( items[i][context] === undefined ) { + length = -1; + } else { + length = items[i][context].length; + } + for( var j = 0, jj = length; j < jj; j += 1 ) { + if( _.indexOf( values[1], globalUI.getPropertyValue( items[i][context][j], values[0] ) ) !== -1 ) { + tmpResult2.push( items[i] ); + } + } + if( length === tmpResult2.length ) { + tmpResult.push( items[i] ); + } + } else { + if( _.indexOf( values[1], globalUI.getPropertyValue( items[i], values[0] ) ) !== -1 ) { + tmpResult.push( items[i] ); + } + } + } + return tmpResult; + }; -}); + that.notIn = function(values, items, context) { // values[1] is array + var tmpResult = [], + tmpResult2, + length, + globalUI = InfinniUI.ObjectUtils; -InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.Label.simple', SimpleLabelView); -//####app/controls/listBox/baseView/listBoxView.js -var BaseListBoxView = ListEditorBaseView.extend({ + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + if( context ) { + tmpResult2 = []; + if( items[i][context] === undefined ) { + length = -1; + } else { + length = items[i][context].length; + } + for( var j = 0, jj = length; j < jj; j += 1 ) { + if( _.indexOf( values[1], globalUI.getPropertyValue( items[i][context][j], values[0] ) ) === -1 ) { + tmpResult2.push( items[i] ); + } + } + if( length === tmpResult2.length ) { + tmpResult.push( items[i] ); + } + } else { + if( _.indexOf( values[1], globalUI.getPropertyValue( items[i], values[0] ) ) === -1 ) { + tmpResult.push( items[i] ); + } + } + } + return tmpResult; + }; - template: { - plain: InfinniUI.Template["controls/listBox/baseView/template/listBox.tpl.html"], - grouped: InfinniUI.Template["controls/listBox/baseView/template/listBoxGrouped.tpl.html"] - }, + that.exists = function(value, items, context) { // value[1] is string + var tmpResult = [], + tmpValue, + globalUI = InfinniUI.ObjectUtils; + if( value[1] === undefined ) { + value[1] = true; + } + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpValue = globalUI.getPropertyValue( items[i], value[0] ); + if( value[1] === true ) { + if( !_.isUndefined(tmpValue) && !_.isNull(tmpValue) ) { + tmpResult.push( items[i] ); + } + } else { + if( _.isUndefined(tmpValue) || _.isNull(tmpValue) ) { + tmpResult.push( items[i] ); + } + } + } + return tmpResult; + }; - className: 'pl-listbox', + that.match = function(values, items, context) { + var tmpResult = [], + globalUI = InfinniUI.ObjectUtils; + for( var i = 0, ii = values[1].length; i < ii; i += 1 ) { + if( globalUI.getPropertyValue( values[1][i], values[0] ) !== undefined ) { + tmpResult.push( values[1][i] ); + } + } + return tmpResult; + }; - events: { - 'change .pl-listbox-input': 'onChangeHandler' - }, + that.all = function(values, items, context) { // value[1] is array + var tmpResult = [], + counter, + tmpArr, + globalUI = InfinniUI.ObjectUtils; - UI: _.defaults({ - items: '.pl-listbox-i', - checkingInputs: '.pl-listbox-input input' - }, ListEditorBaseView.prototype.UI), + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], values[0] ); + counter = 0; + for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { + if( _.indexOf( values[1], tmpArr[j] ) !== -1 ) { + counter += 1; + } + } + if( jj === counter ) { + tmpResult.push( items[i] ); + } + } + return tmpResult; + }; - initialize: function (options) { - //@TODO Реализовать обработку значений по умолчанию! - ListEditorBaseView.prototype.initialize.call(this, options); - }, + that.anyIn = function(values, items, context) { // value[1] is array + var tmpResult = [], + tmpArr, + globalUI = InfinniUI.ObjectUtils; - updateGrouping: function(){ - var isGrouped = this.model.get('groupValueSelector') != null; + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], values[0] ); + for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { + if( _.indexOf( values[1], tmpArr[j] ) !== -1 ) { + tmpResult.push( items[i] ); + break; + } + } + } + return tmpResult; + }; - if(isGrouped){ - this.strategy = new ListBoxViewGroupStrategy(this); - }else{ - this.strategy = new ListBoxViewPlainStrategy(this); - } - }, + that.anyNotIn = function(values, items, context) { // value[1] is array + var tmpResult = [], + counter, + tmpArr, + globalUI = InfinniUI.ObjectUtils; - updateValue: function(){ - this.ui.items.removeClass('pl-listbox-i-chosen'); - this.ui.checkingInputs.prop('checked', false); + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], values[0] ); + counter = 0; + for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { + if( _.indexOf( values[1], tmpArr[j] ) !== -1 ) { + counter += 1; + } + } + if( counter === 0 ) { + tmpResult.push( items[i] ); + } + } + return tmpResult; + }; - var value = this.model.get('value'), - choosingItem, $choosingItem; + that.anyEq = function(value, items, context) { + var tmpResult = [], + tmpArr, + globalUI = InfinniUI.ObjectUtils; - if(!this.isMultiselect() && value !== undefined && value !== null){ - value = [value]; - } + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], value[0] ); + if( _.indexOf(tmpArr, value[1]) !== -1 ) { + tmpResult.push( items[i] ); + } + } + return tmpResult; + }; - if($.isArray(value)){ - for(var i= 0, ii=value.length; i < ii; i++){ - choosingItem = this.model.itemByValue(value[i]); - $choosingItem = this._getElementByItem(choosingItem); + that.anyNotEq = function(value, items, context) { + var tmpResult = [], + tmpArr, + globalUI = InfinniUI.ObjectUtils; - if($choosingItem){ - $choosingItem.addClass('pl-listbox-i-chosen'); - $choosingItem.find('.pl-listbox-input input').prop('checked', true); - } - } - } - }, + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], value[0] ); + for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { + if( tmpArr[j] !== value[1] ) { + tmpResult.push( items[i] ); + break; + } + } + } + return tmpResult; + }; - updateSelectedItem: function(ignoreWasRendered){ - if(!this.wasRendered && ignoreWasRendered != true){ - return; - } + that.anyGt = function(value, items, context) { + var tmpResult = [], + tmpArr, + globalUI = InfinniUI.ObjectUtils; - this.ui.items.removeClass('pl-listbox-i-selected'); + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], value[0] ); + for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { + if( tmpArr[j] > value[1] ) { + tmpResult.push( items[i] ); + break; + } + } + } + return tmpResult; + }; - var selectedItem = this.model.get('selectedItem'), - $selectedItem = this._getElementByItem(selectedItem); + that.anyGte = function(value, items, context) { + var tmpResult = [], + tmpArr, + globalUI = InfinniUI.ObjectUtils; - if( $selectedItem && !$selectedItem.hasClass('pl-disabled-list-item') ) { - $selectedItem.addClass('pl-listbox-i-selected'); - } - }, + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], value[0] ); + for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { + if( tmpArr[j] >= value[1] ) { + tmpResult.push( items[i] ); + break; + } + } + } + return tmpResult; + }; - render: function () { - this.prerenderingActions(); + that.anyLt = function(value, items, context) { + var tmpResult = [], + tmpArr, + globalUI = InfinniUI.ObjectUtils; - var preparedItems = this.strategy.prepareItemsForRendering(); - var template = this.strategy.getTemplate(); + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], value[0] ); + for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { + if( tmpArr[j] < value[1] ) { + tmpResult.push( items[i] ); + break; + } + } + } + return tmpResult; + }; - this.removeChildElements(); + that.anyLte = function(value, items, context) { + var tmpResult = [], + tmpArr, + globalUI = InfinniUI.ObjectUtils; - this.$el.html(template(preparedItems)); - this.bindUIElements(); + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], value[0] ); + for( var j = 0, jj = tmpArr.length; j < jj; j += 1 ) { + if( tmpArr[j] <= value[1] ) { + tmpResult.push( items[i] ); + break; + } + } + } + return tmpResult; + }; - this.strategy.appendItemsContent(preparedItems); + that.sizeEq = function(value, items, context) { + var tmpResult = [], + tmpArr, + globalUI = InfinniUI.ObjectUtils; - this.updateProperties(); + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], value[0] ); + if( tmpArr.length === value[1] ) { + tmpResult.push( items[i] ); + } + } + return tmpResult; + }; - this.trigger('render'); + that.sizeNotEq = function(value, items, context) { + var tmpResult = [], + tmpArr, + globalUI = InfinniUI.ObjectUtils; - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], value[0] ); + if( tmpArr.length !== value[1] ) { + tmpResult.push( items[i] ); + } + } + return tmpResult; + }; - getItems: function(){ - return this.model.get('items'); - }, + that.sizeGt = function(value, items, context) { + var tmpResult = [], + tmpArr, + globalUI = InfinniUI.ObjectUtils; - getItemTemplate: function(){ - return this.model.get('itemTemplate'); - }, + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], value[0] ); + if( tmpArr.length > value[1] ) { + tmpResult.push( items[i] ); + } + } + return tmpResult; + }; - getGroupValueSelector: function(){ - return this.model.get('groupValueSelector'); - }, + that.sizeGte = function(value, items, context) { + var tmpResult = [], + tmpArr, + globalUI = InfinniUI.ObjectUtils; - isMultiselect: function(){ - return this.model.get('multiSelect'); - }, + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], value[0] ); + if( tmpArr.length >= value[1] ) { + tmpResult.push( items[i] ); + } + } + return tmpResult; + }; - isFocusable: function () { - return this.model.get('focusable'); - }, + that.sizeLt = function(value, items, context) { + var tmpResult = [], + tmpArr, + globalUI = InfinniUI.ObjectUtils; - getGroupItemTemplate: function(){ - return this.model.get('groupItemTemplate'); - }, + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], value[0] ); + if( tmpArr.length < value[1] ) { + tmpResult.push( items[i] ); + } + } + return tmpResult; + }; - onChangeHandler: function(){ - var $checked = this.ui.checkingInputs.filter(':checked').parent().parent(), - valueForModel = null, - model = this.model, - val; + that.sizeLte = function(value, items, context) { + var tmpResult = [], + tmpArr, + globalUI = InfinniUI.ObjectUtils; - if(this.isMultiselect()){ - valueForModel = []; + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpArr = globalUI.getPropertyValue( items[i], value[0] ); + if( tmpArr.length <= value[1] ) { + tmpResult.push( items[i] ); + } + } + return tmpResult; + }; - $checked.each(function(i, el){ - val = $(el).data('pl-data-item'); - valueForModel.push(model.valueByItem(val)); - }); + that.regexp = function(values, items, context) { // value[1] is array + var tmpResult = [], + tmpObjValue, + globalUI = InfinniUI.ObjectUtils, + flags = '', + regexp; + for( var j = 1, jj = values[1].length; j < jj; j += 1 ) { + flags += values[1][j]; + } + regexp = new RegExp(values[1][0], flags); + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpObjValue = globalUI.getPropertyValue( items[i], values[0] ); + if( tmpObjValue.search(regexp) !== -1 ) { + tmpResult.push( items[i] ); + } + } + return tmpResult; + }; - }else{ - if($checked.length > 0){ - valueForModel = model.valueByItem($checked.data('pl-data-item')); - } - } + that.text = function(value, items, context) { + var tmpResult = [], + tmpString, + subString = value[0].replace('_', ' ').toLowerCase(); + for( var i = 0, ii = items.length; i < ii; i += 1 ) { + tmpString = JSON.stringify(items[i]).toLowerCase(); + if( tmpString.indexOf( subString ) !== -1 ) { + tmpResult.push( items[i] ); + } + } + return tmpResult; + }; + return that; +})(); - this.model.set('value', valueForModel); - }, +//####app/utils/hashMap.js +/** + * @description Простая реализация хеша у которого в качестве ключей м.б. объект + * @constructor + */ +function HashMap() { + this._keys = []; + this._values = []; +} + +window.InfinniUI.HashMap = HashMap; + +Object.defineProperties(HashMap.prototype, /** @lends HashMap.prototype **/{ + length: { + get: function () { + return this._keys.length; + } + }, + keys: { + get: function () { + return this._keys; + } + }, + + values: { + get: function () { + return this._values; + } + } +}); + +HashMap.prototype.add = function (key, value) { + var i = this._getIndexOfKey(key); + + if (i === -1) { + this._keys.push(key); + this._values.push(value); + } else { + this._values[i] = value; + } +}; + +HashMap.prototype.remove = function (key) { + var i = this._getIndexOfKey(key); + + if (i !== -1) { + this._keys.splice(i, 1); + this._values.splice(i, 1); + } +}; + +HashMap.prototype.getKeyByValue = function (value) { + var key, + i = this._getIndexOfValue(value); + + if (i !== -1) { + key = this._keys[i]; + } + return key; +}; + +/** + * + * @param {Function} predicate + * @param thisArg + * @returns {numeric} + */ +HashMap.prototype.findIndex = function (predicate, thisArg) { + var key, value, index = -1; + for (var i = 0; i < this._keys.length; i = i + 1) { + key = this._keys[i]; + value = this._values[i]; + if (predicate.call(thisArg, key, value)) { + index = i; + break; + } + } + + return index; +}; + +HashMap.prototype.get = function (key) { + var value, + i = this._getIndexOfKey(key); + + if (i !== -1) { + value = this._values[i]; + } + + return value; +}; + +HashMap.prototype.forEach = function (callback, thisArg) { + this._keys.forEach(function (key, index) { + callback.call(thisArg, this._values[index], key, index); + }, this); +}; + +HashMap.prototype.clear = function (callback) { + if (typeof callback === 'function') { + this.forEach(callback); + } + this._keys.length = 0; + this._values.length = 0; +}; + +/** + * @param key + * @returns {number} + * @private + */ +HashMap.prototype._getIndexOfKey = function (key) { + return this._keys.indexOf(key); +}; + +/** + * @param {*} value + * @returns {number} + * @private + */ +HashMap.prototype._getIndexOfValue = function (value) { + return this._values.indexOf(value); +}; - updateDisabledItem: function(){ - var model = this.model, - disabledItemCondition = model.get('disabledItemCondition'); +//####app/utils/hiddenScreen.js +function hiddenScreen() { + this.middleElement = $('
').css({ + 'position': 'absolute', + top: '-10000px' + }); +} +hiddenScreen.prototype = { + add: function (element) { + $('body').prepend(this.middleElement); + this.middleElement.append(element); + } +}; - this.ui.items.removeClass('pl-disabled-list-item'); - this.ui.checkingInputs.attr('disabled', null); +window.InfinniUI.hiddenScreen = hiddenScreen; - if( disabledItemCondition != null ){ - this.ui.items.each(function (i, el) { - var $el = $(el), - item = $el.data('pl-data-item'), - isDisabled = disabledItemCondition( undefined, {value: item}); +//####app/utils/inheritance.js +_.mixin({ + 'inherit': function (child, parent) { + var f = new Function(); + f.prototype = parent.prototype; - if(isDisabled){ - if( $el.hasClass('pl-listbox-i-selected') ) { - this.model.set('selectedItem', null); - } - $el.toggleClass('pl-disabled-list-item', true); - $el.find('input').attr('disabled', 'disabled'); - $el.find('button').attr('disabled', 'disabled'); - } - }) - } - }, + child.prototype = new f(); + child.prototype.constructor = child; - disableAll: function() { - this.ui.items.addClass('pl-disabled-list-item'); + child.superclass = parent.prototype; }, - _getElementByItem: function(item){ - var element = _.find(this.ui.items, function(listboxItem){ - return $(listboxItem).data('pl-data-item') == item; - }); + 'superClass': function (obj, context, values) { + var args = _.toArray(arguments); + args.splice(0, 2); - return $(element); + obj.superclass.constructor.apply(context, args); } }); +//####app/utils/isEqual.js +(function () { + var isEqual = _.isEqual; + _.isEqual = function(a, b) { + if (typeof File !== 'undefined') { + if (a instanceof File || b instanceof File) { + return a === b; + } + } + return isEqual(a, b); + }; + +})(); -InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.ListBox.base', BaseListBoxView); - -//####app/controls/listBox/baseView/viewGroupStrategy.js -function ListBoxViewGroupStrategy(listbox) { - this.listbox = listbox; +//####app/utils/keycodes.js +window.InfinniUI.Keyboard = { + KeyCode: { + ESCAPE: 27, + HOME: 36, + LEFT_ARROW: 37, + RIGHT_ARROW: 39, + END: 35, + UP_ARROW: 38, + DOWN_ARROW: 40, + DELETE: 46, + BACKSPACE: 8, + TAB: 9, + SPACE: 32, + NUMPAD_0: 96, + NUMPAD_1: 97, + NUMPAD_2: 98, + NUMPAD_3: 99, + NUMPAD_4: 100, + NUMPAD_5: 101, + NUMPAD_6: 102, + NUMPAD_7: 103, + NUMPAD_8: 104, + NUMPAD_9: 105, + PLUS: 43, + MINUS: 45, + ASTERISK: 42, + SLASH: 47, + 0: 48, + 1: 49, + 2: 50, + 3: 51, + 4: 52, + 5: 53, + 6: 54, + 7: 55, + 8: 56, + 9: 57 + }, + + getCharByKeyCode: function (keyCode) { + var char, code; + + if (keyCode < 32) { + //Спецсимвол + char = null; + } else { + //@see http://unixpapa.com/js/key.html + if (keyCode >= this.KeyCode.NUMPAD_0 && keyCode <= this.KeyCode.NUMPAD_9) { + code = keyCode - 48; + } else { + switch (keyCode) { + //convert numpad key codes + case 110: + code = this.KeyCode.DELETE; //.Del + break; + case 107: + code = this.KeyCode.PLUS; //+ + break; + case 109: + code = this.KeyCode.MINUS; //- + break; + case 106: + code = this.KeyCode.ASTERISK; //* + break; + case 111: + code = this.KeyCode.SLASH; // / + break; + //Symbol Keys + case 188: + code = 44; + break; + case 173: + code = 45; + break; + case 190: + code = 46; + break; + case 191: + code = 47; + break; + case 192: + code = 96; + break; + case 219: + code = 91; + break; + case 220: + code = 92; + break; + case 221: + code = 93; + break; + case 222: + code = 39; + break; + default: + code = keyCode; + } + } + char = String.fromCharCode(code); + } + return char; + } }; +//####app/utils/layoutManager.js +var layoutManager = { + windowHeight: 0, + clientHeight: 0, + exchange: null, + times: [], -_.extend(ListBoxViewGroupStrategy.prototype, { + setOuterHeight: function ($el, height, fix) { + var delta = 0; + 'border-top-width,border-bottom-width,padding-top,padding-bottom,margin-top,margin-bottom' + .split(',') + .forEach(function(name) { + delta += parseInt($el.css(name)); + }); + var contentHeight = height - delta; + if (fix) { + contentHeight += fix; + } - prepareItemsForRendering: function(){ - var items = this.listbox.getItems(), - inputName = 'listbox-' + guid(), - result = { - isMultiselect: this.listbox.isMultiselect(), - focusable: this.listbox.isFocusable(), - inputName: inputName, - groups: [] - }, - groups = {}, - groupingFunction = this.listbox.getGroupValueSelector(); + //@TODO Разобраться с багом, при задании clearfix.height = 0 вылезает лишний 1 пиксел. Временное решение: + //contentHeight = (contentHeight > 0) ? contentHeight - 1 : contentHeight; - items.forEach(function(item, index){ - var groupKey = groupingFunction(undefined, {value:item}); + $el.height(contentHeight); - if(! (groupKey in groups)){ - groups[groupKey] = []; - } + return contentHeight; + }, - groups[groupKey].push({index: index, item: item}); - }); + getModalSelector: function () { + return '.modal-scrollable'; + }, - for(var k in groups){ - result.groups.push({ - items: groups[k] - }) - } + getSelector: function () { + //return '.pl-data-grid, .pl-scroll-panel, .pl-document-viewer, .pl-menu.vertical, .pl-tab-panel, .pl-treeview'; + return '.verticalAlignmentStretch:not(:hidden)'; + }, - return result; - }, + buildTree: function(items, parentEl, $parentEl, elements, list) { + var items = _.where(list, {parent: parentEl}), + manager = this; - getTemplate: function(){ - return this.listbox.template.grouped; - }, + return { + isElement: _.indexOf(elements, parentEl) !== -1, + element: parentEl, + $element: $parentEl, + child: _.map(items, function (item) { + return manager.buildTree(items, item.element, item.$element, elements, list ); + }) + }; + }, - appendItemsContent: function(preparedItems){ - var $listbox = this.listbox.$el, - itemTemplate = this.listbox.getItemTemplate(), - groupTitleTemplate = this.listbox.getGroupItemTemplate(), - groups = preparedItems.groups, - listbox = this.listbox, - item, itemEl, titleEl, $el, group; + formTree: function(elements, el, $el) { + var $parent, + list = [], + $element, + element; + //Строим дерево элементов: от концевых элементов поднимается к корневому элементу + for (var i = 0, ln = elements.length; i < ln; i = i + 1) { + element = elements[i]; + $element = $(element); + do { + $parent = $element.parent(); - $listbox.find('.pl-listbox-group-i').each(function(i, el){ + var a = _.findWhere(list, {element: element}); + if (typeof a !== 'undefined') { + //Элемент уже занесен в список + break; + } + list.push({ + element: element, + $element: $element, + parent: $parent.get(0), + $parent: $parent + }); - group = groups[i]; - titleEl = groupTitleTemplate(undefined, {index: group.items[0].index, item: group}); - listbox.addChildElement(titleEl); + $element = $parent; + element = $parent.get(0); + } while (element !== el); + } - $el = $(el); - $el.find(".pl-listbox-group-title").append(titleEl.render()); + return this.buildTree(list, el, $el, elements, list); + }, - $el.find(".pl-listbox-body").each(function(j, bodyEl){ - item = group.items[j].item; - itemEl = itemTemplate(undefined, {index: group.items[j].index, item: item}); + setHeight: function (node, height) { + var originalHeight = node.$element.attr('data-height-original'); + if (originalHeight === '') { + node.$element.attr('data-height-original', node.element.style.height); + } + return this.setOuterHeight(node.$element, height); + }, - listbox.addChildElement(itemEl); + defineWay: function(node, height) { + var nodeHeight = this.setHeight(node, height), + manager = this; - $(bodyEl).append(itemEl.render()); - $(bodyEl).parent() - .data('pl-data-item', item); - }); + if( node.$element.hasClass('pl-scroll-panel') || node.$element.hasClass('modal-scrollable') ) { + //Т.к. скроллпанель бесконечная по высоте, контролы внутри нее по высоте не растягиваем + return; + } else if( node.$element.hasClass('tab-content') ) { + _.each(node.child, function (node) { + manager.defineWay(node, nodeHeight); + }); + } else if( node.child.length > 0 ) { + this.goThroughTree(node, nodeHeight); + } + }, - }); - } -}); -//####app/controls/listBox/baseView/viewPlainStrategy.js -function ListBoxViewPlainStrategy(listbox) { - this.listbox = listbox; -}; + goThroughTree: function(node, height) { + var manager = this; + if( node.$element.parentsUntil('.modal').length ) { + node.$element.attr('data-height-original', node.element.style.height); + } -_.extend(ListBoxViewPlainStrategy.prototype, { + var children = node.$element.children(':not(:hidden):not(.modal-scrollable):not(.modal-backdrop):not(.pl-dropdown-container)'), + /* + * @TODO Возможно правильнее исключать из обсчета все элементы с абсолютным позиционированием + */ + grid = _.chain(children) + .filter(function (el) { + var position = $(el).css('position'); + return ['absolute', 'fixed'].indexOf(position) === -1; + }) + .groupBy('offsetTop') + .value(), - prepareItemsForRendering: function(){ - var items = this.listbox.getItems(), - inputName = 'listbox-' + guid(), - result = { - isMultiselect: this.listbox.isMultiselect(), - focusable: this.listbox.isFocusable(), - inputName: inputName, - items: items.toArray() - }; + heights = []; - return result; - }, + _.each(grid, function (row, i) { + var nodes = []; + _.each(row, function (e) { + var n = _.find(node.child, function (c) {return c.element === e;}); + if (n) nodes.push(n); + }); - getTemplate: function(){ - return this.listbox.template.plain; - }, + heights.push(nodes.length ? 0 : _.reduce(row, function (height, e) { + return Math.max(height, $(e).outerHeight(true)); + }, 0)); - appendItemsContent: function(preparedItems){ - var $listbox = this.listbox.$el, - itemTemplate = this.listbox.getItemTemplate(), - items = preparedItems.items, - listbox = this.listbox, - itemEl, $el; + grid[i] = nodes; + }, this); - $listbox.find('.pl-listbox-body').each(function(i, el){ - $el = $(el); - itemEl = itemTemplate(undefined, {index: i, item: items[i]}); - listbox.addChildElement(itemEl); - $el.append(itemEl.render()); + var fixedHeight = _.reduce(heights, function (total, height) {return total + height}, 0), + count = _.reduce(grid, function (count, row) {return row.length ? count + 1 : count}, 0), + + heightForNode = Math.floor((height - fixedHeight) / count); - $el.parent().data('pl-data-item', items[i]); - }); - } -}); -//####app/controls/listBox/listBoxControl.js -function ListBoxControl(viewMode) { - _.superClass(ListBoxControl, this, viewMode); -} + _.each(grid, function (row) { + if (row.length === 0) return; + _.each(row, function (node) { + manager.defineWay(node, heightForNode); + }, this); + }, this); + }, -_.inherit(ListBoxControl, ListEditorBaseControl); + resize: function(el, pageHeight) { + var startTime = Date.now(); //start time + var $el = $(el), + contentHeight = this.setOuterHeight($el, pageHeight), + elements = $el.find(this.getSelector()); -_.extend(ListBoxControl.prototype, { + //var elements = Array.prototype.filter.call($el.find(this.getSelector()), function (element) { + // //Исключаем элементы которые долдны занитмать всю доступную высоту, + // // которые по какой-то причине оказались внутри ScrollPanel + // return $(element).parents('.pl-scrollpanel').length === 0; + //}); + if (elements.length === 0) { + return; + } - createControlModel: function () { - return new ListBoxModel(); - }, + var tree = this.formTree(elements, el, $el); + /** + * Если внутри child один элемент: + * - устанавливаем высоту в 100% + * Если внутри child несколько элементов + * - offsetTop совпадают - устанавливаем высоту в 100% + * - offsetTop не совпадают - устанавливаем высоту в (100 / child.length)% + */ + this.defineWay(tree, pageHeight); + var endTime = Date.now(); //end time + this.timeWatcher(endTime - startTime); + }, - createControlView: function (model, viewMode) { - if(!viewMode || ! viewMode in window.InfinniUI.viewModes.ListBox){ - viewMode = 'common'; - } + timeWatcher: function(time) { + if( time >= 20 ) { + this.times.push(time); + } + }, - var ViewClass = window.InfinniUI.viewModes.ListBox[viewMode]; + getTimes: function() { + return this.times; + }, - return new ViewClass({model: model}); - }, + resizeView: function (container, clientHeight) { + var $page = $('#page-content', container); + //$page.height(clientHeight); + var contentHeight = this.setOuterHeight($page, clientHeight); + var that = this; - updateDisabledItem: function() { - this.controlView.updateDisabledItem(); - }, + this.resize($page.get(0), contentHeight); - disableAll: function() { - this.controlView.disableAll(); - } + //$page.children().each(function (i, el) { + // if (el.style.display !== 'none') { + // //Обработка активной вкладки + // var $tab = $(el); + // + // var $bar = $(".pl-active-bar:not(:hidden)", $tab); + // + // var barHeight = $bar.length ? $bar.outerHeight(true) : 0; + // //var barHeight = $(".pl-active-bar", $tab).outerHeight(true); + // $tab.children().each(function (i, el) { + // if (false === el.classList.contains('pl-active-bar') && el.style.display !== 'none') { + // var pageHeight = contentHeight - barHeight; + // that.resize(el, pageHeight); + // } + // }); + // } + //}); + }, -}); + resizeDialog: function () { + var $currentDialog = $(this.getModalSelector()).last(); + this._resizeDialog($currentDialog); + this.resetDialogHeight($currentDialog); + }, -//####app/controls/listBox/listBoxModel.js -var ListBoxModel = ListEditorBaseModel.extend({ - initialize: function () { - ListEditorBaseModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - } -}); -//####app/controls/listBox/checkingView/listBoxView.js -var CheckingListBoxView = BaseListBoxView.extend({ - className: 'pl-listbox', + resetDialogHeight: function($modal){ + var space = 10; - template: { - plain: InfinniUI.Template["controls/listBox/checkingView/template/listBox.tpl.html"], - grouped: InfinniUI.Template["controls/listBox/checkingView/template/listBoxGrouped.tpl.html"] - }, + if($modal.children()) { + var $container = $modal.children(); - events: _.extend( { + var $header = $('.modal-header', $container); + var $body = $('.modal-body', $container); - }, BaseListBoxView.prototype.events), + var $el = $(this.getSelector(), $modal); - initialize: function (options) { - BaseListBoxView.prototype.initialize.call(this, options); - this.initDomHandlers(); - }, + $el.parentsUntil('.modal').css('height', 'auto'); + $container.css('top', (this.windowHeight - $header.outerHeight(true) - $body.outerHeight(true)) / 2); - updateEnabled: function () { - ListEditorBaseView.prototype.updateEnabled.call(this); + $modal.children('.modal:not(.messagebox)').height($body.outerHeight(true) + $header.outerHeight(true)); - var enabled = this.model.get('enabled'); + } - this.ui.checkingInputs.attr('disabled', !enabled); - }, + //var $header = $('.modal-header', $container); + //var $body = $('.modal-body', $container); - initDomHandlers: function(){ - var $listBox = this.$el, - that = this; + //var headerHeight = $header.outerHeight(true); + // + //$container.css('margin-top', 0); + // + //var el = $(this.getSelector(), $modal); + //if (el.length === 0) { + // //Если диалог не содержит элементы которые должны растягиваться по вертикали на 100% + // //Выравниваем по вертикали в центр + // $container.css('top', (this.windowHeight - headerHeight - $body.outerHeight(true)) / 2); + // return; + //} + // + //$body.css('min-height', '0'); + //var containerHeight = this.setOuterHeight($modal, 'auto'); + // + ////Высота для содержимого окна диалога + //var clientHeight = this.setOuterHeight($container, containerHeight) - $header.outerHeight(); + // + //this.resize($body[0], clientHeight); + //$container.css('top', (this.windowHeight - headerHeight - clientHeight) / 2); + }, - $listBox.get(0).addEventListener('click', function(e){ - e = $.event.fix(e); - var $el = $(e.target), - $currentListItem, item, isDisabledItem; + _resizeDialog: function ($modal) { + var space = 10;//Высота отступа от вертикальных границ диалога до границ экрана - if (!that.model.get('enabled')) { - return; - } + var $container = $modal.children(); - while($el.get(0) != $listBox.get(0)){ - if($el.hasClass('pl-listbox-i')){ - $currentListItem = $el; - } + $container.css('margin-top', 0); + //var marginTop = parseInt($container.css('margin-top'), 10); - $el = $el.parent(); - } + var $header = $('.modal-header', $container); + var $body = $('.modal-body', $container); - if($currentListItem && $currentListItem.length > 0){ - item = $currentListItem.data('pl-data-item'); - isDisabledItem = that.model.isDisabledItem(item); + var headerHeight = $header.outerHeight(true); + $body.css('max-height', this.windowHeight - headerHeight); - if(!isDisabledItem) { - that.model.toggleValue(item); - } + $container.css('margin-top', 0); - that.model.set('selectedItem', item); - } + var el = $(this.getSelector(), $modal); + if (el.length !== 0) { + // Если диалог содержит элементы которые должны растягиваться по вертикали на 100% + // пересчитываем высоту - }, true); - } -}); + //@TODO Зачем задавалась минимальная высота диалогов? + //$body.css('min-height', (this.windowHeight - $header.outerHeight(true) - space * 2) / 2); + var containerHeight = this.setOuterHeight($modal, this.windowHeight - space * 2); -InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.ListBox.checking', CheckingListBoxView); -//####app/controls/listBox/commonView/listBoxView.js -var CommonListBoxView = BaseListBoxView.extend({ - className: 'pl-listbox pl-listbox-common-mode', + //Высота для содержимого окна диалога + var clientHeight = this.setOuterHeight($container, containerHeight) - $header.outerHeight(); - events: _.extend( { + this.resize($body[0], clientHeight); + } + }, - }, BaseListBoxView.prototype.events), + init: function (container) { + if( window.InfinniUI.config.disableLayoutManager === true ) { + return false; + } + container = container || document; + $('#page-content').addClass('page-content-overflow-hidden'); + this.windowHeight = $(window).height(); + this.onChangeLayout(container); + if (this.exchange === null) { + this.exchange = window.InfinniUI.global.messageBus; + this.exchange.subscribe('OnChangeLayout', _.debounce(this.onChangeLayout.bind(this), 42)); + } + }, - initialize: function (options) { - BaseListBoxView.prototype.initialize.call(this, options); - this.initDomHandlers(); - }, + onChangeLayout: function (container) { + if (_.isEmpty(container)) { + container = document; + } - initDomHandlers: function(){ - var $listBox = this.$el, - that = this; + var clientHeight = this.windowHeight + - $("#page-top:not(:hidden)", container).outerHeight() + - $("#page-bottom:not(:hidden)", container).outerHeight() + - $("#menu-area:not(:hidden)", container).outerHeight(); + this.resizeView(container, clientHeight); + this.resizeDialog(); + } +}; - $listBox.get(0).addEventListener('click', function(e){ - e = $.event.fix(e); - var $el = $(e.target), - $currentListItem, item, isDisabledItem; +window.InfinniUI.LayoutManager = layoutManager; - while($el.get(0) != $listBox.get(0)){ - if($el.hasClass('pl-listbox-i')){ - $currentListItem = $el; - } +//####app/utils/logger.js +var LOG_LEVEL = { + debug: 1, + info: 2, + warn: 3, + error: 4, + trace: 5 +} - $el = $el.parent(); - } +function Logger(level){ + this.messages = []; + this.setLevel(level || LOG_LEVEL.debug); - if($currentListItem.length > 0){ - item = $currentListItem.data('pl-data-item'); - isDisabledItem = that.model.isDisabledItem(item); - if(!isDisabledItem){ - that.model.toggleValue(item); - } + this.showMessages = true; +}; - that.model.set('selectedItem', item); - } +_.extend(Logger.prototype, { + getLevel: function(){ + return this.level; + }, - }, true); - } -}); + setLevel: function(level){ + this.level = level; + }, -InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.ListBox.common', CommonListBoxView); -//####app/controls/popupButton/commonView/popupButtonView.js -var CommonPopupButtonView = ContainerView.extend({ + addMessage: function(messageType, message){ + this.messages.push({ + type: messageType, + message: message + }); + }, - className: 'pl-popup-button', + debug: function(message){ + if(this.level > LOG_LEVEL.debug){ + return; + } - template: InfinniUI.Template["controls/popupButton/commonView/template/popupButton.tpl.html"], - dropdownTemplate: InfinniUI.Template["controls/popupButton/commonView/template/popupButton.dropdown.tpl.html"], + if(this.showMessages){ + console.debug(message.message || message); + } - events: { - 'click': 'onClickHandler' + this.addMessage(LOG_LEVEL.debug, message); }, - UI: { - button: '.pl-popup-button__button', - grip: '.pl-popup-button__grip' + info: function(message){ + if(this.level > LOG_LEVEL.info){ + return; + } + + if(this.showMessages){ + console.info(message.message || message); + } + + this.addMessage(LOG_LEVEL.info, message); }, - updateProperties: function(){ - ContainerView.prototype.updateProperties.call(this); + warn: function(message){ + if(this.level > LOG_LEVEL.warn){ + return; + } - this.updateContent(); + if(this.showMessages){ + console.warn(message.message || message); + } + + this.addMessage(LOG_LEVEL.warn, message); }, - updateContent: CommonButtonView.prototype.updateContent, - updateText: CommonButtonView.prototype.updateText, + error: function(message){ + if(this.level > LOG_LEVEL.error){ + return; + } - getButtonElement: function(){ - return this.ui.button; + if(this.showMessages){ + console.error(message.message || message); + } + + this.addMessage(LOG_LEVEL.error, message); }, - render: function () { - this.prerenderingActions(); + trace: function(message){ + if(this.level > LOG_LEVEL.trace){ + return; + } - var items = this.model.get('items').toArray(); - var template = this.template; + if(this.showMessages){ + console.error(message.message || message); + } - this.removeChildElements(); + this.addMessage(LOG_LEVEL.trace, message); + } +}) - this.$el.html(template({items: items})); - this.bindUIElements(); +window.InfinniUI.global.logger = new Logger(); +//####app/utils/metadata.js +InfinniUI.Metadata = InfinniUI.Metadata || {}; + +InfinniUI.Metadata.isValidValue = function (value, metadata) { + var result = false; + for (var i in metadata) { + if (metadata[i] === value) { + result = true; + break; + } + } + + return result; +}; + +InfinniUI.Metadata.isBindingMetadata = function(metadata){ + return $.isPlainObject(metadata) && 'Source' in metadata; +}; +//####app/utils/numeric.js +Number.isInteger = Number.isInteger || function(value) { + return typeof value === "number" && + isFinite(value) && + Math.floor(value) === value; +}; +//####app/utils/stringUtils.js +if (!String.prototype.includes) { + String.prototype.includes = function() { + return String.prototype.indexOf.apply(this, arguments) !== -1; + }; +} - this.$dropdown = this.renderDropdown(); +var stringUtils = { + format: function(value,args){ + return value.replace(/{(\d+)}/g, function (match, number) { + return typeof args[number] != 'undefined' + ? args[number] + : match + ; + }); + }, - this.$dropdown.on('click', this.close.bind(this)); + formatProperty: function(property, indexes){ + if(!indexes || indexes.length == 0 || property == ''){ + return property; + } - this.updateProperties(); + var propertyPaths = property.split('.'); - this.trigger('render'); + var j = indexes.length-1; - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; + for(var i = propertyPaths.length-1; i>=0; i--){ + if(propertyPaths[i] == '#' && j >= 0){ + propertyPaths[i] = indexes[j]; + j--; + }else if(propertyPaths[i] == '$' || stringUtils.isNumeric(propertyPaths[i])){ + j--; + } + } + + return propertyPaths.join('.'); }, - renderDropdown: function(){ - var template = this.dropdownTemplate; - var items = this.model.get('items').toArray(); - var $result = $(template({items: items})); + padLeft: function a (value, len, char) { + if (typeof char == 'undefined' || char === null) { + char = ' '; + } - this.appendItemsContent($result, items); + var str = String(value); - return $result; + if (str.length < len) { + return new Array(len - str.length + 1).join(char) + str; + } + return str; }, - appendItemsContent: function($dropdown, items){ - var that = this, - itemTemplate = this.model.get('itemTemplate'), - itemEl, $el; + isNumeric: function(n) { + return !isNaN(parseFloat(n)) && isFinite(n); + }, - $dropdown.find('.pl-popup-button__item').each(function(i, el){ - $el = $(el); - itemEl = itemTemplate(undefined, {index: i, item: items[i]}); - that.addChildElement(itemEl); - $el.append(itemEl.render()); - }); + replaced: { + '+': '%2B' }, - open: function(){ + joinDataForQuery: function(data){ + var result = []; var that = this; - $('body').append(this.$dropdown); + for(var k in data){ + var p = _.isString(data[k]) ? data[k].replace(/[\+]/g, function (c) { + return that.replaced[c] || c; + }) : data[k]; - this.$dropdown.addClass('open'); - this.alignDropdown(); + result.push(k + '=' + p); + } - var $ignoredElements = this.$dropdown.add (this.ui.grip); - }, + return result.join('&'); + } +}; - close: function(){ - this.$dropdown.removeClass('open'); - this.$dropdown.detach(); - }, +window.InfinniUI.StringUtils = stringUtils; +window.InfinniUI.guid = guid; - alignDropdown: function(){ - var offset = this.$el.offset(), - $elHeight = this.$el.height(), - $elWidth = this.$el.width(), - dropdownList = this.$dropdown.find('.pl-popup-button__items')[0], - $dropdownHeight = dropdownList.offsetHeight, - $dropdownWidth = dropdownList.offsetWidth, - left = offset.left, - top = offset.top + $elHeight; +function guid() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); +} - if( (offset.left + $dropdownWidth) >= window.innerWidth ) { - left += ($elWidth - $dropdownWidth); - } +//####app/utils/testMode.js +(function (window, document, $) { + 'use strict'; + + var DATA_NAME_ATTRIBUTE = 'data-pl-name'; + var DATA_NAME_VIEW_ATTRIBUTE = 'data-pl-name-view'; + var NO_NAME = 'No name'; + var DATA_NAME_SELECTOR = '[' + DATA_NAME_ATTRIBUTE + ']:first'; + var DATA_NAME_VIEW_SELECTOR = '[' + DATA_NAME_VIEW_ATTRIBUTE + ']:first'; + + var location = window.location; + if (location.hash !== '#test') { + return; + } + + $(function () { + + patchBootstrapTooltip(); + var info = new InfoElement(); + + $(document).on('mouseover', function (event) { + info.setElement(event.target); + }); + + function patchBootstrapTooltip() { + $.fn.tooltip.Constructor.prototype.getTitle = function () { + var $e = this.$element; + var o = this.options; + + return o.title; + } + } + }); + + + /*************************************/ + + function ClickManager() { + this._unsubscribe = []; + } + + ClickManager.prototype.append = function (element, handler) { + var EVENT_NAME = 'contextmenu'; + this.clear(); + + if (typeof element === 'undefined' || element === null) { + return; + } + element.addEventListener(EVENT_NAME, handler, true); + this._unsubscribe.push(function () { + element.removeEventListener(EVENT_NAME, handler, true); + }); + return this; + }; + + ClickManager.prototype.clear = function () { + this._unsubscribe.forEach(function (fn) { + fn.call(); + }); + return this; + }; + + function InfoElement() { + this.marker = new Marker(); + this.$currentControl = null; + this.clickManager = new ClickManager(); + } + + InfoElement.prototype.setElement = function (el) { + var + $el = $(el), + $control = getControl($el), + name = getName($control), + viewName = getViewName($control); + + this.hideInfo(); + if ($control) { + this.showInfo($control, viewName, _.isEmpty(name) ? NO_NAME : name); + } + + function getControl($el) { + var $control; + + var name = $el.attr(DATA_NAME_ATTRIBUTE); + if (typeof name !== 'undefined') { + $control = $el; + } else { + $control = $el.parents(DATA_NAME_SELECTOR); + } + return $control; + } + + function getName($el) { + if ($el.length) { + return $el.attr(DATA_NAME_ATTRIBUTE); + } + } + + function getViewName($el) { + var $e = $el.parents(DATA_NAME_VIEW_SELECTOR); + if ($e.length) { + return $e.attr(DATA_NAME_VIEW_ATTRIBUTE); + } + } + }; + + InfoElement.prototype.copyInfo = function (viewName, name) { + if (viewName || name) { + window.prompt("Copy to clipboard: Ctrl+C", formatInfo(viewName, name)); + } + }; + + InfoElement.prototype.showInfo = function ($control, viewName, name) { + if (this.$currentControl && this.$currentControl[0] !== $control[0]) { + this.marker.reset(this.$currentControl); + this.clickManager.clear(); + } + this.marker.highlight($control); + this.$currentControl = $control; + this.clickManager.append($control[0], this.copyInfo.bind(this, viewName, name)); + + $control.tooltip({ + title: formatInfo(viewName, name), + placement: "auto" + }) + .tooltip('show'); + }; + + InfoElement.prototype.hideInfo = function () { + this.clickManager.clear(); + if (this.$currentControl) { + this.marker + .reset(this.$currentControl); + this.$currentControl.tooltip('destroy'); + } + }; + + + /********************************************/ + + function Marker() { + this.DATA_NAME = 'data-pl-original-style'; + + this.css = { + 'box-shadow': 'inset 0 0 1em #ff0000' + }; + } + + Marker.prototype.highlight = function ($el) { + var data; + + if ($el) { + data = $el.data(this.DATA_NAME); + if (!data) { + data = Object.create(null); + for (var i in this.css) { + data[i] = $el.css(i); + } + $el.data(this.DATA_NAME, data); + } + $el.css(this.css); + } + return this; + }; + + Marker.prototype.reset = function ($el) { + var data; + if ($el) { + data = $el.data(this.DATA_NAME); + $el.data(this.DATA_NAME, null); + if (data) { + $el.css(data); + } + } + return this; + }; + + + /********************/ + + function formatInfo(viewName, name) { + var info = viewName ? [viewName] : []; + info.push(name); + + return info.join(':'); + }; + + +})(window, document, jQuery); + - if( (top + $dropdownHeight) >= window.innerHeight ) { - top -= ($elHeight + $dropdownHeight + 2); - } +//####app/utils/treeModel.js +var TreeModel = function(context, source, startTree){ + this.context = context; + this.source = source; + this.dataTree = startTree || {}; - this.$dropdown.offset({ - top: top, - left: left - }); + this.handlersTree = {}; + + this.mirroringFrom = null; + this.mirroringTo = null; +}; + +window.InfinniUI.TreeModel = TreeModel; + +_.extend(TreeModel.prototype, { + + counter: 1, + + getProperty: function(propertyName){ + if(this.mirroringFrom){ + propertyName = propertyName.replace(this.mirroringFrom, this.mirroringTo); + } + return InfinniUI.ObjectUtils.getPropertyValue(this.dataTree, propertyName) }, - toggle: function(){ - if(!this.$dropdown.hasClass('open')){ - this.open(); - }else{ - this.close(); + setProperty: function(propertyName, value){ + var oldValue = this.getProperty(propertyName); + if(value == oldValue){ + return false; } - }, - onClickHandler: function(){ - this.toggle(); - }, + InfinniUI.ObjectUtils.setPropertyValue(this.dataTree, propertyName, value); - updateGrouping: function(){} + this._notifyAboutPropertyChanged(propertyName, oldValue); -}); + return true; + }, -InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.PopupButton.common', CommonPopupButtonView); + onPropertyChanged: function(propertyName, handler, params){ + var handlersNode; + var bindId = this.counter + '-bindId'; + this.counter ++; -//####app/controls/popupButton/popupButtonControl.js -function PopupButtonControl(viewMode) { - _.superClass(PopupButtonControl, this, viewMode); -} + if(_.isFunction(propertyName)){ + params = handler; + handler = propertyName; -_.inherit(PopupButtonControl, ContainerControl); + handlersNode = this._getHandlersSubTree('*', true); + }else{ + handlersNode = this._getHandlersSubTree(propertyName, true); + } -_.extend(PopupButtonControl.prototype, /** @lends PopupButtonControl.prototype */ { + handler._bindId = bindId; + if(params && 'owner' in params){ + handler._owner = params.owner; + } - createControlModel: function () { - return new PopupButtonModel(); + handlersNode[bindId] = handler; }, - createControlView: function (model, viewMode) { - if(!viewMode || ! viewMode in window.InfinniUI.viewModes.PopupButton){ - viewMode = 'common'; + _getHandlersSubTree: function(propertyName, restoreIfNoProperty){ + if(propertyName == ''){ + return this.handlersTree; } - var ViewClass = window.InfinniUI.viewModes.PopupButton[viewMode]; - - return new ViewClass({model: model}); - } + var propertyPaths = propertyName.split('.'); + var tmpResult = this.handlersTree; + for(var i = 0, ii = propertyPaths.length; i 0; - }, + checkAndCallAnyHandlers(handlersNode); + + if(propertyName != ''){ + for(var i = 0, ii = propertyNamePaths.length; i < ii; i++){ + + tmpPropertyName = propertyNamePaths[i]; + if(handlersNode[tmpPropertyName]){ + handlersNode = handlersNode[tmpPropertyName]; + checkAndCallAnyHandlers(handlersNode); - function(){ - if(horizontalAlignment == 'Right'){ - $el - .addClass('pull-right'); }else{ - $el - .removeClass('pull-right'); + break; } } - ); + } - }, - getButtonElement: function(){ - return this.ui.button; + + function checkAndCallAnyHandlers(_handlersNode){ + var handler; + + if('*' in _handlersNode){ + for( var k in _handlersNode['*'] ){ + handler = _handlersNode['*'][k]; + if(that._isOwnerAlive(handler)){ + that._callHandlerAboutPropertyChanged(handler, propertyName, oldValue); + }else{ + delete _handlersNode['*'][k]; + } + } + } + } }, - render: function () { - this.prerenderingActions(); + _isOwnerAlive: function(handler){ + if(handler._owner && 'isRemoved' in handler._owner){ - var items = this.model.get('items').toArray(); - var template = this.template; + if(typeof handler._owner.isRemoved == 'function'){ + return handler._owner.isRemoved(); + }else{ + return !handler._owner.isRemoved; + } - this.removeChildElements(); + }else{ + return true; + } + }, - this.$el.html(template({items: items})); - this.bindUIElements(); + _callHandlerAboutPropertyChanged: function(handler, propertyName, oldValue){ + var args = { + property: propertyName, + newValue: this.getProperty(propertyName), + oldValue: oldValue, + source: this.source + }; - this.$dropdown = this.renderDropdown(); + handler(this.context, args); + }, - this.updateProperties(); + setMirroring: function(mirroringFrom, mirroringTo){ + this.mirroringFrom = mirroringFrom; + this.mirroringTo = mirroringTo; + } - this.trigger('render'); +}); - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, +//####app/utils/urlManager.js +var urlManager = { + getParams: function(){ + var getPath = location.search, + result = {}, + params, tmpParam; - renderDropdown: function(){ - var template = this.dropdownTemplate; - var items = this.model.get('items').toArray(); - var $result = $(template({items: items})); + if(getPath.length == 0){ + return result; + } - this.appendItemsContent($result, items); - $result.on('click', function () { - this.close(); - }.bind(this)); - return $result; - }, + getPath = getPath.substr(1); + params = getPath.split('&'); - appendItemsContent: function($dropdown, items){ - var that = this, - itemTemplate = this.model.get('itemTemplate'), - itemEl, $el; + for(var i= 0, ii = params.length; i 0){ + index = location.href.indexOf(searchPath); + if(index > 0){ + newUrl = location.href.substr(0, index); + } + } + + if(newUrl){ + history.pushState(null, null, newUrl); + } + + }, - this.$dropdown.addClass('open'); - $parent.addClass('open'); + setParameter: function(name, value){ + var oldSearch = location.search; + var newSearch = _.isEmpty(oldSearch) ? + stringUtils.format("?{0}={1}", [name, value]) : + stringUtils.format("{0}&{1}={2}", [oldSearch, name, value]); - this.alignDropdown(); + var newUrl = stringUtils.format("{0}//{1}{2}{3}{4}",[location.protocol, location.host, location.pathname, newSearch, location.hash]); - var $ignoredElements = this.$dropdown.add (this.$el); - new ActionOnLoseFocus($ignoredElements, function(){ - that.close(); - }); + history.pushState(null, null, newUrl); }, - close: function(){ - this.$dropdown.removeClass('open'); - this.$el.parent().removeClass('open'); - this.$dropdown.detach(); - }, + deleteParameter: function(name){ + var params = urlManager.getParams(); + delete params[name]; - alignDropdown: function(){ - var horizontalAlignment = this.model.get('horizontalAlignment'); - var $el = this.$el.parent(); - var offset = $el.offset(); - var top = offset.top + $el.height()- 2; - var $dropdownMenu = this.$dropdown.find('.dropdown-menu'); - var left; + var newSearch = generateSearch(params); - if(horizontalAlignment == "Right"){ - left = offset.left - ($dropdownMenu.width() - $el.width()); - }else{ - left = offset.left; - } + var newUrl = stringUtils.format("{0}//{1}{2}{3}{4}",[location.protocol, location.host, location.pathname, newSearch, location.hash]); + history.pushState(null, null, newUrl); - this.$dropdown.offset({ - top: top, - left: left - }); - }, + function generateSearch(params){ + var paramsArray = []; + _.mapObject(params, function(val, key){ + var param = stringUtils.format("{0}={1}",[key, val]); + paramsArray.push( param ); + }); - onClickGripHandler: function(){ - this.toggle(); - }, + return _.isEmpty(paramsArray) ? + "" : + "?" + paramsArray.join("&"); + }; + } +}; - updateGrouping: function(){}, +window.InfinniUI.UrlManager = urlManager; +//####app/messaging/messageBus.js +function MessageBus(view) { + var subscriptions = {}; - whenReady: function(conditionFunction, onConditionFunction, n){ - var that = this; + this.send = function (messageType, messageBody) { + messageType = patchMessageType(messageType); + if (subscriptions[messageType]) { + var context; + if (view && view.getContext) { + context = view.getContext(); + } + _.each(subscriptions[messageType], function (handler) { + handler(context, { value: messageBody }); + }); + } + }; - if(n === undefined){ - n = 100; + this.subscribe = function (messageType, messageHandler) { + messageType = patchMessageType(messageType); + if (!subscriptions[messageType]) { + subscriptions[messageType] = []; } + + subscriptions[messageType].push(messageHandler); + }; - if(!conditionFunction()){ - if(n>0){ - setTimeout( function(){ - that.whenReady(conditionFunction, onConditionFunction, n-1); - }, 10); - } - }else{ - onConditionFunction(); + this.unsubscribeByType = function (messageType) { + messageType = patchMessageType(messageType); + if (subscriptions[messageType]) { + delete subscriptions[messageType]; } - } + }; -}); + this.getView = function () { + return view; + }; -InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.PopupButton.forMenu', ForMenuPopupButtonView); + function patchMessageType(messageType) { -//####app/controls/stackPanel/stackPanelControl.js -/** - * - * @param parent - * @constructor - * @augments ContainerControl - */ -function StackPanelControl(viewMode) { - _.superClass(StackPanelControl, this, viewMode); + if (typeof messageType === 'object' && typeof messageType.name !== 'undefined') { + messageType = messageType.name; + } + + return messageType; + } } -_.inherit(StackPanelControl, ContainerControl); +window.InfinniUI.global.messageBus = new MessageBus(); +//####app/messaging/messageTypes.js +window.messageTypes = { -_.extend(StackPanelControl.prototype, - /** @lends StackPanelControl.prototype */ - { - createControlModel: function () { - return new StackPanelModel(); - }, + onViewBuildError: {name: 'onViewBuildError'}, + onViewCreated: {name: 'onViewCreated'}, - createControlView: function (model, viewMode) { - var view = new StackPanelView({model: model}); + onChangeLayout: {name: 'OnChangeLayout'}, + onNotifyUser: {name: 'onNotifyUser'}, + onToolTip: {name: 'onToolTip'}, + onRemove: {name: 'onRemove'}, - view.viewMode = viewMode; + onContextMenu: {name: 'onContextMenu'}, + onOpenContextMenu: {name: 'onOpenContextMenu'}, - return view; - } - } -); + onDataLoading: {name: 'onDataLoading'}, + onDataLoaded: {name: 'onDataLoaded'}, + onToolTipDestroy: {name: 'onToolTipDestroy'}, + onToolTipInit: {name: 'onToolTipInit'} -//####app/controls/stackPanel/stackPanelModel.js -/** - * @constructor - * @augments ContainerModel - */ -var StackPanelModel = ContainerModel.extend( - /** @lends StackPanelModel.prototype */ - { - initialize: function () { - ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - } - } -); -//####app/controls/stackPanel/baseView/stackPanelView.js -/** - * @class - * @augments ControlView - */ -var StackPanelView = ContainerView.extend( - /** @lends StackPanelView.prototype */ - { - tagName: 'ul', - className: 'pl-stack-panel pl-clearfix', +}; - template: { - plain: InfinniUI.Template["controls/stackPanel/baseView/template/stackPanel.tpl.html"], - grouped: InfinniUI.Template["controls/stackPanel/baseView/template/stackPanelGrouped.tpl.html"] - }, - UI: { - items: '.stackpanel-items' - }, +//####app/controls/_base/_mixins/ajaxRequestMixin.js +var ajaxRequestMixin = (function (bus) { + + function invokeCallback(cb, args) { + var result; + if (typeof cb === 'function') { + result = cb.apply(null, Array.prototype.slice.call(args)); + } + return result; + } + + return { + + onBeforeRequest: function (callback) { + return function () { + bus.send(messageTypes.onDataLoading, {}); + return invokeCallback(callback, arguments); + } + }, + + onSuccessRequest: function (callback) { + return function () { + bus.send(messageTypes.onDataLoaded, {success: true}); + return invokeCallback(callback, arguments); + } + }, + + onErrorRequest: function (callback) { + return function () { + bus.send(messageTypes.onDataLoaded, {success: false}); + return invokeCallback(callback, arguments); + } + } + } + +})(window.InfinniUI.global.messageBus); +//####app/controls/_base/_mixins/bindUIElementsMixin.js +var bindUIElementsMixin = { + /** + * Сохраняет в поле ui элементы по селектору в UI + * + * UI: {"name1": "selector1", "name2": "selector2"} + */ + bindUIElements: function () { + this.ui = {}; - initialize: function (options) { - ContainerView.prototype.initialize.call(this, options); + if (typeof this.UI === 'undefined') { + return; + } - this.initOrientation(); - }, + for (var i in this.UI) { + if (!this.UI.hasOwnProperty(i)) continue; - updateGrouping: function(){ - var isGrouped = this.model.get('groupValueSelector') != null; + this.ui[i] = this.$(this.UI[i]); + } + } +}; +//####app/controls/_base/_mixins/eventHandlerMixin.js +var eventHandlerMixin = { - if(isGrouped){ - this.strategy = new StackPanelViewGroupStrategy(this); - }else{ - this.strategy = new StackPanelViewPlainStrategy(this); - } - }, + /** + * + * @param {String} name + * @callback handler + * @returns {boolean} + */ + addEventHandler: function (name, handler) { - render: function () { - this.prerenderingActions(); + this.initEventHandlerMixin(); - this.removeChildElements(); + if (name === null || typeof name === 'undefined') { + return false; + } - var preparedItems = this.strategy.prepareItemsForRendering(); - var template = this.strategy.getTemplate(); + if (handler === null || typeof handler === 'undefined') { + return false; + } - this.$el.html(template(preparedItems)); + if (typeof this.eventHandlers[name] === 'undefined') { + this.eventHandlers[name] = []; + } - this.strategy.appendItemsContent(preparedItems); + var handlers = this.eventHandlers[name]; - this.bindUIElements(); - this.updateProperties(); + if (handlers.indexOf(handler) === -1) { + handlers.push(handler); + } + }, - this.trigger('render'); - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, + /** + * @description Вызывает обработчики указанного события. + * Формат вызова callEventHandler(name, [data],[handler]) + * @param {string} name Название события + * @param {Array} [data] Параметры, которые будут переданы в обработчик + * @callback [callback] Функцию в которую будут переданы результат вызова каждого обработчика + */ + callEventHandler: function (name) { + if (typeof this.eventHandlers === 'undefined' || name === null || typeof name === 'undefined') { + return; + } + var handlers = this.eventHandlers[name]; - initOrientation: function () { - this.listenTo(this.model, 'change:orientation', this.updateOrientation); - this.updateOrientation(); - }, + if (typeof handlers === 'undefined') { + return; + } - updateOrientation: function () { - var orientation = this.model.get('orientation'); - this.$el.toggleClass('horizontal-orientation', orientation == 'Horizontal'); - this.$el.toggleClass('pl-stack-panel_horizontal', orientation == 'Horizontal'); - }, + var args = Array.prototype.slice.call(arguments, 1); - getItems: function(){ - return this.model.get('items'); - }, + var params = args.pop(); + var callback; - getItemTemplate: function(){ - return this.model.get('itemTemplate'); - }, + if (typeof params === 'function') { + callback = params; + } + params = args.pop(); - getGroupValueSelector: function(){ - return this.model.get('groupValueSelector'); - }, + _.each(handlers, function (handler) { + var result = handler.apply(undefined, params); + if (typeof callback !== 'undefined') { + callback(result); + } + }); + }, - getGroupItemTemplate: function(){ - return this.model.get('groupItemTemplate'); - }, + /** + * @private + */ + initEventHandlerMixin: function () { + if (typeof this.eventHandlers === 'undefined') { + this.eventHandlers = {}; + } } -); -//####app/controls/stackPanel/baseView/viewGroupStrategy.js -function StackPanelViewGroupStrategy(stackPanel) { - this.stackPanel = stackPanel; -} -_.extend(StackPanelViewGroupStrategy.prototype, { +}; +//####app/controls/_base/control/control.js +/** + * @description Базовый класс контролов + * @class Control + */ +var Control = function (viewMode) { + this.controlModel = this.createControlModel(); + this.controlView = this.createControlView(this.controlModel, viewMode); - groupTemplate: InfinniUI.Template["controls/stackPanel/baseView/template/stackPanelGroup.tpl.html"], + this.initHandlers(); - prepareItemsForRendering: function(){ - var items = this.stackPanel.getItems(), - inputName = 'listbox-' + guid(), - result = { - inputName: inputName, - groups: [] - }, - groups = {}, - groupingFunction = this.stackPanel.getGroupValueSelector(); +}; - items.forEach(function(item, index){ - var groupKey = groupingFunction(undefined, {value:item}); +_.extend(Control.prototype, { - if(! (groupKey in groups)){ - groups[groupKey] = []; - } + createControlModel: function () { + throw ('Не перегружен абстрактный метод Control.createControlModel()'); + }, - groups[groupKey].push(item); - }); + createControlView: function (model, viewMode) { + throw ('Не перегружен абстрактный метод Control.createControlView()'); + }, - for(var k in groups){ - if (!groups.hasOwnProperty(k)) { - continue; - } - result.groups.push({ - items: groups[k], - indices: groups[k].map(function (item) { - return items.indexOf(item); - }) - }); - } + initHandlers: function () { + this.controlView.on('onLoaded', function () { + this.controlModel.set('isLoaded', true); + }, this); + }, - return result; + set: function (key, value) { + this.controlModel.set(key, value); }, - getTemplate: function(){ - return this.stackPanel.template.grouped; + get: function (key) { + return this.controlModel.get(key); }, - /** - * - * @param {Object} preparedItems - * @param {Array} preparedItems.groups - */ - appendItemsContent: function (preparedItems) { - var - stackPanel = this.stackPanel, - $stackPanel = stackPanel.$el, - groupTemplate = this.groupTemplate, - groupHeaderTemplate = this.stackPanel.getGroupItemTemplate(), - itemTemplate = this.stackPanel.getItemTemplate(), - $groups, - groups = preparedItems.groups; + on: function (name, handler) { + return this.controlModel.on(name, handler); + }, - $groups = groups.map(function (group, groupIndex) { + render: function () { + return this.controlView.render().$el; + }, - var $items, - items = group.items || [], - indices = group.indices || [], - $group = $(groupTemplate({items: items})), - groupHeader = groupHeaderTemplate(null, { - index: indices[0], //Индекс любого элемента в этой группе - item: group - }); + getChildElements: function () { + return []; + }, - stackPanel.addChildElement(groupHeader); + onLoaded: function (handler) { + this.controlModel.on('change:isLoaded', function (isLoaded) { + if (isLoaded) { + handler(); + } + }); + }, - $items = items.map(function (item, itemIndex) { - var element = itemTemplate(null, {index: indices[itemIndex], item: item}); - stackPanel.addChildElement(element); - return element.render(); - }); + isLoaded: function () { + return this.controlModel.get('isLoaded'); + }, - $('.pl-stack-panel-group__header', $group).append(groupHeader.render()); + onBeforeClick: function (handler) { + this.controlView.on('beforeClick', handler); + }, - $('.pl-stack-panel-list__item', $group).each(function (i, el) { - $(el).append($items[i]); - }); + onClick: function (handler) { + this.controlView.$el.on('click', handler); + }, - return $group; + onDoubleClick: function (handler) { + this.controlView.$el.on('dblclick', handler); + }, - }); + onMouseDown: function (handler) { + this.controlView.$el.on('mousedown', handler); + }, - $stackPanel.append($groups); - } -}); -//####app/controls/stackPanel/baseView/viewPlainStrategy.js -function StackPanelViewPlainStrategy(stackPanel) { - this.stackPanel = stackPanel; -}; + onMouseUp: function (handler) { + this.controlView.$el.on('mouseup', handler); + }, -_.extend(StackPanelViewPlainStrategy.prototype, { + onMouseEnter: function (handler) { + this.controlView.$el.on('mouseenter', handler); + }, - prepareItemsForRendering: function(){ - var items = this.stackPanel.getItems(), - result = { - items: items.toArray() - }; + onMouseLeave: function (handler) { + this.controlView.$el.on('mouseleave', handler); + }, - return result; + onMouseMove: function (handler) { + this.controlView.$el.on('mousemove', handler); }, - getTemplate: function(){ - return this.stackPanel.template.plain; + onMouseWheel: function (handler) { + this.controlView.$el.on('mousewheel DOMMouseScroll', handler); }, - appendItemsContent: function(preparedItems, childElementsClass){ - var $stackPanel = this.stackPanel.$el, - itemTemplate = this.stackPanel.getItemTemplate(), - items = preparedItems.items, - stackPanel = this.stackPanel, - itemEl, $el; + onKeyDown: function (handler) { + this.controlView.$el.on('keydown', handler); + }, - childElementsClass = childElementsClass || '.pl-stack-panel-i'; + onKeyUp: function (handler) { + this.controlView.$el.on('keyup', handler); + }, - $stackPanel.find(childElementsClass).each(function(i, el){ - $el = $(el); - itemEl = itemTemplate(undefined, {index: i, item: items[i]}); - stackPanel.addChildElement(itemEl); - $el.append(itemEl.render()); + onRemove: function( handler ) { + this.controlView.on(messageTypes.onRemove.name, handler); + }, - $el.parent().data('pl-data-item', items[i]); - }); + remove: function () { + this.controlView.remove(); + }, + + setFocus: function () { + this.controlView.setFocus(); } }); -//####app/controls/tablePanel/tablePanelControl.js -/** - * - * @param parent - * @constructor - * @augments ContainerControl - */ -function TablePanelControl(parent) { - _.superClass(TablePanelControl, this, parent); -} - -_.inherit(TablePanelControl, ContainerControl); +InfinniUI.Control = Control; +//####app/controls/_base/control/controlModel.js +var ControlModel = Backbone.Model.extend({ + defaults: { + text: null, + name: null, + enabled: true, + parentEnabled: true, + visible: true, + textHorizontalAlignment: InfinniUI.TextHorizontalAlignment.left, + horizontalAlignment: 'Stretch', + verticalAlignment: 'Top', + textStyle: null, + background: null, + foreground: null, + isLoaded: false, + validationState: 'success', + validationMessage: '', + focusable: true, + focused: false + }, + + initialize: function(){ + this.set('guid', guid(), {silent: true}); + this.on('change:focused', function (model, value) { + this.trigger(value ? 'OnGotFocus' : 'OnLostFocus'); + }); + }, + + set: function (key, val, options) { + var + defaults = this.defaults, + attrs; + + if (key == null) return this; + if (typeof key === 'object') { + attrs = key; + options = val; + } else { + (attrs = {})[key] = val; + } + + for (var name in attrs) { + if (typeof attrs[name] !== 'undefined' && attrs[name] !== null) { + continue; + } + + if (name in defaults) { + attrs[name] = defaults[name]; + } + } + return Backbone.Model.prototype.set.call(this, attrs, options); + } + +}); + +InfinniUI.ControlModel = ControlModel; +//####app/controls/_base/control/controlView.js +/** + * @class + * @augments Backbone.View + */ +var ControlView = Backbone.View.extend(/** @lends ControlView.prototype */{ + + initialize: function () { + this.wasRendered = false; + this.once('render', this.initHandlersForProperties, this); + this._initDomHandlers(); + + }, + + classNameFocused: 'pl-focused', + + _initDomHandlers: function () { + var + view = this, + $el = this.$el; + + $el[0].addEventListener('click', function (event) { + view.trigger('beforeClick', null, {value: event}); + }, true); + }, + + initHandlersForProperties: function () { + this.listenTo(this.model, 'change:visible', this.updateVisible); + this.listenTo(this.model, 'change:horizontalAlignment', this.updateHorizontalAlignment); + this.listenTo(this.model, 'change:textHorizontalAlignment', this.updateTextHorizontalAlignment); + this.listenTo(this.model, 'change:verticalAlignment', this.updateVerticalAlignment); + this.listenTo(this.model, 'change:enabled', this.updateEnabled); + this.listenTo(this.model, 'change:name', this.updateName); + this.listenTo(this.model, 'change:style', this.updateStyle); + this.listenTo(this.model, 'change:text', this.updateText); + + this.listenTo(this.model, 'change:textStyle', this.updateTextStyle); + this.listenTo(this.model, 'change:background', this.updateBackground); + this.listenTo(this.model, 'change:foreground', this.updateForeground); + + this.listenTo(this.model, 'change:validationState', this.updateValidationState); + + + this.listenTo(this.model, 'change:focusable', this.updateFocusable); + this.listenTo(this.model, 'change:focused', this.updateFocused); + + this.initFocusHandlers(); + }, + + initFocusHandlers: function () { + var $el = this.$el, + el = this.el, + view = this, + model = this.model; + + + $el + .on('focusin', onFocusIn) + .on('focusout', onFocusOut); + + function onFocusIn(event) { + model.set('focused', true); + } + + function onFocusOut(event) { + if (view.isControlElement(event.relatedTarget)) { + //focus out to element inside control + model.set('focused', true); + } else { + //focus out + model.set('focused', false); + } + } + }, + + isControlElement: function (el) { + return this.el === el || $.contains(this.el, el) + }, + + updateProperties: function () { + this.updateVisible(); + this.updateTextHorizontalAlignment(); + this.updateHorizontalAlignment(); + this.updateVerticalAlignment(); + this.updateEnabled(); + this.updateName(); + this.updateText(); + this.updateStyle(); + + this.updateTextStyle(); + this.updateBackground(); + this.updateForeground(); + + this.updateValidationState(); + + this.updateFocusable(); + this.updateFocused(); + + this.updateViewMode(); + }, + + /** + * @description Изменяет контрол в соответсвии со значением focusable. Напр. добавить tabindex="0" + */ + updateFocusable: function () { + + }, + + /** + * @description Возвращает элемент, который должен получить фокус + */ + getElementForFocus: function () { + return this.$el; + }, + + updateFocused: function () { + var focused = this.model.get('focused'); + + if (focused) { + var $el = this.getElementForFocus(); + if ($el && $el.length) { + //$el.focus(); + } + } + this.$el.toggleClass(this.classNameFocused, focused); + }, + + + onFocusHandler: function (event) { + //console.log('onFocus'); + }, + + + updateVisible: function () { + var isVisible = this.model.get('visible'); + this.$el + .toggleClass('hidden', !isVisible); + + this.onUpdateVisible(); + }, + + onUpdateVisible: function () { + this.updateLayout(); + }, + + updateLayout: function () { + var exchange = window.InfinniUI.global.messageBus; + exchange.send('OnChangeLayout', {}); + }, + + updateEnabled: function () { + var isEnabled = this.model.get('enabled'); + this.$el + .toggleClass('pl-disabled', !isEnabled); + }, + + updateVerticalAlignment: function () { + //var verticalAlignment = this.model.get('verticalAlignment'); + this.switchClass('verticalAlignment', this.model.get('verticalAlignment'), this.$el, false); + + //var prefix = 'verticalAlignment'; + //var regexp = new RegExp('(^|\\s)' + prefix + '\\S+', 'ig'); + // + //this.$el.removeClass(function (i, name) { + // return (name.match(regexp) || []).join(' '); + // }) + // .addClass(prefix + verticalAlignment); + }, + + updateTextHorizontalAlignment: function () { + this.switchClass('pl-text-horizontal', this.model.get('textHorizontalAlignment')); + }, + + updateHorizontalAlignment: function () { + this.switchClass('pl-horizontal', this.model.get('horizontalAlignment')); + }, + + updateName: function () { + var newName = this.model.get('name'), + currentName = this.$el.attr('data-pl-name'); + if (newName != currentName && typeof newName == 'string') { + this.$el.attr('data-pl-name', newName); + } + }, + + updateText: function () { + + }, + + updateTextStyle: function () { + var customStyle = this.model.get('textStyle'); + + if (this.currentTextStyle) { + this.$el + .removeClass(this.valueToTextClassName(this.currentTextStyle)); + } + + if (customStyle) { + this.$el + .addClass(this.valueToTextClassName(customStyle)); + } + + this.currentTextStyle = customStyle; + }, + + updateBackground: function () { + var customStyle = this.model.get('background'); + + if (this.currentBackground) { + this.$el + .removeClass(this.valueToBackgroundClassName(this.currentBackground)); + } + + if (customStyle) { + this.$el + .addClass(this.valueToBackgroundClassName(customStyle)); + } + + this.currentBackground = customStyle; + }, + + updateForeground: function () { + var customStyle = this.model.get('foreground'); + + if (this.currentForeground) { + this.$el + .removeClass(this.valueToForegroundClassName(this.currentForeground)); + } + + if (customStyle) { + this.$el + .addClass(this.valueToForegroundClassName(customStyle)); + } + + this.currentForeground = customStyle; + }, + + updateStyle: function () { + var customStyle = this.model.get('style'); + + if (this.currentStyle) { + this.$el + .removeClass(this.currentStyle); + } + + if (customStyle) { + this.$el + .addClass(customStyle); + } + + this.currentStyle = customStyle; + }, + + updateViewMode: function () { + if(this.viewMode == 'FormGroup' ){ + this.$el.addClass('pl-form-group'); + } + }, + + updateValidationState: function () { + var newState = this.model.get('validationState'), + message = this.model.get('validationMessage'); + switch (newState) { + + case 'success': + { + this.$el + .removeClass('has-warning has-error'); + this.hideErrorMessage(); + } + break; + + case 'warning': + { + this.$el + .removeClass('has-error') + .addClass('has-warning'); + this.showErrorMessage(message); + } + break; + + case 'error': + { + this.$el + .removeClass('has-warning') + .addClass('has-error'); + this.showErrorMessage(message); + } + break; + + } + + }, + + showErrorMessage: function (message) { + var $errorIcn = $(_.template('')({message: message})); + + this.hideErrorMessage(); + this.$el.find('.form-control:first') + .before($errorIcn); + + $errorIcn.tooltip({'container': 'body'}); + }, + + hideErrorMessage: function () { + this.$el.find('.error-icn') + .remove(); + }, + + rerender: function () { + if (this.wasRendered) { + this.render(); + } + }, + + prerenderingActions: function () { + this.wasRendered = true; + }, + + /** + * + * @param {Boolean} [onLoaded=true] + */ + postrenderingActions: function (triggeringOnLoaded) { + this.delegateEvents(); + + triggeringOnLoaded = triggeringOnLoaded === undefined ? true : triggeringOnLoaded; + + if (triggeringOnLoaded) { + this.trigger('onLoaded'); + } + }, + + remove: function () { + this.trigger(messageTypes.onRemove.name); + Backbone.View.prototype.remove.apply(this, Array.prototype.slice.call(arguments)); + }, + + switchClass: function (name, value, $el, separator) { + if (typeof separator === 'undefined') { + separator = '-'; + } else if (separator === false) { + separator = ''; + } + + var startWith = name + separator; + var regexp = new RegExp('(^|\\s)' + startWith + '\\S+', 'ig'); + var $element = $el || this.$el; + $element.removeClass(function (i, name) { + return (name.match(regexp) || []).join(' '); + }) + .addClass(startWith + value); + }, + + valueToBackgroundClassName: function (value) { + return 'pl-' + value.toLowerCase() + '-bg'; + }, + + valueToForegroundClassName: function (value) { + return 'pl-' + value.toLowerCase() + '-fg'; + }, + + valueToTextClassName: function (value) { + return 'pl-' + value.toLowerCase(); + }, + + renderTemplate: function (template) { + var data = this.getData(); + this.$el.html(template(data)); + this.bindUIElements(); + }, + + getData: function () { + var model = this.model; + return { + name: model.get('name'), + text: model.get('text'), + focusable: model.get('focusable'), + focused: model.get('focused'), + enabled: model.get('enabled'), + visible: model.get('visible'), + horizontalAlignment: model.get('horizontalAlignment'), + verticalAlignment: model.get('verticalAlignment'), + textHorizontalAlignment: model.get('textHorizontalAlignment'), + textVerticalAlignment: model.get('textVerticalAlignment'), + textStyle: model.get('textStyle'), + foreground: model.get('foreground'), + background: model.get('background') + } + }, + + setFocus: function () { + this.$el.focus(); + } + +}); + +_.extend(ControlView.prototype, bindUIElementsMixin, eventHandlerMixin); + +InfinniUI.ControlView = ControlView; -_.extend(TablePanelControl.prototype, - /** @lends TablePanelControl.prototype */ - { - createControlModel: function () { - return new TablePanelModel(); - }, +//####app/controls/_base/button/buttonControlMixin.js +var buttonControlMixin = { - createControlView: function (model) { - return new TablePanelView({model: model}); - } + click: function () { + this.controlView.$el.click(); } -); +}; +//####app/controls/_base/container/containerControl.js +/** + * + * @param parent + * @constructor + * @augments Control + */ +function ContainerControl(viewMode) { + _.superClass(ContainerControl, this, viewMode); +} + +_.inherit(ContainerControl, Control); -//####app/controls/tablePanel/tablePanelModel.js +_.extend(ContainerControl.prototype, {}); +//####app/controls/_base/container/containerModel.js /** * @constructor - * @augments ContainerModel + * @augments ControlModel */ -var TablePanelModel = ContainerModel.extend( - /** @lends TablePanelModel.prototype */ +var ContainerModel = ControlModel.extend( + + /** @lends ContainerModel.prototype */ { + defaults: _.defaults({ + //items: new Collection() + itemTemplate: null + }, ControlModel.prototype.defaults), + initialize: function () { - ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + ControlModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + this.set('items', new Collection()); } } ); -//####app/controls/tablePanel/tablePanelView.js + + + + +//####app/controls/_base/container/containerView.js /** * @class * @augments ControlView */ -var TablePanelView = ContainerView.extend( - /** @lends TablePanelView.prototype */ +var ContainerView = ControlView.extend( + /** @lends ContainerView.prototype */ { - className: 'pl-table-panel', - initialize: function (options) { - ContainerView.prototype.initialize.call(this, options); - }, - - render: function () { - this.prerenderingActions(); + ControlView.prototype.initialize.call(this, options); - this.removeChildElements(); + this.childElements = []; - this.renderItemsContents(); - this.updateProperties(); - this.trigger('render'); + this.listenTo(this.model, 'change:groupValueSelector', this.updateGrouping); + this.updateGrouping(); + }, - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; + updateGrouping: function(){ + throw 'ContainerView.updateGrouping В потомке ContainerView не реализовано обновление группировок.'; }, - renderItemsContents: function(){ - var items = this.model.get('items'), - itemTemplate = this.model.get('itemTemplate'), - that = this, - element, item; + initHandlersForProperties: function(){ + ControlView.prototype.initHandlersForProperties.call(this); - items.forEach(function(item, i){ - element = itemTemplate(undefined, {item: item, index: i}); - that.addChildElement(element); - that.$el - .append(element.render()); + var that = this; + this.model.get('items').onChange(function(event){ + switch (event.action) { + case 'replace': + break; + default: + that.rerender(); + } }); }, - updateGrouping: function(){} - } -); - -//####app/controls/tablePanel/cell/cellControl.js -/** - * - * @param parent - * @constructor - * @augments ContainerControl - */ -function CellControl(parent) { - _.superClass(CellControl, this, parent); -} - -_.inherit(CellControl, ContainerControl); + removeChildElements: function(){ + for(var i = 0, ii = this.childElements.length; i < ii; i++){ + this.childElements[i].remove(); + } -_.extend(CellControl.prototype, - /** @lends CellControl.prototype */ - { - createControlModel: function () { - return new CellModel(); + this.childElements = []; }, - createControlView: function (model) { - return new CellView({model: model}); + addChildElement: function(child){ + this.childElements.push(child); } } ); +//####app/controls/_base/editorBase/editorBaseControlMixin.js +var editorBaseControlMixin = { + initialize_editorBaseControl: function(){ -//####app/controls/tablePanel/cell/cellModel.js -/** - * @constructor - * @augments ContainerModel - */ -var CellModel = ContainerModel.extend( - /** @lends CellModel.prototype */ - { - defaults: _.defaults({ - columnSpan: 1 - }, ContainerModel.prototype.defaults), + }, - initialize: function () { - ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - } + setValue: function (value) { + this.controlModel.set('value', value); + }, + + getValue: function () { + return this.controlModel.get('value'); + }, + + onValueChanging: function (handler) { + this.controlModel.onValueChanging(handler); + }, + + onValueChanged: function (handler) { + this.controlModel.onValueChanged(handler); } -); -//####app/controls/tablePanel/cell/cellView.js -/** - * @class - * @augments ControlView - */ -var CellView = ContainerView.extend( - /** @lends CellView.prototype */ - { - className: 'pl-cell', +}; +//####app/controls/_base/editorBase/editorBaseModelMixin.js +var editorBaseModelMixin = { - initialize: function (options) { - ContainerView.prototype.initialize.call(this, options); + defaults_editorBaseModel: { + value: null, + hintText: null, + errorText: null, + warningText: null, + labelFloating: false + }, - this.initColumnSpan(); - }, + initialize_editorBaseModel: function(){ + this.eventManager = new EventManager(); + this.isInited = true; + }, - render: function () { - this.prerenderingActions(); + transformValue: function (value) { + return value; + }, - this.removeChildElements(); + _applyDefaultValue: function (value) { + var defaults = _.result(this, 'defaults'); + return typeof value === 'undefined' ? defaults['value'] : value; + }, - this.renderItemsContents(); + _setValue: function(value, options) { + value = this.transformValue(value); - this.updateProperties(); - this.trigger('render'); + value = this._applyDefaultValue(value); - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop + var + oldValue = this.get('value'), + message = { + oldValue: oldValue, + newValue: value + }; + + if (value === oldValue) { + return; + } + + if(this.isInited){ + if (this.eventManager.trigger('onValueChanging', message)) { + ContainerModel.prototype.set.call(this, 'value', value, options || {}); + this.trigger('onValueChanged', message); + } + }else{ + ContainerModel.prototype.set.call(this, 'value', value, options || {}); + } + + }, + + set: function (key, value, options) { + var attributes, options; + if (key === null) { return this; - }, + } - renderItemsContents: function(){ - var items = this.model.get('items'), - itemTemplate = this.model.get('itemTemplate'), - that = this, - element, item; + if (typeof key === 'object') { + attributes = key; + options = value; + } else { + (attributes = {})[key] = value; + } - items.forEach(function(item, i){ - element = itemTemplate(undefined, {item: item, index: i}); - that.addChildElement(element); - that.$el - .append(element.render()); - }); - }, + options = options || {}; - initColumnSpan: function () { - this.listenTo(this.model, 'change:columnSpan', this.updateColumnSpan); - this.updateColumnSpan(); - }, + if ('value' in attributes) { + this._setValue(attributes.value, options); + delete attributes.value; + } - updateColumnSpan: function () { - var columnSpan = this.model.get('columnSpan'), - currentColumnSpan = this.columnSpan; + var hasAttributes = false; - if(columnSpan != currentColumnSpan){ + for (var i in attributes) { + hasAttributes = true; + break; + } + + if (hasAttributes) { + return ContainerModel.prototype.set.call(this, attributes, options); + } - if(currentColumnSpan){ - this.$el - .removeClass('col-xs-' + currentColumnSpan); - } + return false; + }, - this.$el - .addClass('col-xs-' + columnSpan); + getValue: function () { + return this.get('value'); + }, - this.columnSpan = columnSpan; - } + isSetValue: function (value) { + return value !== null && typeof value !== 'undefined' && value !== ''; + }, - }, + onValueChanging: function (handler) { + this.eventManager.on('onValueChanging', handler); + }, - updateGrouping: function(){} + onValueChanged: function (handler) { + this.on('onValueChanged', handler); } -); +}; -//####app/controls/tablePanel/row/rowControl.js -/** - * - * @param parent - * @constructor - * @augments ContainerControl - */ -function RowControl(parent) { - _.superClass(RowControl, this, parent); +//####app/controls/_base/editorBase/editorBaseViewMixin.js +var editorBaseViewMixin = { + UI: { + hintText: '.pl-control-hint-text', + warningText: '.pl-control-warning-text', + errorText: '.pl-control-error-text' + }, + + getData: function () { + var model = this.model; + + return { + guid: model.get('guid') + } + }, + + initHandlersForProperties: function(){ + this.listenTo(this.model, 'onValueChanged', this.updateValue); + this.listenTo(this.model, 'change:hintText', this.updateHintText); + this.listenTo(this.model, 'change:errorText', this.updateErrorText); + this.listenTo(this.model, 'change:warningText', this.updateWarningText); + }, + + updateProperties: function(){ + this.updateValue(); + this.updateLabelFloating(); + this.updateHintText(); + this.updateErrorText(); + this.updateWarningText(); + }, + + + updateValue: function(){ + throw 'editorBaseViewMixin.updateValue В потомке editorBaseViewMixin не реализовано обновление данных.'; + }, + + updateValueState: function(){ + var value = this.model.get('value'); + var isEmpty = _.isEmpty(value) && !(_.isNumber(value)); + this.$el.toggleClass("pl-empty-text-editor", isEmpty); + }, + + updateLabelFloating: function () { + var labelFloating = this.model.get('labelFloating'); + this.$el.toggleClass("pl-label-floating", labelFloating === true); + }, + + updateHintText: function(){ + var hintText = this.model.get('hintText'); + if(hintText){ + this.ui.hintText + .text(hintText) + .removeClass('hidden'); + }else{ + this.ui.hintText + .text('') + .addClass('hidden'); + } + + }, + + updateErrorText: function(){ + var errorText = this.model.get('errorText'); + if(errorText){ + this.ui.errorText + .text(errorText) + .removeClass('hidden'); + }else{ + this.ui.errorText + .text('') + .addClass('hidden'); + } + + }, + + updateWarningText: function(){ + var warningText = this.model.get('warningText'); + if(warningText){ + this.ui.warningText + .text(warningText) + .removeClass('hidden'); + }else{ + this.ui.warningText + .text('') + .addClass('hidden'); + } + + }, + + updateEnabled: function () { + ControlView.prototype.updateEnabled.call(this); + + if(this.ui.control){ + var isEnabled = this.model.get('enabled'); + this.ui.control.prop('disabled', !isEnabled); + } + + }, + + onInvalidHandler: function (model, error) { + // что ита??? + // вот ето - @see {@link http://backbonejs.org/#Model-validate} !!! + + + //@TODO Можно ли использовать поля из API или реализовывать вывод ошибок отдельно? + //this.model.set('errorText', error); + } +}; + +//####app/controls/_base/listEditorBase/listEditorBaseControl.js +function ListEditorBaseControl(viewMode) { + _.superClass(ListEditorBaseControl, this, viewMode); + this.initialize_editorBaseControl(); } -_.inherit(RowControl, ContainerControl); +_.inherit(ListEditorBaseControl, ContainerControl); -_.extend(RowControl.prototype, - /** @lends RowControl.prototype */ - { - createControlModel: function () { - return new RowModel(); - }, +_.extend(ListEditorBaseControl.prototype, { - createControlView: function (model) { - return new RowView({model: model}); - } + onSelectedItemChanged: function (handler) { + this.controlModel.onSelectedItemChanged(handler); } -); - +}, editorBaseControlMixin); +//####app/controls/_base/listEditorBase/listEditorBaseModel.js +var ListEditorBaseModel = ContainerModel.extend( _.extend({ -//####app/controls/tablePanel/row/rowModel.js -/** - * @constructor - * @augments ContainerModel - */ -var RowModel = ContainerModel.extend( - /** @lends RowModel.prototype */ - { - initialize: function () { - ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - } - } -); -//####app/controls/tablePanel/row/rowView.js -/** - * @class - * @augments ControlView - */ -var RowView = ContainerView.extend( - /** @lends RowView.prototype */ - { - className: 'pl-row row', + defaults: _.defaults({ + multiSelect: false, + disabledItemCondition: null + }, ContainerModel.prototype.defaults), - initialize: function (options) { - ContainerView.prototype.initialize.call(this, options); - }, + initialize: function () { + var that = this; + this.hashValueByItem = new HashMap(); + ContainerModel.prototype.initialize.apply(this, arguments); + this.initialize_editorBaseModel(); - render: function () { - this.prerenderingActions(); + this.bindSelectedItemsWithValue(); - this.removeChildElements(); + this.get('items').onChange(function(){ + that.hashValueByItem.clear(); + }); + }, - this.renderItemsContents(); + onSelectedItemChanged: function (handler) { + this.on('change:selectedItem', function(source, newSelectedItem){ + handler({value: newSelectedItem}); + }); + }, - this.updateProperties(); - this.trigger('render'); + toggleValue: function (value, toggle) { + var + currentValue = this.get('value'), + multiSelect = this.get('multiSelect'), + index, clonedValue; - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, + if(multiSelect){ + currentValue = Array.isArray(currentValue) ? currentValue : []; - renderItemsContents: function(){ - var items = this.model.get('items'), - itemTemplate = this.model.get('itemTemplate'), - that = this, - element, item; + var valueAsString = JSON.stringify(value); - items.forEach(function(item, i){ - element = itemTemplate(undefined, {item: item, index: i}); - that.addChildElement(element); - that.$el - .append(element.render()); + var newValue = currentValue.filter(function(val) { + return JSON.stringify(val) !== valueAsString; }); - }, - - updateGrouping: function(){} - } -); - -//####app/controls/tabPanel/tabPanelControl.js -/** - * - * @param parent - * @constructor - * @augments ContainerControl - */ -function TabPanelControl(parent) { - _.superClass(TabPanelControl, this, parent); -} - -_.inherit(TabPanelControl, ContainerControl); -_.extend(TabPanelControl.prototype, /** @lends TabPanelControl.prototype */ { + if (typeof toggle === 'undefined' || toggle === true) { + if (newValue.length === currentValue.length) { + newValue.push(value); + } + } - setSelectedItem: function (value) { - /** - * @TODO Отрефакторить! Временное решение т.к. коллекция model.items содержит не экземпляры страниц а метаданные! см. templating в Container - */ - var - selectedItem = null, - model = this.controlModel, - elements = this.controlView.childElements, - items = model.get('items'); + this.set('value', newValue); - if (value instanceof TabPage) { - model.set('selectedItem', value) - } else if (Array.isArray(elements)) { - var index = items.indexOf(value); - if (index !== -1) { - selectedItem = elements[index]; + }else{ + if(value != currentValue){ + this.set('value', value); } - this.controlModel.set('selectedItem', selectedItem); } }, - createControlModel: function () { - return new TabPanelModel(); + bindSelectedItemsWithValue: function(){ + return; + //this.on('change:selectedItem', function (model, newSelectedItem) { + // var value = this.get('value'), + // newItemValue = this.valueByItem(newSelectedItem); + // + // if(!this.get('multiSelect') && !this.isStringifyEqualValues(newItemValue, value)){ + // this.set('value', newItemValue); + // } + //}, this); + // + //this.on('change:value', function (model, newValue) { + // var selectedItem = this.get('selectedItem'), + // newSelectedItem = this.itemByValue(newValue); + // + // if(!this.get('multiSelect') && selectedItem != newSelectedItem){ + // this.set('selectedItem', newSelectedItem); + // } + //}, this); }, - createControlView: function (model) { - return new TabPanelView({model: model}); - } - -}); - + valueByItem: function(item){ + var valueSelector = this.get('valueSelector'); + if(!valueSelector){ + return item; + }else{ + return valueSelector(undefined, {value: item}); + } + }, -//####app/controls/tabPanel/tabPanelModel.js -/** - * @constructor - * @augments ContainerModel - */ -var TabPanelModel = ContainerModel.extend(/** @lends TabPanelModel.prototype */ { + itemInfoByValue: function(value){ + if (this.hashValueByItem.length === 0) { + this.updateHashValueByItem(); + } + var info, + index, + item = this.hashValueByItem.getKeyByValue(value); - initialize: function () { - ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - }, + if (typeof item !== 'undefined') { + info = { + item: item, + index: this.hashValueByItem.keys.indexOf(item) + } + } else { + var text = JSON.stringify(value); + index = this.hashValueByItem.findIndex(function (item, value) { + return JSON.stringify(value) === text; + }); - defaults: _.defaults( - { - headerLocation: InfinniUI.TabHeaderLocation.top, - headerOrientation: InfinniUI.TabHeaderOrientation.horizontal - }, - ContainerModel.prototype.defaults - ) + if (index !== -1) { + info = { + index: index, + item: this.hashValueByItem.keys[index] + } + } + } -}); -//####app/controls/tabPanel/tabPanelView.js -/** - * @class - * @augments ControlView - */ -var TabPanelView = ContainerView.extend(/** @lends TabPanelView.prototype */ { + return info; + }, - className: 'pl-tabpanel', + itemByValue: function(value){ + var itemInfo = this.itemInfoByValue(value); - template: { - top: InfinniUI.Template["controls/tabPanel/template/tabPanel.top.tpl.html"], - right: InfinniUI.Template["controls/tabPanel/template/tabPanel.right.tpl.html"], - bottom: InfinniUI.Template["controls/tabPanel/template/tabPanel.bottom.tpl.html"], - left: InfinniUI.Template["controls/tabPanel/template/tabPanel.left.tpl.html"], - none: InfinniUI.Template["controls/tabPanel/template/tabPanel.none.tpl.html"] + if(!itemInfo){ + return undefined; + }else{ + return itemInfo.item; + } }, - UI: { - header: '.pl-tabpanel-header', - content: '.pl-tabpanel-content' + itemIndexByValue: function(value){ + var itemInfo = this.itemInfoByValue(value); + + if(!itemInfo){ + return -1; + }else{ + return itemInfo.index; + } }, - initHandlersForProperties: function () { - ContainerView.prototype.initHandlersForProperties.call(this); - this.listenTo(this.model, 'change:headerLocation', this.onChangeHeaderLocation); - this.listenTo(this.model, 'change:headerOrientation', this.updateHeaderOrientation); - this.listenTo(this.model, 'change:selectedItem', this.updateSelectedItem); + itemIndexByItem: function(item){ + var value = this.valueByItem(item); + return this.itemIndexByValue(value); }, - render: function () { - this.prerenderingActions(); + isDisabledItem: function(item){ + var disabledItemCondition = this.get('disabledItemCondition'); + return (disabledItemCondition != null) && disabledItemCondition(undefined, {value: item}); + }, - this.renderTemplate(this.getTemplate()); + updateHashValueByItem: function () { + var items = this.get('items'), + value; + this.hashValueByItem.clear(); + items.forEach(function (item) { + value = this.valueByItem(item); + this.hashValueByItem.add(item, value); + }, this); + } - this.renderItemsContents(); - this.checkSelectedItem(); +}, editorBaseModelMixin)); - this.postrenderingActions(); +//####app/controls/_base/listEditorBase/listEditorBaseView.js +var ListEditorBaseView = ContainerView.extend( _.extend( {}, editorBaseViewMixin, { - this.trigger('render'); - this.updateProperties(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; + initHandlersForProperties: function(){ + ContainerView.prototype.initHandlersForProperties.call(this); + editorBaseViewMixin.initHandlersForProperties.call(this); + + this.listenTo(this.model, 'change:selectedItem', this.updateSelectedItem); + this.listenTo(this.model, 'change:multiSelect', this.updateMultiSelect); + this.listenTo(this.model, 'change:disabledItemCondition', this.updateDisabledItem); }, - /** - * @protected - */ - renderItemsContents: function () { - var items = this.model.get('items'); + updateProperties: function(){ + ContainerView.prototype.updateProperties.call(this); + editorBaseViewMixin.updateProperties.call(this); - this.removeChildElements(); - this.ui.content.empty(); - this.model.set('selectedItemIndex', -1); + this.updateSelectedItem(); + this.updateMultiSelect(); + this.updateDisabledItem(); + }, - var data = []; - items.forEach(function (item, index) { - data.push({ - tabElement: this.renderTabContent(item, index), - item: item, - index: index - }); - }, this); + updateMultiSelect: function () { - this.renderTabHeaders(data); - }, + } - /** - * @protected - * @param {Array.} data - */ - renderTabHeaders: function (data) { - var header, - model = this.model, - items = model.get('items'), - selectedItem = model.get('selectedItem'); +})); +//####app/controls/_base/textEditorBase/textEditorBaseControl.js +/** + * + * @param parent + * @constructor + * @augments Control + * @mixes editorBaseControlMixin + */ +function TextEditorBaseControl(parent) { + _.superClass(TextEditorBaseControl, this, parent); + this.initialize_editorBaseControl(); +} - if (Array.isArray(this.tabHeaders)) { - while (header = this.tabHeaders.pop()) { - this.stopListening(header); - header.remove(); - } - } +_.inherit(TextEditorBaseControl, Control); - this.tabHeaders = data.map(function (data) { - var selected = items.indexOf(data.item) !== -1; - var header = this.renderTabHeader(data.tabElement, selected); +_.extend(TextEditorBaseControl.prototype, editorBaseControlMixin); +//####app/controls/_base/textEditorBase/textEditorBaseModel.js +/** + * @class + * @augments ControlModel + * @mixes editorBaseModelMixin + */ +var TextEditorBaseModel = ControlModel.extend(/** @lends TextEditorBaseModel.prototype */ { + defaults: _.defaults({ + labelText: null, + displayFormat: null, + editMask: null + }, + editorBaseModelMixin.defaults_editorBaseModel, + ControlModel.prototype.defaults), - this.listenTo(header, 'selected', function () { - model.set('selectedItem', data.tabElement); - }); + initialize: function () { + ControlModel.prototype.initialize.apply(this, arguments); + this.initialize_editorBaseModel(); + } +}); - this.listenTo(header, 'close', function () { - data.tabElement.close(); - }); +_.extend(TextEditorBaseModel.prototype, editorBaseModelMixin); - return header; - }, this); - }, +//####app/controls/_base/textEditorBase/textEditorBaseView.js +/** + * @class TextEditorBaseView + * @augments ControlView + * @mixed editorBaseViewMixin + */ + + +var TextEditorBaseView = ControlView.extend(/** @lends TextEditorBaseView.prototype */ _.extend({}, editorBaseViewMixin, { + + UI: _.extend({}, editorBaseViewMixin.UI, { + control: '.pl-control', + //editor: '.pl-control-editor', + editor: '.pl-editor', + label: '.pl-control-label', + textbox: '.pl-text-box-input' + }), + + events: { + + }, + + initialize: function () { + ControlView.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + }, + + initHandlersForProperties: function(){ + ControlView.prototype.initHandlersForProperties.call(this); + editorBaseViewMixin.initHandlersForProperties.call(this); + + this.listenTo(this.model, 'change:labelText', this.updateLabelText); + this.listenTo(this.model, 'change:labelFloating', this.updateLabelFloating); + this.listenTo(this.model, 'change:displayFormat', this.updateDisplayFormat); + this.listenTo(this.model, 'change:editMask', this.updateEditMask); + this.listenTo(this.model, 'change:inputType', this.updateInputType); + }, + + updateProperties: function(){ + ControlView.prototype.updateProperties.call(this); + editorBaseViewMixin.updateProperties.call(this); + + this.updateLabelText(); + this.updateInputType(); + }, + + updateFocusable: function () { + var focusable = this.model.get('focusable'); + + if (!focusable) { + this.ui.editor.attr('tabindex', -1); + } else { + this.ui.editor.removeAttr('tabindex'); + } + }, + + updateInputType: function () { + var inputType = this.model.get('inputType'); + var $editor = this.ui.editor; + var tagName = $editor.prop('tagName'); + if (inputType && tagName.toLowerCase() === 'input') { + $editor.attr('type', inputType); + } + }, + + updateEditMask: function(){ + this.updateValue(); + }, + + setFocus: function () { + this.ui.editor.focus(); + }, + + updateValue: function(){ + editorBaseViewMixin.updateValueState.call(this); + this.ui.control.val(this.getDisplayValue()); + }, + + updateLabelText: function(){ + var labelText = this.model.get('labelText'); + if(labelText){ + this.ui.label + .text(labelText) + .removeClass('hidden'); + }else{ + this.ui.label + .text('') + .addClass('hidden'); + } + + }, + + updateDisplayFormat: function(){ + this.updateValue(); + }, + + /** + * Рендеринг редактора значений + * + */ + renderControlEditor: function () { + var model = this.model; + var editor = model.get('editor'); + if (editor) { + editor.render(this.ui.editor); + } + }, + + getData: function () { + var model = this.model; + + return _.extend({}, + ControlView.prototype.getData.call(this), + editorBaseViewMixin.getData.call(this), { + labelText: model.get('labelText'), + labelFloating: model.get('labelFloating'), + value: this.getDisplayValue() + }); + }, + + getDisplayValue: function () { + var + model = this.model, + value = model.get('value'), + displayFormat = model.get('displayFormat'); + + return displayFormat ? displayFormat(null, {value: value}) : value; + } + +})); - /** - * - * @param {TabPage} tabPageElement - * @param {boolean} selected - * @returns {TabHeaderView} - */ - renderTabHeader: function (tabPageElement, selected) { - var header = new TabHeaderView({ - text: tabPageElement.getText(), - canClose: tabPageElement.getCanClose(), - selected: selected - }); +//####app/controls/_base/eventManager.js +function EventManager() { + this.handlers = {}; +} - tabPageElement.onPropertyChanged('text', function () { - header.setText(tabPageElement.getText()); - }); +EventManager.prototype.on = function (name, handler) { + if (typeof this.handlers[name] === 'undefined') { + this.handlers[name] = []; + } + this.handlers[name].push(handler); + return this; +}; - tabPageElement.onPropertyChanged('canClose', function () { - header.setCanClose(tabPageElement.getCanClose()); - }); +EventManager.prototype.trigger = function (name, message, context) { + var eventHandlers = this.handlers[name]; + var response = true; + if (Array.isArray(eventHandlers)) { + response = eventHandlers + .map(function (handler) { + return handler.call(context, message); + }) + .every(function (result) { + return result !== false; + }); + } + return response; +}; - this.ui.header.append(header.render().$el); - return header; - }, +//####app/controls/_base/highlightMixin.js +var highlightMixin = { + + attributeName: '_highlight', + + highlightClassName: 'active', + + control: { + + setHighlight: function (highlight) { + this.controlModel.set(highlightMixin.attributeName, highlight); + }, + + getHighlight: function () { + return this.controlModel.get(highlightMixin.attributeName); + } + + }, + + controlView: { + + initHighlightMixin: function () { + this.listenTo(this.model, 'change:' + highlightMixin.attributeName, function () { + var model = this.model; + this.$el.toggleClass(highlightMixin.highlightClassName, model.get(highlightMixin.attributeName)); + this.$el.parent().toggleClass(highlightMixin.highlightClassName, model.get(highlightMixin.attributeName)); + }); + } + + } +}; + - renderTabContent: function (item, index) { - var - itemTemplate = this.model.get('itemTemplate'), - element = itemTemplate(undefined, {item: item, index: index}); +//####app/controls/_base/textEditor/textEditorModel.js +/** + * @TODO Если маска заполнена не полностью - не выходить из режима редактирования + */ +var TextEditorModel = Backbone.Model.extend({ + + Mode: { + Edit: 'edit', + Display: 'display' + }, + + initialize: function () { + + this.initEditMode(); + + this.on('change:originalValue', this.onChangeOriginalValueHandler); + this.on('change:value', this.onChangeValueHandler); + this.on('change:mode', this.onChangeModeHandler); + this.on('change:text', this.onChangeTextHandler); + }, + + onChangeTextHandler: function (model, value, options) { + var modeStrategy = this.get('modeStrategy'); + modeStrategy.onChangeTextHandler(model, value, options); + }, + + convertValue: function (value) { + var getConverter = this.get('valueConverter'); + var converter = getConverter.call(null); + return (typeof converter === 'function') ? converter.call(this, value) : value; + }, + + initEditMode: function () { + this.modeStrategies = {}; + this.modeStrategies[this.Mode.Edit] = new TextEditorModelEditModeStrategy(); + this.modeStrategies[this.Mode.Display] = new TextEditorModelDisplayModeStrategy(); + + this.updateEditModeStrategy(); + }, + + defaults: function () { + return { + mode: this.Mode.Display + }; + }, + + updateEditModeStrategy: function () { + var mode = this.get('mode'); + this.set('modeStrategy', this.modeStrategies[mode]); + }, + + onChangeModeHandler: function (model, mode, options) { + var prevMode = this.previous('mode'); + if (options.cancel) { + this.cancelChanges(); + } else if (mode === this.Mode.Display && prevMode === this.Mode.Edit) { + //При успешном переходе из режима редактирования в режим отображения - обновляем исходное значение + this.applyChanges(); + } + + this.updateEditModeStrategy(); + this.updateText(); + }, + + /** + * + * @param {boolean} [cancel = false] + * @param {boolean} [validate = true] + */ + setDisplayMode: function (cancel, validate) { + cancel = !!cancel; + validate = (typeof validate === 'undefined') ? true : !!validate; + + this.set('mode', this.Mode.Display, { + cancel: cancel, + validate: validate + }); + + }, + + applyChanges: function () { + this.set('originalValue', this.get('value')); + }, + + cancelChanges: function () { + this.set('value', this.get('originalValue')); + }, + + /** + * + * @param text + * @param {boolean} [ui = false] + */ + setText: function (text, ui) { + var modeStrategy = this.get('modeStrategy'); + modeStrategy.setText(this, text, ui); + }, + + getEditMask: function () { + return this.get('editMask'); + }, + + getValue: function () { + return this.get('value'); + // + // + //var editMask = this.getEditMask(); + //var value; + // + //if (editMask) { + // value = editMask.getValue() + //} else { + // value = this.$el.val(); + //} + + //return value; + }, + + getDisplayFormat: function () { + return this.get('displayFormat'); + }, + + setEditMode: function () { + this.set('mode', this.Mode.Edit); + }, + + validate: function (attrs, options) { + + //@TODO Если меняется Mode Edit => Display, проверить введенное значение!!! + var validateValue = this.get('validateValue'), + value = this.getValue(); + + if (_.isFunction(validateValue)) { + return validateValue.call(null, value); + } + }, + + updateText: function () { + var modeStrategy = this.get('modeStrategy'); + modeStrategy.updateText(this); + }, + + onChangeValueHandler: function (model, value, options) { + if (!options.ui) { + this.updateText(); + } + + }, + + onChangeOriginalValueHandler: function (model, value) { + model.set('value', value, {originalValue: true}); + } + +}); +//####app/controls/_base/textEditor/textEditorView.js +var TextEditorView = Backbone.View.extend({ + + /** + * @member {TextEditorModel} model + */ + + classNameError: 'has-error', + + events: { + 'focusin': 'onFocusinHandler', + 'focusout': 'onFocusoutHandler', + 'keydown': 'onKeydownHandler', + 'change': 'onChangeHandler', + 'input': 'onInputHandler', + 'keyup': 'onKeyupHandler', //trigger OnKeyDown Event + 'click': 'onClickHandler', + 'drop': 'onDropHandler', + 'dragstart': 'OnDragstartHandler', + 'dragend': 'OnDragendHandler', + 'dragover': 'OnDragoverHandler', + 'dragleave': 'OnDragleaveHandler', + 'dragenter': 'OnDragenterHandler', + 'paste': 'onPasteHandler' + }, + + updateModelTextFromEditor: function () { + var model = this.model, + editMask = model.getEditMask(); + + if (!editMask) { + model.setText(this.$el.val(), true); + } + }, + + onChangeHandler: function () { + //Обработка для корректной обработки автозаполняемых полей + this.updateModelTextFromEditor(); + }, + + onInputHandler: function () { + var editMask = this.model.getEditMask(); + if (!editMask) { + this.updateModelTextFromEditor(); + } + }, + + onKeydownHandler: function (event) { + if (event.ctrlKey || event.altKey) { + return; + } + + if (event.which === InfinniUI.Keyboard.KeyCode.ESCAPE) { + //Отменить изменения и выйти из режима редактирования + this.model.setDisplayMode(true, false); + this.$el.blur(); + return; + } + + var editMask = this.model.getEditMask(); + if (!editMask) { + //model.text будет изменено в обработчике onInputHandler + return; + } + + var model = this.model; + var position; + + switch (event.which) { + case InfinniUI.Keyboard.KeyCode.TAB: + break; + case InfinniUI.Keyboard.KeyCode.HOME: + if (!event.shiftKey) { + position = editMask.moveToPrevChar(0); + if (position !== false) { + event.preventDefault(); + this.setCaretPosition(position); + } + } + + break; + + case InfinniUI.Keyboard.KeyCode.LEFT_ARROW: + if (!event.shiftKey) { + position = editMask.moveToPrevChar(this.getCaretPosition()); + if (position !== false) { + event.preventDefault(); + this.setCaretPosition(position); + } + } + break; + + case InfinniUI.Keyboard.KeyCode.RIGHT_ARROW: + if (!event.shiftKey) { + position = editMask.moveToNextChar(this.getCaretPosition()); + if (position !== false) { + event.preventDefault(); + this.setCaretPosition(position); + } + } + break; + + case InfinniUI.Keyboard.KeyCode.END: + if (!event.shiftKey) { + position = editMask.moveToNextChar(this.$el.val().length); + if (position !== false) { + event.preventDefault(); + this.setCaretPosition(position); + } + } + break; + + case InfinniUI.Keyboard.KeyCode.UP_ARROW: + if (!event.shiftKey) { + position = editMask.setNextValue(this.getCaretPosition()); + if (position !== false) { + event.preventDefault(); + model.setText(editMask.getText()); + this.setCaretPosition(position); + } + } + break; + + case InfinniUI.Keyboard.KeyCode.DOWN_ARROW: + if (!event.shiftKey) { + position = editMask.setPrevValue(this.getCaretPosition()); + if (position !== false) { + event.preventDefault(); + this.model.setText(editMask.getText()); + this.setCaretPosition(position); + } + } + break; + + case InfinniUI.Keyboard.KeyCode.DELETE: + event.preventDefault(); + position = editMask.deleteCharRight(this.getCaretPosition(), this.getSelectionLength()); + + this.model.setText(editMask.getText()); + if (position !== false) { + this.setCaretPosition(position); + } + break; + + case InfinniUI.Keyboard.KeyCode.BACKSPACE: + event.preventDefault(); + position = editMask.deleteCharLeft(this.getCaretPosition(), this.getSelectionLength()); + + this.model.setText(editMask.getText()); + if (position !== false) { + this.setCaretPosition(position); + } + break; + + case InfinniUI.Keyboard.KeyCode.SPACE: + if (editMask.value instanceof Date) { + event.preventDefault(); + position = editMask.getNextItemMask(this.getCaretPosition()); + if (position !== false) { + this.setCaretPosition(position); + } + } + break; + + default: + //замена выделенного текста, по нажатию + var char = InfinniUI.Keyboard.getCharByKeyCode(event.keyCode); + + event.preventDefault(); + + if (this.getSelectionLength() > 0) { + position = editMask.deleteSelectedText(this.getCaretPosition(), this.getSelectionLength(), char); + } else { + //Ввод символа + position = editMask.setCharAt(char, this.getCaretPosition(), this.getSelectionLength()); + } + + this.model.setText(editMask.getText()); + + if (position !== false) { + this.setCaretPosition(position); + } + + break; + } + }, + + onKeyupHandler: function (event) { + this.trigger('onKeyDown', { + keyCode: event.which, + value: this.model.getValue() + }); + }, + + onClickHandler: function (event) { + this.checkCurrentPosition(); + }, + + onPasteHandler: function (event) { + var originalEvent = event.originalEvent; + var text = originalEvent.clipboardData.getData('text/plain'); + var editMask = this.model.getEditMask(); + + if (editMask) { + event.preventDefault(); + this.textTyping(text); + } + }, + + OnDragstartHandler: function (event) { + var originalEvent = event.originalEvent; + originalEvent.dataTransfer.effectAllowed = 'copy'; + this.$el.attr('data-dragged', true); + }, + + OnDragendHandler: function (/*event*/) { + this.$el.removeAttr('data-dragged', false); + }, + + OnDragoverHandler: function (event) { + event.preventDefault(); + }, + + OnDragenterHandler: function (event) { + var dragged = this.$el.attr('data-dragged'); + + if (!dragged && this.getCanChange()) { + this.model.setEditMode(); + } + }, + + OnDragleaveHandler: function (event) { + var dragged = this.$el.attr('data-dragged'); + + if (!dragged) { + this.model.setDisplayMode(); + } + }, + + onDropHandler: function (event) { + event.preventDefault(); + event.stopPropagation(); + var dragged = this.$el.attr('data-dragged'); + + if (dragged) { //prevent drop on self + return; + } + + if (!this.getCanChange()) { + return; + } + + var originalEvent = event.originalEvent; + var text = originalEvent.dataTransfer.getData('text/plain'); + + this.textTyping(text, 0); + this.$el.focus(); + }, + + getCanChange: function () { + var disabled = this.$el.prop('disabled'); + + return disabled === false; + }, + + /** + * @description Заполняет поле ввода строкой text начиная с позиции position + * @protected + * + * @param {string} text + * @param {number} [position] + */ + textTyping: function (text, position) { + var editMask = this.model.getEditMask(); + var newText = text; + + if (editMask) { + text.split('') + .reduce(function (pos, char) { + return editMask.setCharAt(char, pos); + }, _.isNumber(position) ? position : this.getCaretPosition()); + + newText = editMask.getText(); + } + + this.model.setText(newText); + }, + + checkCurrentPosition: function (currentPosition) { + + if (!this.canCaretPosition()) { + return; + } + var editMask = this.model.getEditMask(); + if (!editMask) { + return; + } + + if (typeof currentPosition === 'undefined') { + currentPosition = this.getCaretPosition(); + } + + var position = currentPosition === 0 ? editMask.moveToPrevChar(0) : editMask.moveToNextChar(currentPosition - 1); + if (position !== currentPosition) { + this.setCaretPosition(position); + } + + }, + + getSelectionLength: function () { + var el = this.el, + len = 0; + + if (this.canCaretPosition()) { + var startPos = parseInt(el.selectionStart, 10), + endPos = parseInt(el.selectionEnd, 10); + + if (!isNaN(startPos) && !isNaN(endPos)) { + len = endPos - startPos; + } + } + + return len; + }, + + canCaretPosition: function () { + return (/text|password|search|tel|url/).test(this.el.type); + }, + + setCaretPosition: function (caretPosition) { + + if (_.isNumber(caretPosition) && this.canCaretPosition()) { + var el = this.el; + + //IE9+ + if (typeof el.selectionStart !== 'undefined') { + el.setSelectionRange(caretPosition, caretPosition); + } + } + + }, + + /** + * @private + * Получение позиции курсора в поле редактирования + * @returns {number} + */ + getCaretPosition: function () { + /** @var {HTMLInputElement} **/ + var el = this.el; + + var position = 0; + + if (this.canCaretPosition()) { + position = el.selectionStart; + } + + return position; + }, + + initialize: function () { + this.applyAutocomplete(); + this.listenTo(this.model, 'change:mode', this.onChangeModeHandler); + this.listenTo(this.model, 'change:text', this.onChangeTextHandler); + this.listenTo(this.model, 'invalid', this.onInvalidHandler); + }, + + /** + * @description Для элементов с маской ввода отключаем поддержку автозаполнения + */ + applyAutocomplete: function () { + var editMask = this.model.getEditMask(); + if (editMask) { + this.$el.attr('autocomplete', 'off'); + } + }, + + onInvalidHandler: function (model, error) { + this.$el.toggleClass(this.classNameError, true); + }, + + onFocusinHandler: function (/* event */) { + this.model.setEditMode(); + setTimeout(this.setCaretPosition.bind(this, 0), 4); + }, + + onFocusoutHandler: function (/* event */) { + this.model.setDisplayMode(); + }, + + onChangeModeHandler: function (model, mode) { + this.checkCurrentPosition(); + }, + + onChangeTextHandler: function (model, text) { + var $input = this.$el; + var position = this.getCaretPosition(); + + $input.toggleClass(this.classNameError, false); + + if($input.val() !== text) { + $input.val(text); + } + + var editMask = this.model.getEditMask(); + + if (editMask) { + if ($input.is(':focus')) { + this.checkCurrentPosition(position); + } + } + } +}); +//####app/controls/_base/textEditor/_mode/textEditorModelBaseModeStrategy.js +/** + * + * @constructor + */ +function TextEditorModelBaseModeStrategy() { +} + +/** + * Отображает текстовое представление значения элемента + * @abstract + * @param {TextEditorModel} model + */ +TextEditorModelBaseModeStrategy.prototype.updateText = function (model) { + +}; + + +/** + * Устанавливает значение поля оторажения/ввода значения + * @param {TextEditorModel} model + * @param {string} text + * @param {boolean} ui Признак исзменения со стороны UI + */ +TextEditorModelBaseModeStrategy.prototype.setText = function (model, text, ui) { + +}; + + +/** + * @param model + * @param value + */ +TextEditorModelBaseModeStrategy.prototype.onChangeTextHandler = function (model, value, options) { + +}; + - this.addChildElement(element); - this.ui.content.append(element.render()); - return element; - }, +//####app/controls/_base/textEditor/_mode/textEditorModelDisplayModeStrategy.js +/** + * @augments TextEditorModelBaseModeStrategy + * @constructor + */ +function TextEditorModelDisplayModeStrategy() { + TextEditorModelBaseModeStrategy.call(this); +} + +TextEditorModelDisplayModeStrategy.prototype = Object.create(TextEditorModelBaseModeStrategy.prototype); +TextEditorModelDisplayModeStrategy.prototype.constructor = TextEditorModelDisplayModeStrategy; + +TextEditorModelDisplayModeStrategy.prototype.updateText = function (model) { + var displayFormat = model.getDisplayFormat(); + var value = model.get('value'); + + var text; + + if (_.isFunction(displayFormat)) { + text = displayFormat.call(null, null, {value: value}); + } else { + text = value; + } + + model.set('text', text); +}; + +TextEditorModelDisplayModeStrategy.prototype.setText = function (model, text, ui) { + if (ui) { + //Изменение значения в поле ввода для режима просмотра - результат срабатывания автозаполнения браузера + model.set('text', text, {ui: ui}); + } +}; + +TextEditorModelDisplayModeStrategy.prototype.onChangeTextHandler = function (model, text, options) { + if (options.ui) { + var value = model.convertValue(text); + model.set('value', value, {ui: options.ui}); + } + model.applyChanges(); +}; +//####app/controls/_base/textEditor/_mode/textEditorModelEditModeStrategy.js +/** + * @augments TextEditorModelBaseModeStrategy + * @constructor + */ +function TextEditorModelEditModeStrategy() { + TextEditorModelBaseModeStrategy.call(this); +} + +TextEditorModelEditModeStrategy.prototype = Object.create(TextEditorModelBaseModeStrategy.prototype); +TextEditorModelEditModeStrategy.prototype.constructor = TextEditorModelBaseModeStrategy; + +TextEditorModelEditModeStrategy.prototype.updateText = function (model) { + var editMask = model.getEditMask(); + var value = model.get('value'); + var text; + + if (!editMask) { + text = value; + } else { + editMask.reset(value); + text = editMask.getText(); + } + + if (typeof text === 'undefined' || text === null) { + model.set('text', ''); + } else { + model.set('text', text.toString()); + } + +}; + +TextEditorModelEditModeStrategy.prototype.setText = function (model, text, ui) { + model.set('text', text, {ui: ui}); +}; + +TextEditorModelEditModeStrategy.prototype.onChangeTextHandler = function (model, newValue, options) { + var editMask = model.getEditMask(); + var value = editMask ? editMask.getData() : newValue; + model.set('value', model.convertValue(value), {silent: !!editMask, ui: options.ui}); +}; + - /** - * @protected - * @returns {Function} - */ - getTemplate: function () { - var - template, - headerLocation = this.model.get('headerLocation'); +//####app/controls/textBox/textBoxControl.js +/** + * + * @param parent + * @constructor + * @augments TextEditorBaseControl + */ +function TextBoxControl(parent) { + _.superClass(TextBoxControl, this, parent); +} + +_.inherit(TextBoxControl, TextEditorBaseControl); + +_.extend(TextBoxControl.prototype, { + + createControlModel: function () { + return new TextBoxModel(); + }, + + createControlView: function (model) { + return new TextBoxView({model: model}); + } +}); + - switch (headerLocation) { - case InfinniUI.TabHeaderLocation.top: - template = this.template.top; - break; - case InfinniUI.TabHeaderLocation.right: - template = this.template.right; - break; - case InfinniUI.TabHeaderLocation.bottom: - template = this.template.bottom; - break; - case InfinniUI.TabHeaderLocation.left: - template = this.template.left; - break; - case InfinniUI.TabHeaderLocation.none: - default: - template = this.template.none; - break; - } +//####app/controls/textBox/textBoxModel.js +/** + * @class + * @augments TextEditorBaseModel + */ +var TextBoxModel = TextEditorBaseModel.extend(/** @lends TextBoxModel.prototype */{ + defaults: _.extend( + {}, + TextEditorBaseModel.prototype.defaults, + { + multiline: false, + inputType: 'text' + } + ), + + initialize: function () { + TextEditorBaseModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + } + +}); +//####app/controls/textBox/textBoxView.js +/** + * @class + * @augments TextEditorBaseView + */ +var TextBoxView = TextEditorBaseView.extend(/** @lends TextBoxView.prototype */{ + + template: { + oneline: InfinniUI.Template["controls/textBox/template/oneline.tpl.html"], + multiline: InfinniUI.Template["controls/textBox/template/multiline.tpl.html"] + }, + + className: 'pl-textbox form-group', + + UI: _.extend({}, TextEditorBaseView.prototype.UI), + + events: _.extend({}, TextEditorBaseView.prototype.events, { + + }), + + initHandlersForProperties: function(){ + TextEditorBaseView.prototype.initHandlersForProperties.call(this); + + this.listenTo(this.model, 'change:multiline', this.updateMultiline); + this.listenTo(this.model, 'change:lineCount', this.updateLineCount); + }, + + updateProperties: function(){ + TextEditorBaseView.prototype.updateProperties.call(this); + + this.updateLineCount(); + }, + + updateMultiline: function(){ + this.rerender(); + }, + + updateLineCount: function(){ + var lineCount = this.model.get('lineCount'); + this.ui.editor.attr('rows', lineCount); + }, + + render: function () { + this.prerenderingActions(); + + var model = this.model; + var template = model.get('multiline') ? this.template.multiline : this.template.oneline; + + this.renderTemplate(template); + this.renderTextBoxEditor(); + + this.updateProperties(); + + this.trigger('render'); + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, + + getData: function () { + var data = TextEditorBaseView.prototype.getData.call(this); + var model = this.model; + return _.extend( + data, + { + multiline: model.get('multiline'), + lineCount: model.get('lineCount') + } + ); + }, + + renderTextBoxEditor: function () { + this.renderControlEditor(); + } + +}); + +//####app/controls/dateTimePicker/_modes/dateTimePickerMode.date.js +var dateTimePickerModeDate = { + getTemplate: function () { + return InfinniUI.Template["controls/dateTimePicker/template/date.tpl.html"]; + }, + + onClickDropdownHandler: function (event) { + var model = this.model; + var calendar = new SelectDate({ + model: model + }); + calendar.render(); + $('body').append(calendar.$el); + + calendar.updatePosition(this.el); + + this.listenTo(calendar, 'date', function (date) { + model.set('value', this.convertValue(date)); + }); + }, + + convertValue: function (value) { + return InfinniUI.DateUtils.toISO8601(value, {timezoneOffset: this.model.get('timeZone')}); + } +}; - return template; - }, +//####app/controls/dateTimePicker/_modes/dateTimePickerMode.dateTime.js +var dateTimePickerModeDateTime = { + getTemplate: function () { + return InfinniUI.Template["controls/dateTimePicker/template/dateTime.tpl.html"]; + }, + + onClickDropdownHandler: function (event) { + var model = this.model; + var calendar = new SelectDateTime({ + model: model + }); + calendar.render(); + $('body').append(calendar.$el); + + calendar.updatePosition(this.el); + + this.listenTo(calendar, 'date', function (date) { + model.set('value', this.convertValue(date)); + }); + }, + + convertValue: function (value) { + return InfinniUI.DateUtils.toISO8601(value, {timezoneOffset: this.model.get('timeZone')}); + } +}; - /** - * @protected - */ - updateProperties: function () { - ContainerView.prototype.updateProperties.call(this); - this.updateHeaderOrientation(); - this.updateSelectedItem(); - }, +//####app/controls/dateTimePicker/_modes/dateTimePickerMode.time.js +var dateTimePickerModeTime = { + getTemplate: function () { + return InfinniUI.Template["controls/dateTimePicker/template/time.tpl.html"]; + }, + + onClickDropdownHandler: function (event) { + var model = this.model; + var calendar = new SelectTime({ + model: model + }); + calendar.render(); + $('body').append(calendar.$el); + + calendar.updatePosition(this.el); + + this.listenTo(calendar, 'date', function (date) { + model.set('value', this.convertValue(date)); + }); + }, + + convertValue: function (value) { + return InfinniUI.DateUtils.toISO8601(value, {timezoneOffset: this.model.get('timeZone')}); + } +}; - /** - * @protected - */ - onChangeHeaderLocation: function () { - //При изменении положения вкладок меняется весь шаблон - this.rerender(); - }, +//####app/controls/dateTimePicker/components/base/selectComponent.js +var SelectComponent = Backbone.View.extend({ + + modelClass: Backbone.Model, + + initialize: function (options) { + var modelClass = this.modelClass; + + this.model = new modelClass({ + today: options.today || new Date(), + value: options.value, + date: options.value || options.today, + max: options.max, + min: options.min + }); + this.render(); + return this; + }, + + show: function () { + this.$el.css('display', 'block'); + }, + + hide: function () { + this.$el.css('display', 'none'); + }, + + /** + * @description Установка текущего положения списка выбора значений + * Если устанавливается недействительная дата - используется текущая + * @param date + */ + setDate: function (date) { + this.model.setDate(date); + } + +}); + + +_.extend(SelectComponent.prototype, bindUIElementsMixin); +//####app/controls/dateTimePicker/components/base/selectComponentModel.js +var SelectComponentModel = Backbone.Model.extend({ + + defaults: function () { + var today = new Date(); + + return { + today: today, + todayMonth: today.getMonth(), + todayDay: today.getDate(), + todayYear: today.getFullYear(), + hour: today.getHours(), + minute: today.getMinutes(), + second: today.getSeconds(), + millisecond: today.getMilliseconds() + } + }, + + initialize: function () { + this.updateDateParts(); + this.on('change:date', this.onChangeDateHandler, this); + }, + + updateDateParts: function () { + var date = this.get('date'); + + if (date instanceof Date) { + this.set({ + year: date.getFullYear(), + month: date.getMonth(), + day: date.getDate(), + hour: date.getHours(), + minute: date.getMinutes(), + second: date.getSeconds(), + millisecond: date.getMilliseconds() + }); + } else { + this.set({ + year: null, + month: null, + day: null, + hour: null, + minute: null, + second: null, + millisecond: null + }); + } + + }, + + onChangeDateHandler: function (model, value) { + if (typeof value !== 'undefined' && value !== null) { + model.set({ + year: moment(value).year(), + month: moment(value).month(), + day: moment(value).date(), + hour: moment(value).hour(), + minute: moment(value).minute(), + second: moment(value).second(), + millisecond: moment(value).millisecond() + }) + } else { + model.set({ + year: null, + month: null, + day: null, + hour: null, + minute: null, + second: null, + millisecond: null + }); + } + }, + + updateDatePart: function (datePart, model, value) { + var + d = this.get('date'), + date = InfinniUI.DateUtils.createDate(d) || this.get('today'), + data = this.toJSON(); + + + switch (datePart) { + case 'hour': + case 'minute': + case 'second': + date.setHours(data.hour, data.minute, data.second); + break; + case 'year': + case 'month': + case 'day': + date.setFullYear(data.year, data.month, data.day); + break; + } + + this.set('date', date); + }, + + checkRange: function (date, precision) { + var min = this.get('min'), + max = this.get('max'); + + return InfinniUI.DateUtils.checkRangeDate(date, min, max, precision); + }, + + keepDateInRange: function () { + if (this.isValid()) { + return; + } + var date = InfinniUI.DateUtils.getNearestDate(this.get('date'), this.get('min'), this.get('max')); + this.set('date', date); + }, + + /** + * @description Установка текущего положения списка выбора значений + * Если устанавливается недействительная дата - используется текущая + * @param date + */ + setDate: function (date) { + if (typeof date === 'undefined' || date === null){ + var value = this.get('value'), + today = this.get('date'); + + date = value || today; + } + + if (date instanceof Date) { + date = new Date(date.getTime()); + } + this.set('date', date); + } + + +}); + - /** - * @protected - */ - updateHeaderOrientation: function () { - //@TODO Реализовать TabPanel.updateHeaderOrientation() - }, +//####app/controls/dateTimePicker/components/selectDays.js +var SelectDaysModel = SelectComponentModel.extend({ + + initialize: function () { + SelectComponentModel.prototype.initialize.call(this); + this.on('change:year', this.updateDatePart.bind(this, 'year')); + this.on('change:month', this.updateDatePart.bind(this, 'month')); + this.on('change:day', this.updateDatePart.bind(this, 'day')); + }, + + today: function () { + this.set({ + year: this.get('todayYear'), + month: this.get('todayMonth') + }); + }, + + nextMonth: function () { + var + month = this.get('month'), + year = this.get('year'); + + this.set({ + month: month === 11 ? 0 : month + 1, + year: month === 11 ? year + 1 : year + }); + + this.keepDateInRange(); + }, + + prevMonth: function () { + var + month = this.get('month'), + year = this.get('year'); + + this.set({ + month: month === 0 ? 11 : month - 1, + year: month === 0 ? year - 1 : year + }); + + this.keepDateInRange(); + } + +}); + +var SelectDays = SelectComponent.extend({ + + modelClass: SelectDaysModel, + + template: InfinniUI.Template["controls/dateTimePicker/template/date/days.tpl.html"], + + UI: { + headerDays: '.weekdays-head .day', + calendarDays: '.day-calendar', + year: '.years-year', + month: '.years-month' + }, + + events: { + 'click .years': 'onYearsClickHandler', + 'click .btn-month-prev': 'prevMonth', + 'click .btn-month-next': 'nextMonth', + 'click .today-date': 'showToday', + 'click .day-calendar:not(".day-unavailable")': 'useDay', + 'click .time': 'showTime' + }, + + render: function () { + var template = this.template(); + this.$el.html(template); + this.bindUIElements(); + this.fillLegend(); + this.fillCalendar(); + this.renderMonth(); + this.renderYear(); + this.initOnChangeHandlers(); + }, + + initOnChangeHandlers: function () { + this.listenTo(this.model, 'change:month', this.onChangeMonthHandler); + this.listenTo(this.model, 'change:year', this.onChangeYearHandler); + this.listenTo(this.model, 'change:day', this.onChangeDayHandler); + }, + + renderMonth: function () { + var month = this.model.get('month'); + var dateTimeFormatInfo = localized.dateTimeFormatInfo; + this.ui.month.text(dateTimeFormatInfo.monthNames[month]); + }, + + renderYear: function () { + var year = this.model.get('year'); + this.ui.year.text(year); + }, + + onChangeMonthHandler: function (model, value) { + this.renderMonth(); + this.fillCalendar(); + }, + + onChangeYearHandler: function (model, value) { + this.renderYear(); + this.fillCalendar(); + }, + + fillLegend: function () { + var dateTimeFormatInfo = localized.dateTimeFormatInfo; + var firstDayOfWeek = dateTimeFormatInfo.firstDayOfWeek; + var days = dateTimeFormatInfo.abbreviatedDayNames.map(function (day, i) { + return i; + }); + + if (firstDayOfWeek > 0) { + days = days.splice(firstDayOfWeek).concat(days); + } + + this.ui.headerDays.each(function (i, el) { + var $el = $(el); + var index = days[i]; + $el.text(dateTimeFormatInfo.abbreviatedDayNames[index]); + markWeekend($el, index); + }); + + this.ui.calendarDays.each(function (i, el) { + var $el = $(el); + var index = days[i % 7]; + markWeekend($el, index); + }); + + function markWeekend($el, weekday) { + $el.toggleClass('day-weekend', weekday === 0 || weekday === 6); + } + }, + + fillCalendar: function () { + var model = this.model; + var valueDate = model.get('value'); + var month = model.get('month'); + var year = model.get('year'); + var day = model.get('day'); + var min = model.get('min'); + var max = model.get('max'); + var firstDayOfMonth = new Date(year, month); + var weekday = firstDayOfMonth.getDay(); + var dateTimeFormatInfo = localized.dateTimeFormatInfo; + var firstDayOfWeek = dateTimeFormatInfo.firstDayOfWeek; + + var weekdays = [0,1,2,3,4,5,6]; + Array.prototype.push.apply(weekdays, weekdays.splice(0, firstDayOfWeek)); + var start = new Date(year, month, 1 - weekdays.indexOf(weekday)); + + var startYear = start.getFullYear(), + startMonth = start.getMonth(), + startDate = start.getDate(); + + this.ui.calendarDays.each(function (i, el) { + var $el = $(el); + var d = new Date(startYear, startMonth, startDate + i); + $el.text(d.getDate()); + $el.attr('data-date', d); + markActiveMonth($el, d.getMonth() === month); + markToday($el, d); + markSelected($el, d); + markAvailable($el, d); + }); + + function markActiveMonth($el, active) { + $el.toggleClass('day-inactive', !active); + } + + function markToday($el, date) { + var today = date.getMonth() === model.get('todayMonth') + && date.getFullYear() === model.get('todayYear') + && date.getDate() === model.get('todayDay'); + + $el.toggleClass('day-today', today); + } + + function markSelected($el, value) { + var selected = false; + + if (valueDate) { + selected = moment(valueDate).isSame(value, 'day'); + } + + $el.toggleClass('day-selected', selected); + } + + function markAvailable($el, value) { + $el.toggleClass('day-unavailable', !model.checkRange(value, 'day')); + } + + }, + + onYearsClickHandler: function (event) { + var date = this.model.get('date'); + + this.trigger('year', date); + }, + + prevMonth: function () { + this.model.prevMonth(); + }, + + nextMonth: function () { + this.model.nextMonth(); + }, + + showToday: function () { + this.today(); + }, + + today: function () { + this.model.today(); + }, + + showTime: function () { + this.trigger('time', this.model.get('date')); + }, + + useDay: function (event) { + var $el = $(event.target), + date = new Date($el.attr('data-date')); + + this.model.set({ + year: date.getFullYear(), + month: date.getMonth(), + day: date.getDate() + }); + + this.trigger('date', this.model.get('date')); + } + +}); +//####app/controls/dateTimePicker/components/selectHours.js +var SelectHoursModel = SelectComponentModel.extend({ + + initialize: function () { + SelectComponentModel.prototype.initialize.call(this); + this.on('change:hour', this.updateDatePart.bind(this, 'hour')); + } + +}); + +var SelectHours = SelectComponent.extend({ + + modelClass: SelectHoursModel, + + template: InfinniUI.Template["controls/dateTimePicker/template/time/hours.tpl.html"], + + events: { + "click .hour:not('.hour-unavailable')": "useHour" + }, + + UI: { + hour: '.hour' + }, + + render: function () { + var template = this.template(); + this.$el.html(template); + this.bindUIElements(); + this.fillHoursTable(); + this.initOnChangeHandlers(); + }, + + fillHoursTable: function () { + //@TODO Заполнять в зависимости от формата 12/24 + var + model = this.model; + var date = model.get('date') || model.get('today'); + var now = new Date(); + + this.ui.hour.each(function (i, el) { + var $el = $(el); + var hour = stringUtils.padLeft(i, 2, '0'); + + $el.attr('data-hour', i); + $el.text(hour); + markNow($el, i); + markSelected($el, i); + markAvailable($el, i); + }); + + function markSelected($el, value) { + $el.toggleClass('hour-selected', date.getHours() === value); + } + + function markNow($el, value) { + var selected = moment(now).isSame(value, 'hour'); + $el.toggleClass('hour-today', selected); + } + + function markAvailable($el, value) { + var date = moment(model.get('date')).hour(value); + $el.toggleClass('hour-unavailable', !model.checkRange(date, 'hour')); + } + }, + + initOnChangeHandlers: function () { + this.listenTo(this.model, 'change:date', this.fillHoursTable); + }, + + useHour: function (event) { + var + $el = $(event.target), + model = this.model, + date = model.get('date'), + hour = parseInt($el.attr('data-hour'), 10); + + var newDate = InfinniUI.DateUtils.cloneDate(date); + newDate.setHours(hour); + model.set('date', newDate); + + this.trigger('hour', newDate); + } + +}); - /** - * @protected - * @description Проверяет чтобы одна из вкладок была активна - */ - checkSelectedItem: function () { - var - model = this.model, - tabPages = this.childElements, - selectedItem = model.get('selectedItem'); +//####app/controls/dateTimePicker/components/selectMinutes.js +var SelectMinutesModel = SelectComponentModel.extend({ + + initialize: function () { + SelectComponentModel.prototype.initialize.call(this); + this.on('change:minute', this.updateDatePart.bind(this, 'minute')); + } + +}); + +var SelectMinutes = SelectComponent.extend({ + + modelClass: SelectMinutesModel, + + template: InfinniUI.Template["controls/dateTimePicker/template/time/minutes.tpl.html"], + + events: { + "click .minute:not('.minute-unavailable')": "useMinute" + }, + + UI: { + minute: '.minute' + }, + + render: function () { + var template = this.template(); + this.$el.html(template); + this.bindUIElements(); + this.fillMinutesTable(); + this.initOnChangeHandlers(); + }, + + fillMinutesTable: function () { + var + model = this.model, + minute = model.get('minute'); + + this.ui.minute.each(function (i, el) { + var $el = $(el); + var minute = $el.attr('data-minute'); + markSelected($el, parseInt(minute, 10)); + markAvailable($el, parseInt(minute, 10)) + }); + + function markSelected($el, value) { + $el.toggleClass('minute-selected', value === minute); + } + + function markAvailable($el, value) { + var date = moment(model.get('date')).minute(value); + $el.toggleClass('minute-unavailable', !model.checkRange(date, 'minute')); + } + }, + + initOnChangeHandlers: function () { + this.listenTo(this.model, 'change:date', this.fillMinutesTable); + }, + + useMinute: function (event) { + var + $el = $(event.target), + model = this.model, + date = model.get('date'), + minute = parseInt($el.attr('data-minute'), 10); + + var newDate = InfinniUI.DateUtils.cloneDate(date); + newDate.setMinutes(minute); + this.trigger('minute', newDate); + } + +}); - if (!Array.isArray(tabPages)) { - model.set('selectedItem', null); - } else if (tabPages.length) { - if (tabPages.indexOf(selectedItem) === -1) { - model.set('selectedItem', tabPages[0]); - } - } else { - model.set('selectedItem', null); - } - }, +//####app/controls/dateTimePicker/components/selectMonths.js +var SelectMonthsModel = SelectComponentModel.extend({ + + initialize: function () { + SelectComponentModel.prototype.initialize.call(this); + this.on('change:month', this.updateDatePart.bind(this, 'month')); + this.on('change:year', this.updateDatePart.bind(this, 'year')); + }, + + + + nextYear: function () { + var year = this.get('year'); + this.set('year', year + 1); + this.keepDateInRange(); + }, + + prevYear: function () { + var year = this.get('year'); + this.set('year', year - 1); + this.keepDateInRange(); + }, + + today: function () { + this.set({ + month: this.get('todayMonth'), + year: this.get('todayYear') + }); + } +}); + +var SelectMonths = SelectComponent.extend({ + + modelClass: SelectMonthsModel, + + template: InfinniUI.Template["controls/dateTimePicker/template/date/months.tpl.html"], + + events: { + "click .btn-year-prev": "prevYear", + "click .btn-year-next": "nextYear", + "click .month:not('.month-unavailable')": "useMonth", + "click .year": "selectYear", + "click .today-month": "showToday" + }, + + UI: { + month: '.month', + year: '.year' + }, + + render: function () { + var template = this.template(); + this.$el.html(template); + this.bindUIElements(); + this.fillMonthsTable(); + this.initOnChangeHandlers(); + }, + + fillMonthsTable: function () { + this.ui.year.text(this.model.get('year')); + + var + model = this.model, + dateTimeFormatInfo = localized.dateTimeFormatInfo, + todayMonth = model.get('todayMonth'), + month = model.get('month'); + + this.ui.month.each(function (i, el) { + var $el = $(el); + $el.text(dateTimeFormatInfo.abbreviatedMonthNames[i]); + $el.attr('data-month', i); + markTodayMonth($el, i); + markSelected($el, i); + markAvailable($el, i); + }); + + function markTodayMonth($el, value) { + var date = moment([model.get('year'), value]); + var today = model.get('today'); + + $el.toggleClass('month-today', moment(date).isSame(today, 'month')); + } + + function markSelected($el, value) { + var date = moment([model.get('year'), value]); + var selected = model.get('value'); + + $el.toggleClass('month-selected', moment(date).isSame(selected, 'month')); + } + + function markAvailable($el, value) { + var date = moment([model.get('year'), value]); + $el.toggleClass('month-unavailable', !model.checkRange(date, 'month')); + } + }, + + initOnChangeHandlers: function () { + this.listenTo(this.model, 'change:year', this.fillMonthsTable); + }, + + prevYear: function () { + this.model.prevYear(); + }, + + nextYear: function () { + this.model.nextYear(); + }, + + useMonth: function (event) { + var + $el = $(event.target), + model = this.model; + + model.set({ + year: parseInt(model.get('year'), 10), + month: parseInt($el.attr('data-month'), 10) + }); + this.trigger('month', model.get('date')); + }, + + selectYear: function () { + var + model = this.model; + + this.trigger('year', model.get('data')); + }, + + showToday: function () { + this.today(); + }, + + today: function () { + this.model.today(); + } + + + +}); - /** - * @protected - */ - updateSelectedItem: function () { - if (!this.wasRendered) { - return; - } +//####app/controls/dateTimePicker/components/selectSeconds.js +var SelectSecondsModel = SelectComponentModel.extend({ + + initialize: function () { + SelectComponentModel.prototype.initialize.call(this); + this.on('change:second', this.updateDatePart.bind(this, 'second')); + } + +}); + +var SelectSeconds = SelectComponent.extend({ + + modelClass: SelectSecondsModel, + + template: InfinniUI.Template["controls/dateTimePicker/template/time/seconds.tpl.html"], + + events: { + "click .second:not('.second-unavailable')": "useSecond" + }, + + UI: { + second: '.second' + }, + + render: function () { + var template = this.template(); + this.$el.html(template); + this.bindUIElements(); + this.fillSecondsTable(); + this.initOnChangeHandlers(); + }, + + fillSecondsTable: function () { + var + model = this.model, + second = model.get('second'); + + this.ui.second.each(function (i, el) { + var $el = $(el); + var second = $el.attr('data-second'); + markSelected($el, parseInt(second, 10)); + markAvailable($el, parseInt(second, 10)) + }); + + function markSelected($el, value) { + $el.toggleClass('second-selected', value === second); + } + + function markAvailable($el, value) { + var date = moment(model.get('date')).seconds(value); + $el.toggleClass('second-unavailable', !model.checkRange(date)); + } + }, + + initOnChangeHandlers: function () { + this.listenTo(this.model, 'change:date', this.fillSecondsTable); + }, + + useSecond: function (event) { + var + $el = $(event.target), + model = this.model, + date = model.get('date'), + second = parseInt($el.attr('data-second'), 10); + + var newDate = InfinniUI.DateUtils.cloneDate(date); + + newDate.setSeconds(second); + this.trigger('second', newDate); + } + +}); - var - tabPages = this.childElements, - tabHeaders = this.tabHeaders, - selectedItem = this.model.get('selectedItem'), - selectedIndex = tabPages.indexOf(selectedItem); +//####app/controls/dateTimePicker/components/selectTimes.js +var SelectTimesModel = SelectComponentModel.extend({ + + initialize: function () { + SelectComponentModel.prototype.initialize.call(this); + this.on('change:hour', this.updateDatePart.bind(this, 'hour')); + this.on('change:minute', this.updateDatePart.bind(this, 'minute')); + this.on('change:second', this.updateDatePart.bind(this, 'second')); + this.on('change:millisecond', this.updateDatePart.bind(this, 'millisecond')); + }, + + nextHour: function () { + var hour = this.get('hour'); + hour += 1; + + //@TODO Границу использовать в зависимости от 12/24 формата записи даты из настроек локализации + if (hour > 23) { + return; + } + + this.set('hour', hour); + this.keepDateInRange(); + }, + + prevHour: function () { + var hour = this.get('hour'); + hour -= 1; + + if (hour < 0) { + return; + } + + this.set('hour', hour); + this.keepDateInRange(); + }, + + nextMinute: function () { + var minute = this.get('minute'); + minute += 1; + + if (minute >= 60) { + return; + } + + this.set('minute', minute); + this.keepDateInRange(); + }, + + prevMinute: function () { + var minute = this.get('minute'); + minute -= 1; + + if (minute < 0) { + return; + } + + this.set('minute', minute); + this.keepDateInRange(); + }, + + nextSecond: function () { + var second = this.get('second'); + second += 1; + + if (second >= 60) { + return; + } + + this.set('second', second); + this.keepDateInRange(); + }, + + prevSecond: function () { + var second = this.get('second'); + second -= 1; + + if (second < 0) { + return; + } + + this.set('second', second); + this.keepDateInRange(); + }, + + validate: function (attr, options) { + var value = InfinniUI.DateUtils.cloneDate(attr.date); + value.setHours(attr.hour, attr.minute, attr.second, attr.millisecond); + + if (!this.checkRange(value)) { + return 'Out of range'; + } + } + +}); + +var SelectTimes = SelectComponent.extend({ + + modelClass: SelectTimesModel, + + template: InfinniUI.Template["controls/dateTimePicker/template/time/time.tpl.html"], + + events: { + "click .time-spin-down.time-spin-hour": "prevHour", + "click .time-spin-up.time-spin-hour": "nextHour", + + "click .time-spin-down.time-spin-minute": "prevMinute", + "click .time-spin-up.time-spin-minute": "nextMinute", + + "click .time-spin-down.time-spin-second": "prevSecond", + "click .time-spin-up.time-spin-second": "nextSecond", + + "click .time-segment-hour": "selectHour", + "click .time-segment-minute": "selectMinute", + "click .time-segment-second": "selectSecond", + "click .days": "selectDay" + }, + + UI: { + month: '.month', + year: '.year', + hour: '.time-segment-hour', + minute: '.time-segment-minute', + second: '.time-segment-second' + }, + + render: function () { + var template = this.template(); + this.$el.html(template); + this.bindUIElements(); + this.updateHour(); + this.updateMinute(); + this.updateSecond(); + this.initOnChangeHandlers(); + }, + + selectHour: function () { + var + model = this.model, + date = model.get('date'), + hour = model.get('hour'), + minute = model.get('minute'), + second = model.get('second'); + + date.setHours(hour, minute, second); + this.trigger('hour', date); + }, + + selectMinute: function () { + var + model = this.model, + date = model.get('date'), + hour = model.get('hour'), + minute = model.get('minute'), + second = model.get('second'); + + date.setHours(hour, minute, second); + this.trigger('minute', date); + }, + + selectSecond: function () { + var + model = this.model, + date = model.get('date'), + hour = model.get('hour'), + minute = model.get('minute'), + second = model.get('second'); + + date.setHours(hour, minute, second); + this.trigger('second', date); + }, + + initOnChangeHandlers: function () { + this.listenTo(this.model, 'change:hour', this.updateHour); + this.listenTo(this.model, 'change:minute', this.updateMinute); + this.listenTo(this.model, 'change:second', this.updateSecond); + this.listenTo(this.model, 'change:date', this.useTime); + }, + + updateHour: function () { + var hour = this.model.get('hour'); + this.ui.hour.text(stringUtils.padLeft(hour, 2, '0')); + }, + + updateMinute: function () { + var minute = this.model.get('minute'); + this.ui.minute.text(stringUtils.padLeft(minute, 2, '0')); + }, + + updateSecond: function () { + var second = this.model.get('second'); + this.ui.second.text(stringUtils.padLeft(second, 2, '0')); + }, + + prevHour: function () { + this.model.prevHour(); + }, + + nextHour: function () { + this.model.nextHour(); + }, + + prevMinute: function () { + this.model.prevMinute(); + }, + + nextMinute: function () { + this.model.nextMinute(); + }, + + prevSecond: function () { + this.model.prevSecond(); + }, + + nextSecond: function () { + this.model.nextSecond(); + }, + + useTime: function () { + var + date = this.model.get('date'); + + this.trigger('date', date); + }, + + selectDay: function () { + var + date = this.model.get('date'); + + this.trigger('day', date); + + } + +}); - //TabPage - if (Array.isArray(tabPages)) { - tabPages.forEach(function (tabPage) { - tabPage.setSelected(false); - }); +//####app/controls/dateTimePicker/components/selectYears.js +var SelectYearsModel = SelectComponentModel.extend({ + + defaults: function () { + var defaults = SelectComponentModel.prototype.defaults.call(this); + + return _.defaults({ + pageSize: 20, + page: 0 + }, defaults); + }, + + initialize: function () { + SelectComponentModel.prototype.initialize.call(this); + this.on('change:year', this.updateDatePart.bind(this, 'year')); + this.on('change:year', this.onChangeYearHandler); + }, + + prevPage: function () { + var page = this.get('page'); + this.set('page', page - 1); + }, + + nextPage: function () { + var page = this.get('page'); + this.set('page', page + 1); + }, + + resetPage: function () { + this.set('page', 0); + }, + + onChangeYearHandler: function (model, value) { + this.keepDateInRange(); + model.set('page', 0); + } + +}); + +var SelectYears = SelectComponent.extend({ + + modelClass: SelectYearsModel, + + template: InfinniUI.Template["controls/dateTimePicker/template/date/years.tpl.html"], + + events: { + 'click .btn-year-prev': "prevPage", + 'click .btn-year-next': "nextPage", + 'click .today-year': "showTodayYear", + 'click .year:not(".year-unavailable")': "useYear" + }, + + UI: { + years: '.year', + yearBegin: '.year-begin', + yearEnd: '.year-end' + }, + + initOnChangeHandlers: function () { + this.listenTo(this.model, 'change:page', this.fillYearsTable); + this.listenTo(this.model, 'change:year', this.fillYearsTable); + }, + + render: function () { + var template = this.template(); + this.$el.html(template); + this.bindUIElements(); + //this.fillCalendar(); + this.fillYearsTable(); + this.initOnChangeHandlers(); + }, + + fillYearsTable: function () { + var + model = this.model, + page = model.get('page'), + pageSize = model.get('pageSize'), + year = model.get('year'), + todayYear = model.get('todayYear'), + //startYear = Math.ceil((year || todayYear) - pageSize / 2) + page * pageSize; + startYear = Math.ceil(year - pageSize / 2) + page * pageSize; + + this.ui.years.each(function (i, el) { + var $el = $(el); + var year = startYear + i; + $el.text(year); + $el.attr('data-year', year); + markTodayYear($el, year); + markSelected($el, year); + markAvailable($el, year); + }); + + this.ui.yearBegin.text(startYear); + this.ui.yearEnd.text(startYear + pageSize - 1); + + function markTodayYear($el, value) { + $el.toggleClass('year-today', value === todayYear); + } + + function markSelected($el, value) { + $el.toggleClass('year-selected', value === year); + } + function markAvailable($el, value) { + var date = moment([value]); + $el.toggleClass('year-unavailable', !model.checkRange(date, 'year')); + } + + }, + + prevPage: function () { + this.model.prevPage(); + }, + + nextPage: function () { + this.model.nextPage(); + }, + + showTodayYear: function () { + this.today(); + }, + + today: function () { + this.model.resetPage(); + }, + + useYear: function (event) { + var $el = $(event.target), + model = this.model; + + model.set({ + year: parseInt($el.attr('data-year'), 10) + }); + + this.trigger('year', model.get('date')); + } + +}); - if (selectedIndex !== -1) { - tabPages[selectedIndex].setSelected(true); - } - } +//####app/controls/dateTimePicker/dateTimePickerControl.js +/** + * + * @param parent + * @constructor + * @augments TextEditorBaseControl + */ +function DateTimePickerControl(parent) { + _.superClass(DateTimePickerControl, this, parent); +} + +window.InfinniUI.DateTimePickerControl = DateTimePickerControl; + +_.inherit(DateTimePickerControl, TextEditorBaseControl); + +_.extend(DateTimePickerControl.prototype, { + + createControlModel: function () { + return new DateTimePickerModel(); + }, + + createControlView: function (model) { + return new DateTimePickerView({model: model}); + } +}); + - //TabHeader - if (Array.isArray(tabHeaders)) { - tabHeaders.forEach(function (tabHeader) { - tabHeader.setSelected(false); - }); - if (selectedIndex !== -1) { - tabHeaders[selectedIndex].setSelected(true); - } - } +//####app/controls/dateTimePicker/dateTimePickerModel.js +/** + * @class + * @augments TextEditorBaseModel + */ +var DateTimePickerModel = TextEditorBaseModel.extend(/** @lends DateTimePickerModel.prototype */{ + defaults: _.extend( + {}, + TextEditorBaseModel.prototype.defaults, + { + mode: "Date" + //today: new Date() + } + ), + + initialize: function () { + TextEditorBaseModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + this.set('today', new Date()); + this.set('timeZone', InfinniUI.DateUtils.getDefaultTimeZone()); + }, + + validate: function (attributes, options) { + var + min = attributes.minValue, + max = attributes.maxValue; + + return InfinniUI.DateUtils.checkRangeDate(attributes.value, attributes.minValue, attributes.maxValue); + } + + +}); +//####app/controls/dateTimePicker/dateTimePickerStrategy.js +var dateTimePickerStrategy = (function () { + + return { + Date: dateTimePickerModeDate, + DateTime: dateTimePickerModeDateTime, + Time: dateTimePickerModeTime + }; + +})(); + - }, +//####app/controls/dateTimePicker/dateTimePickerView.js +/** + * @class + * @augments TextEditorBaseView + */ +var DateTimePickerView = TextEditorBaseView.extend(/** @lends DateTimePickerView.prototype */{ + + className: "pl-datepicker form-group", + + template: InfinniUI.Template["controls/dateTimePicker/template/date.tpl.html"], + + UI: _.extend({}, TextEditorBaseView.prototype.UI, { + dropdownButton: '.pl-datepicker-calendar', + controlWrap: '.control-wrap', + editorWrap: '.editor-wrap' + }), + + events: _.extend({}, TextEditorBaseView.prototype.events, { + 'click .pl-datepicker-calendar': 'onClickDropdownHandler' + }), + + initialize: function () { + TextEditorBaseView.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + this.updateMode(); + this.listenTo(this.model, 'change:mode', this.updateMode); + }, + + initHandlersForProperties: function(){ + TextEditorBaseView.prototype.initHandlersForProperties.call(this); + + this.listenTo(this.model, 'change:minValue', this.updateMinValue); + this.listenTo(this.model, 'change:maxValue', this.updateMaxValue); + }, + + updateProperties: function(){ + TextEditorBaseView.prototype.updateProperties.call(this); + }, + + updateMode: function(){ + var mode = this.model.get('mode'); + _.extend(this, dateTimePickerStrategy[mode]); + + this.rerender(); + }, + + updateMinValue: function(){ + var mode = this.model.get('mode'); + _.extend(this, dateTimePickerStrategy[mode]); + + this.rerender(); + }, + + updateMaxValue: function(){ + var mode = this.model.get('mode'); + _.extend(this, dateTimePickerStrategy[mode]); + + this.rerender(); + }, + + updateEnabled: function(){ + TextEditorBaseView.prototype.updateEnabled.call(this); + + var isEnabled = this.model.get('enabled'); + this.ui.dropdownButton.prop('disabled', !isEnabled); + }, + + render: function () { + this.prerenderingActions(); + + this.renderTemplate(this.getTemplate()); + this.updateProperties(); + this.renderDateTimePickerEditor(); + + this.trigger('render'); + + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, + + getData: function () { + var + model = this.model; + + return _.extend({}, + TextEditorBaseView.prototype.getData.call(this), { + minValue: model.get('minValue'), + maxValue: model.get('maxValue'), + mode: model.get('mode') + }); + }, + + renderDateTimePickerEditor: function () { + var model = this.model; + this.renderControlEditor(); + return this; + }, + + getTemplate: function () { + throw new Error('Не перекрыт getTemplate'); + }, + + onClickDropdownHandler: function (event) {} + +}); +//####app/controls/dateTimePicker/selectDate.js +var SelectDate = Backbone.View.extend({ + + className: 'pl-datepicker-dropdown pl-dropdown-container', + + template: InfinniUI.Template["controls/dateTimePicker/template/select.date.tpl.html"], + + UI: { + days: '.days', + months: '.months', + years: '.years' + }, + + events: { + 'click .backdrop': 'onClickBackdropHandler', + 'click .datepicker-clear': 'onClickClearValueHandler', + 'click .today-date': 'onClickTodayHandler' + }, + + render: function () { + var template = this.template(); + this.$el.html(template); + this.bindUIElements(); + this.renderComponents(); + }, + + renderComponents: function () { + var model = this.model; + var value = InfinniUI.DateUtils.createDate(model.get('value')); + var today = InfinniUI.DateUtils.createDate(model.get('today')); + var timeZone = model.get('timeZone'); + var m = moment(value); + + if (m.isValid()) { + value = m.toDate(); + } else { + value = null; + } + + value = InfinniUI.DateUtils.changeTimezoneOffset(value, timeZone); + + var options = { + value: value, + today: today || new Date(), + //date: value, + max: model.get('maxValue'), + min: model.get('minValue') + }; + + options.el = this.ui.months; + var months = new SelectMonths(options); + + options.el = this.ui.years; + var years = new SelectYears(options); + + options.el = this.ui.days; + var days = new SelectDays(options); + + this.months = months; + this.years = years; + this.days = days; + + this.workflow(days, months, years, value)(value); + }, + + onClickBackdropHandler: function (event) { + this.remove(); + }, + + onClickClearValueHandler: function () { + this.clearValue(); + }, + + clearValue: function () { + this.useValue(null); + }, + + useValue: function (date) { + var model = this.model; + var timeZone = model.get('timeZone'); + + var min = model.get('minValue'), + max = model.get('maxValue'); + + if (!InfinniUI.DateUtils.checkRangeDate(date, min, max)) { + date = InfinniUI.DateUtils.getNearestDate(date, min, max); + } + + this.trigger('date', InfinniUI.DateUtils.restoreTimezoneOffset(date, timeZone)); + this.remove(); + }, + + workflow: function (days, months, years) { + + this + .listenTo(days, 'date', this.useValue) + .listenTo(days, 'year', function (date) { + showYears(date);//Needed select year from list + }) + .listenTo(years, 'year', function (date) { + showMonths(date);//Needed select month for year + }) + .listenTo(months, 'year', function (date) { + showYears(date);//Needed select year from list + }) + .listenTo(months, 'month', function (date) { + showDays(date);//Needed select day from calendar + }); + + return showDays; + + function showDays(date) { + days.setDate(date); + + years.hide(); + months.hide(); + days.show(); + } + + function showMonths(date) { + months.setDate(date); + + days.hide(); + years.hide(); + months.show(); + } + + function showYears(date) { + years.setDate(date); + + days.hide(); + months.hide(); + years.show(); + } + + }, + + onClickTodayHandler: function () { + this.useValue(new Date()); + }, + + updatePosition: function (parentDOMElement) { + var direction = this.getDropdownDirection(parentDOMElement); + this.setPositionFor(parentDOMElement, direction ); + }, + + setPositionFor: function (parentDOMElement, direction) { + clearInterval(this._intervalId); + + this.applyStyle(parentDOMElement, direction); + this._intervalId = setInterval(this.applyStyle.bind(this, parentDOMElement, direction), 100); + }, + + remove: function () { + clearInterval(this._intervalId); + return Backbone.View.prototype.remove.apply(this, arguments); + }, + + getDropdownDirection: function (parentDOMElement) { + + var windowHeight = $(window).height(); + var rect = parentDOMElement.getBoundingClientRect(); + var height = this.$el.height(); + + var direction = 'bottom'; + if (rect.bottom + height + 30 > windowHeight && rect.bottom > windowHeight / 2 && rect.top > height) { + direction = 'top'; + } + + return direction; + }, + + applyStyle: function (parentDOMElement, direction) { + var rect = parentDOMElement.getBoundingClientRect(); + + var rectDropdown = this.el.getBoundingClientRect(); + + //@TODO Вынести общие стили в css + var style = { + position: "absolute", + left: window.pageXOffset + rect.right - Math.round(rectDropdown.width) + }; + + if (direction === 'bottom') { + style.top = window.pageYOffset + rect.bottom; + } else { + style.top = window.pageYOffset + rect.top - this.$el.height(); + } + + this.$el.css(style); + } + + +}); + +_.extend(SelectDate.prototype, bindUIElementsMixin); +//####app/controls/dateTimePicker/selectDateTime.js +var SelectDateTime = SelectDate.extend({ + + className: 'pl-datepicker-dropdown pl-dropdown-container', + + template: InfinniUI.Template["controls/dateTimePicker/template/select.dateTime.tpl.html"], + + UI: { + days: '.days', + months: '.months', + years: '.years', + times: '.times', + hours: '.hours', + minutes: '.minutes' + }, + + onClickToggleDateHandler: function () { + this.trigger('days'); + }, + + onClickToggleTimeHandler: function () { + this.trigger('time'); + }, + + + renderComponents: function () { + var model = this.model; + var value = InfinniUI.DateUtils.createDate(model.get('value')); + var today = InfinniUI.DateUtils.createDate(model.get('today')); + var timeZone = model.get('timeZone'); + var m = moment(value); + + if (m.isValid()) { + value = m.toDate(); + } else { + value = null; + } + + value = InfinniUI.DateUtils.changeTimezoneOffset(value, timeZone); + + var options = { + value: value, + today: today || new Date(), + //date: value, + max: model.get('maxValue'), + min: model.get('minValue') + }; + + options.el = this.ui.months; + var months = new SelectMonths(options); + + options.el = this.ui.years; + var years = new SelectYears(options); + + options.el = this.ui.days; + var days = new SelectDays(options); + + options.el = this.ui.times; + var time = new SelectTimes(options); + //time.setDate(undefined); + + options.el = this.ui.hours; + var hours = new SelectHours(options); + + options.el = this.ui.minutes; + var minutes = new SelectMinutes(options); + + + this.workflow(days, months, years, time, hours, minutes)(value); + }, + + useTime: function (date) { + var model = this.model; + var timeZone = model.get('timeZone'); + + var min = model.get('minValue'), + max = model.get('maxValue'); + + if (!InfinniUI.DateUtils.checkRangeDate(date, min, max)) { + date = InfinniUI.DateUtils.getNearestDate(date, min, max); + } + + this.trigger('date', InfinniUI.DateUtils.restoreTimezoneOffset(date, timeZone)); + + return date; + }, + + workflow: function (days, months, years, time, hours, minutes) { + var useTime = this.useTime.bind(this); + var components = Array.prototype.slice.call(arguments); + + this + .listenTo(days, 'date', this.useValue) + .listenTo(days, 'year', function (date) { + showYears(date);//Needed select year from list + }) + .listenTo(days, 'time', function (date) { + showTime(date); + }) + .listenTo(years, 'year', function (date) { + showMonths(date);//Needed select month for year + }) + .listenTo(months, 'year', function (date) { + showYears(date);//Needed select year from list + }) + .listenTo(months, 'month', function (date) { + showDays(date);//Needed select day from calendar + }); + + this.listenTo(time, 'hour', function (date) { + showHours(date); + }) + .listenTo(time, 'minute', function (date) { + showMinutes(date); + }) + .listenTo(time, 'day', function (date) { + showDays(date); + }) + .listenTo(time, 'date', function (date) { + useTime(date); + }) + .listenTo(hours, 'hour', function (date) { + var newDate = useTime(date); + showTime(newDate); + }) + .listenTo(minutes, 'minute', function (date) { + var newDate = useTime(date); + showTime(newDate); + }); + + //Переключатель режима Date/Time + this + .on('days', function (date) { + showDays(date); + }) + .on('time', function (date) { + showTime(date); + }); + + return showDays; + + function switchComponent(component) { + components.forEach(function (c) { + if (c !== component) { + c.hide(); + } + }); + component.show(); + } + + function showDays(date) { + days.setDate(date); + switchComponent(days); + } + + function showMonths(date) { + months.setDate(date); + switchComponent(months); + } + + function showYears(date) { + years.setDate(date); + switchComponent(years); + } + + function showHours(date) { + hours.setDate(date); + switchComponent(hours); + } + + function showMinutes(date) { + minutes.setDate(date); + switchComponent(minutes); + } + + function showTime(date) { + time.setDate(date); + switchComponent(time); + } + + } + +}); +//####app/controls/dateTimePicker/selectTime.js +var SelectTime = SelectDate.extend({ + + className: 'pl-timepicker-dropdown pl-dropdown-container', + + template: InfinniUI.Template["controls/dateTimePicker/template/select.time.tpl.html"], + + UI: { + times: '.times', + hours: '.hours', + minutes: '.minutes', + seconds: '.seconds' + }, + + renderComponents: function () { + var model = this.model; + var value = InfinniUI.DateUtils.createDate(model.get('value')); + var today = InfinniUI.DateUtils.createDate(model.get('today')); + var timeZone = model.get('timeZone'); + var m = moment(value); + + if (m.isValid()) { + value = m.toDate(); + } else { + value = null; + } + + value = InfinniUI.DateUtils.changeTimezoneOffset(value, timeZone); + //if (value === null || typeof value === 'undefined') { + // value = today; + //} + + var options = { + value: value, + today: today, + //date: date, + max: model.get('maxValue'), + min: model.get('minValue') + }; + + options.el = this.ui.times; + var time = new SelectTimes(options); + + options.el = this.ui.hours; + var hours = new SelectHours(options); + + options.el = this.ui.minutes; + var minutes = new SelectMinutes(options); + + options.el = this.ui.seconds; + var seconds = new SelectSeconds(options); + + this.workflow(time, hours, minutes, seconds)(value); + }, + + useTime: function (date) { + var model = this.model; + var timeZone = model.get('timeZone'); + + var min = model.get('minValue'), + max = model.get('maxValue'); + + if (!InfinniUI.DateUtils.checkRangeDate(date, min, max)) { + date = InfinniUI.DateUtils.getNearestDate(date, min, max); + } + + this.trigger('date', InfinniUI.DateUtils.restoreTimezoneOffset(date, timeZone)); + return date; + }, + + workflow: function (time, hours, minutes, seconds) { + var useTime = this.useTime.bind(this); + var components = Array.prototype.slice.call(arguments); + + this.listenTo(time, 'hour', function (date) { + showHours(date); + }) + .listenTo(time, 'minute', function (date) { + showMinutes(date); + }) + .listenTo(time, 'second', function (date) { + showSeconds(date); + }) + .listenTo(time, 'date', function (date) { + useTime(date); + }) + .listenTo(hours, 'hour', function (date) { + var value = useTime(date); + showTime(value); + }) + .listenTo(minutes, 'minute', function (date) { + var value = useTime(date); + showTime(value); + }) + .listenTo(seconds, 'second', function (date) { + var value = useTime(date); + showTime(value); + }); + + return showTime; + + function switchComponent(component) { + components.forEach(function (c) { + if (c !== component) { + c.hide(); + } + }); + component.show(); + } + + function showHours(date) { + hours.setDate(date); + switchComponent(hours); + } + + function showMinutes(date) { + minutes.setDate(date); + switchComponent(minutes); + } + + function showSeconds(date) { + seconds.setDate(date); + switchComponent(seconds); + } + + function showTime(date) { + time.setDate(date); + switchComponent(time); + } + + } + +}); +//####app/controls/datePicker/datePickerControl.js +function DatePickerControl(parent) { + _.superClass(DatePickerControl, this, parent); +} + +_.inherit(DatePickerControl, DateTimePickerControl); + +_.extend(DatePickerControl.prototype, { + + createControlModel: function () { + return new DatePickerModel(); + }, + + createControlView: function (model) { + return new DatePickerView({model: model}); + } +}); + + +//####app/controls/datePicker/datePickerModel.js +var DatePickerModel = DateTimePickerModel.extend({ + + initialize: function () { + DateTimePickerModel.prototype.initialize.apply(this, arguments); - /** - * @protected - */ - updateGrouping: function () { } }); +//####app/controls/datePicker/datePickerView.js +var DatePickerView = DateTimePickerView .extend({ + +}); +//####app/controls/datePicker/dateTimePickerMode.datePicker.js +console.assert(dateTimePickerModeDate, "dateTimePickerModeDate is undefined"); + +var dateTimePickerModeDatePicker = _.extend({}, dateTimePickerModeDate, { + + convertValue: function (value) { + var _value = null; + if (value && value.constructor === Date) { + _value = InfinniUI.DateUtils.dateToTimestamp(value); + } + + return _value; + } +}); + +dateTimePickerStrategy['DatePicker'] = dateTimePickerModeDatePicker; -//####app/controls/tabPanel/tabHeader/tabHeaderView.js -var TabHeaderModel = Backbone.Model.extend({ +//####app/controls/timePicker/dateTimePickerMode.timePicker.js +console.assert(dateTimePickerModeTime, "dateTimePickerModeTime is undefined"); + +var dateTimePickerModeTimePicker = _.extend({}, dateTimePickerModeTime, { + + convertValue: function (value) { + var _value = null; + if (value && value.constructor === Date) { + _value = InfinniUI.DateUtils.dateToTimestampTime(value); + } + + return _value; + } + +}); + +dateTimePickerStrategy['TimePicker'] = dateTimePickerModeTimePicker; +//####app/controls/timePicker/timePickerControl.js +function TimePickerControl(parent) { + _.superClass(TimePickerControl, this, parent); +} + +_.inherit(TimePickerControl, DateTimePickerControl); + +_.extend(TimePickerControl.prototype, { + + createControlModel: function () { + return new TimePickerModel(); + }, + + createControlView: function (model) { + return new TimePickerView({model: model}); + } +}); + - defaults: { - text: '', - canClose: false +//####app/controls/timePicker/timePickerModel.js +var TimePickerModel = DateTimePickerModel.extend({ + + initialize: function () { + DateTimePickerModel.prototype.initialize.apply(this, arguments); + var date = new Date(); + date.setFullYear(1970, 0, 1); + this.set('today', date); } + }); +//####app/controls/timePicker/timePickerView.js +var TimePickerView = DateTimePickerView .extend({ -var TabHeaderView = Backbone.View.extend({ + className: "pl-datepicker pl-timepicker form-group" - className: "pl-tabheader", +}); +//####app/controls/application/statusBar/statusBar.js +var StatusBarControl = function () { + _.superClass(StatusBarControl, this); +}; +_.inherit(StatusBarControl, Control); +_.extend(StatusBarControl.prototype, { + createControlModel: function () { + return new StatusBarModel(); + }, + createControlView: function (model) { + return new StatusBarView({model: model}); + } +}); - tagName: "li", +var StatusBarModel = ControlModel.extend({ + defaults: _.defaults({}, ControlModel.prototype.defaults, { + time: '', + date: '', + result: null + }) +}); - template: InfinniUI.Template["controls/tabPanel/tabHeader/template/tabHeader.tpl.html"], +var StatusBarView = ControlView.extend({ + className: 'pl-status-bar', events: { - "click": "onClickHandler", - "click .pl-close": "onClickCloseHandler" + 'click .signIn': 'signInHandler', + 'click .signOut': 'signOutHandler', + 'click .status-bar-menu': 'openMenuHandler' }, - UI: { - label: '.pl-tabheader-text', - close: '.pl-close' - }, + template: InfinniUI.Template['controls/application/statusBar/template.tpl.html'], + loginTemplate: InfinniUI.Template['controls/application/statusBar/authentication/loginTemplate.tpl.html'], - initialize: function (options) { - this.model = new TabHeaderModel(options); + enterTemplate: InfinniUI.Template['controls/application/statusBar/authentication/enterTemplate.tpl.html'], + successTemplate: InfinniUI.Template['controls/application/statusBar/authentication/successTemplate.tpl.html'], - this.on('rendered', this.onRenderedHandler); - }, + initialize: function () { + var self = this; + self.model.set('time', moment().format('HH:mm')); + self.model.set('date', moment().format('D MMMM')); - render: function () { - this.$el.html(this.template); - this.bindUIElements(); - this.trigger('rendered'); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, + window.setInterval(function () { + self.model.set('time', moment().format('HH:mm')); + self.model.set('date', moment().format('D MMMM')); + self.dateRender(); + }, 10 * 1000); - /** - * - * @param {string} value - */ - setText: function (value) { - this.model.set('text', value); + getUserInfo(this); + this.listenTo(this.model, 'change:result', this.render); }, - /** - * - * @param {boolean} value - */ - setCanClose: function (value) { - this.model.set('canClose', value); + dateRender: function () { + this.$el.find('.time').text(this.model.get('time')); + this.$el.find('.date').text(this.model.get('date')); }, - /** - * - * @param {boolean} value - */ - setSelected: function (value) { - this.model.set('selected', value); - }, + signInHandler: function () { + var self = this; + if (!this.$modal) { + this.$modal = $(this.loginTemplate({})); + this.$modal.appendTo('body'); + } - /** - * @protected - */ - updateProperties: function () { - this.updateTextHandler(); - this.updateCanClose(); - this.updateSelectedHandler(); + this.$modal.modal('show'); + this.$modal.on('hidden.bs.modal', function () { + $(this).find('#password, #userName').val(''); + $(this).find('#remember').attr('checked', false); + }); + this.$modal.find('.post').on('click', function () { + signInInternal(self); + }) }, + openMenuHandler: function(){ + var menu = $('.app-area').find('.pl-menu'); + var area = menu.closest('.app-area'); - /** - * @protected - */ - onRenderedHandler: function () { - this.updateProperties(); - this.listenTo(this.model, 'change:text', this.updateTextHandler); - this.listenTo(this.model, 'change:selected', this.updateSelectedHandler); - this.listenTo(this.model, 'cahnge:canClose', this.updateCanClose); + if(menu.length && area.length) { + if($(area).is(':visible')) { + area.css({ + 'display': 'none' + }); + }else{ + area.css({ + 'position': 'absolute', + 'width': '100%', + 'display': 'block', + 'overflow': 'hidden' + }); + } + } }, - /** - * @protected - */ - updateTextHandler: function () { - var text = this.model.get('text'); - this.ui.label.text(text); + signOutHandler: function () { + signOut(this); }, - /** - * @protected - */ - updateCanClose: function () { - var canClose = this.model.get('canClose'); - this.ui.close.toggleClass('hidden', !canClose); - }, + render: function () { + var result = this.model.get('result');debugger; + var header = InfinniUI.config.configName; + var $wrap = $(this.template({header: header})); + var $loginTemplate, + self = this; - /** - * @protected - */ - updateSelectedHandler: function () { - var selected = this.model.get('selected'); - this.$el.toggleClass('pl-active active', selected); - }, + window.adjustLoginResult(result).then(function(r){ + if (result) { + $loginTemplate = $(self.successTemplate({ + displayName: r.UserName, + activeRole: r.ActiveRole, + roles: _.pluck(result.Roles, 'DisplayName').join(', ') + })); + } else { + $loginTemplate = $(self.enterTemplate({})); + } - onClickHandler: function (event) { - this.trigger('selected'); - }, + $wrap.find('.page-header-inner').prepend($loginTemplate); + self.$el + .empty() + .append($wrap); + }); - onClickCloseHandler: function (event) { - event.stopPropagation(); - this.trigger('close'); - } + this.$el.find('.calendar').datepicker({ + todayHighlight: true, + language: 'ru' + }); + + //~fix DatePicker auto close + this.$el.find('.dropdown-toggle').on('click.bs.dropdown', function() { + var clicks = $(this).data('clicks'); + if (clicks) { + $(this).parent('.dropdown').off('hide.bs.dropdown'); + } else { + $(this).parent('.dropdown').on('hide.bs.dropdown', function () {return false;}); + } + $(this).data("clicks", !clicks); + }); + return this; + } }); +//####app/controls/application/statusBar/authentication/SignInSuccessView.js +jQuery(document).ready(function () { + if( InfinniUI.config.disableGetCurrentUser !== false ) { + InfinniUI.user = { + onReadyDeferred: $.Deferred(), + onReady: function(handler){ + this.onReadyDeferred.done(handler); + } + }; -_.extend(TabHeaderView.prototype, bindUIElementsMixin); + refreshUserInfo(); + } +}); -//####app/controls/tabPanel/tabPage/tabPageControl.js -/** - * - * @param parent - * @constructor - * @augments ContainerControl - */ -function TabPageControl(parent) { - _.superClass(TabPageControl, this, parent); +function getUserInfo(self){ + var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); + authProvider.getCurrentUser( + function (result) { + self.model.set('result', result); + }, + function (error) { + showObject('#signInInternalResult', error); + } + ); } -_.inherit(TabPageControl, ContainerControl); +function refreshUserInfo() { + var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); + authProvider.getCurrentUser( + function (result) { + InfinniUI.user.onReadyDeferred.resolve(result); + }, + function (error) { + InfinniUI.user .onReadyDeferred.resolve(null); + } + ); +} -_.extend(TabPageControl.prototype, /** @lends TabPageControl.prototype */ { +function changePassword() { + var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); + authProvider.changePassword( + $('#oldPassword').val(), + $('#newPassword').val(), + function (result) { + refreshUserInfo(); + }, + function (error) { + showObject('#changePasswordResult', error); + } + ); +} - createControlModel: function () { - return new TabPageModel(); - }, +function changeProfile() { + var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); - createControlView: function (model) { - return new TabPageView({model: model}); - } + authProvider.changeProfile( + $('#displayName').val(), + $('#description').val(), + function (result) { + refreshUserInfo(); + }, + function (error) { + showObject('#changeProfileResult', error); + } + ); +} +function changeActiveRole() { + var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); -}); + authProvider.changeActiveRole( + $('#activeRole').val(), + function (result) { + refreshUserInfo(); + }, + function (error) { + showObject('#сhangeActiveRoleResult', error); + } + ); +} +function getLinkExternalLoginForm() { + var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); -//####app/controls/tabPanel/tabPage/tabPageModel.js -/** - * @constructor - * @augments ContainerModel - */ -var TabPageModel = ContainerModel.extend(/** @lends TabPageModel.prototype */ { + authProvider.getLinkExternalLoginForm( + getAbsoluteUri('/Home/SignInSuccess'), + getAbsoluteUri('/Home/SignInFailure'), + function (result) { + $('#linkExternalLoginForm').append(result); + }, + function (error) { + showObject('#linkExternalLoginResult', error); + } + ); +} - initialize: function () { - ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - }, +function unlinkExternalLogin(provider, providerKey) { + var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); - defaults: _.defaults( - { - canClose: false, - selected: false + authProvider.unlinkExternalLogin( + provider, + providerKey, + function (result) { + refreshUserInfo(); }, - ContainerModel.prototype.defaults - ) - -}); -//####app/controls/tabPanel/tabPage/tabPageView.js -/** - * @class - * @augments ControlView - */ -var TabPageView = ContainerView.extend(/** @lends TabPageView.prototype */ { + function (error) { + showObject('#unlinkExternalLoginResult', error); + } + ); +} - className: 'pl-tabpage hidden', +function signOut(self) { + var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); - template: InfinniUI.Template["controls/tabPanel/tabPage/template/tabPage.tpl.html"], + onSuccessSignOut(getHomePageContext()); - UI: { + authProvider.signOut( + function (result) { - }, - initHandlersForProperties: function () { - ContainerView.prototype.initHandlersForProperties.call(this); - this.listenTo(this.model, 'change:selected', this.updateSelected); - }, + window.getCurrentUserName = function(){ + return null; + }; - updateProperties: function () { - ContainerView.prototype.updateProperties.call(this); - this.updateSelected(); - }, + //self.model.set('result', result); + self.model.set('result', null); + location.reload(); +// window.location = '/Home/SignIn'; + }, + function (error) { + showObject('#getCurrentUserResult', error.responseJSON); + } + ); +} - render: function () { - this.prerenderingActions(); +function setUserInfo(userInfo) { + //showObject('#getCurrentUserResult', userInfo); + //$('#displayName').val(userInfo.DisplayName); + //$('#description').val(userInfo.Description); + //$('#activeRole').val(userInfo.ActiveRole); - this.removeChildElements(); + if (userInfo.Logins !== null && userInfo.Logins !== undefined) { + var externalLogins = $('#externalLogins'); - this.$el.html(this.template({ - items: this.model.get('items') - })); - this.renderItemsContents(); + for (var i = 0; i < userInfo.Logins.length; ++i) { + var loginInfo = userInfo.Logins[i]; + var provider = loginInfo.Provider; + var providerKey = loginInfo.ProviderKey; - this.bindUIElements(); + var unlinkButton = $(document.createElement('input')); + unlinkButton.attr('type', 'button'); + unlinkButton.attr('value', provider); + unlinkButton.attr('onclick', 'unlinkExternalLogin(\'' + provider + '\', \'' + providerKey + '\')'); + externalLogins.append(unlinkButton); + } + } + getLinkExternalLoginForm(); +} - this.postrenderingActions(); +function getAbsoluteUri(relativeUri) { + return location.protocol + '//' + location.host + relativeUri; +} - this.trigger('render'); - this.updateProperties(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, +function showObject(element, object) { + var text = formatObject(object); + $(element).text(text); +} - renderItemsContents: function () { - var $items = this.$el.find('.pl-tabpage-i'), - items = this.model.get('items'), - itemTemplate = this.model.get('itemTemplate'), - that = this, - element, item; +function formatObject(object) { + return JSON.stringify(object, null, 4); +} - $items.each(function (i, el) { - item = items.getByIndex(i); - element = itemTemplate(undefined, {item: item, index: i}); - that.addChildElement(element); - $(el) - .append(element.render()); - }); - }, +//####app/controls/application/statusBar/authentication/SignInView.js +jQuery(document).ready(function () { + if( InfinniUI.config.disableSignInExternalForm !== false ) { + getSignInExternalForm(); + } +}); - updateSelected: function () { - var selected = this.model.get('selected'); - this.$el.toggleClass('hidden', !selected); - }, +function signInInternal(self) { + var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); + authProvider.signInInternal( + $('#userName').val(), + $('#password').val(), + $('#remember').is(':checked'), + function (result) { - /** - * @protected - */ - updateGrouping: function () { - } + window.getCurrentUserName = function(){ + return result.UserName; + }; -}); + self.model.set('result', result); + self.$modal.modal('hide'); + location.reload(); + }, + function (error) { + if(error.Error.indexOf('Invalid username or password') > -1){ + toastr.error('Неверный логин или пароль', "Ошибка!"); + } + showObject('#signInInternalResult', error); + } + ); +} -//####app/controls/treeView/treeViewControl.js -function TreeViewControl() { - _.superClass(TreeViewControl, this); +function getSignInExternalForm() { + var authProvider = new AuthenticationProvider(InfinniUI.config.serverUrl); + authProvider.getSignInExternalForm( + getAbsoluteUri('/Home/SignInSuccess'), + getAbsoluteUri('/Home/SignInFailure'), + function (result) { + $('#signInExternalForm').append(result); + }, + function (error) { + showObject('#signInExternalResult', error); + } + ); } -_.inherit(TreeViewControl, ListEditorBaseControl); +function getAbsoluteUri(relativeUri) { + return location.protocol + '//' + location.host + relativeUri; +} -_.extend(TreeViewControl.prototype, { +function showObject(element, object) { + var text = formatObject(object); + $(element).text(text); +} - createControlModel: function () { - return new TreeViewModel(); - }, +function formatObject(object) { + return JSON.stringify(object, null, 4); +} - createControlView: function (model) { - return new TreeViewView({model: model}); - } -}); +//####app/controls/application/statusBar/authentication/authenticationProvider.js +/** +  * Провайдер аутентификации. +  * +  * @constructor +  */ +function AuthenticationProvider(baseAddress) { + this.baseAddress = baseAddress; +} -//####app/controls/treeView/treeViewModel.js -var TreeViewModel = ListEditorBaseModel.extend({ +_.extend(AuthenticationProvider.prototype, { + handlers: { + onActiveRoleChanged: $.Callbacks(), + onSignInInternal: $.Callbacks(), + onSignOut: $.Callbacks() + }, - initialize: function () { - ListEditorBaseModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + /** +      * Возвращает информацию о текущем пользователе. +      * +      * @public +      */ + getCurrentUser: function(resultCallback, errorCallback) { + this.sendPostRequestForServiceResult('/Auth/GetCurrentUser', {}, resultCallback, errorCallback); }, - toggleItem: function (item, toggle) { - var value = this.valueByItem(item); - this.toggleValue(value, toggle); - this.trigger('toggle'); - } -}); -//####app/controls/treeView/treeViewView.js -var TreeViewView = ListEditorBaseView.extend({ + /** +      * Изменяет пароль текущего пользователя. +      * +      * @public +      */ + changePassword: function (oldPassword, newPassword, resultCallback, errorCallback) { + var changePasswordForm = { + OldPassword: oldPassword, + NewPassword: newPassword + }; - className: 'pl-treeview', - classNameMultiSelect: 'pl-treeview_multi-select', - classNameSingleSelect: 'pl-treeview_single-select', + this.sendPostRequestForServiceResult('/Auth/ChangePassword', changePasswordForm, resultCallback, errorCallback); + }, - template: InfinniUI.Template["controls/treeView/template/treeview.tpl.html"], + /** +      * Изменяет персональную информацию текущего пользователя. +      * +      * @public +      */ + changeProfile: function (displayName, description, resultCallback, errorCallback) { + var changeProfileForm = { + DisplayName: displayName, + Description: description + }; - events: {}, + this.sendPostRequestForServiceResult('/Auth/ChangeProfile', changeProfileForm, resultCallback, errorCallback); + }, - UI: _.defaults({}, ListEditorBaseView.prototype.UI), + /** +      * Изменяет активную роль текущего пользователя. +      * +      * @public +      */ + changeActiveRole: function (activeRole, resultCallback, errorCallback) { + var changeActiveRoleForm = { + ActiveRole: activeRole + }; - initialize: function (options) { - ListEditorBaseView.prototype.initialize.call(this, options); - this.ItemsMap = new HashMap(); + this.sendPostRequestForServiceResult('/Auth/ChangeActiveRole', changeActiveRoleForm, function(){ + var args = _.toArray(arguments); + args.push(activeRole); + if(resultCallback){ + resultCallback.apply(this, args); + } + this.handlers.onActiveRoleChanged.fire.apply(this.handlers.onActiveRoleChanged, args); + }, errorCallback); }, - render: function () { - this.prerenderingActions(); - - this.renderTemplate(this.getTemplate()); - - this.renderItems(); - this.updateProperties(); + /** +      * Осуществляет вход пользователя в систему через внутренний провайдер. +      * +      * @public +      */ + signInInternal: function (userName, password, remember, resultCallback, errorCallback) { + var signInInternalForm = { + UserName: userName, + Password: password, + Remember: remember + }; - this.trigger('render'); + this.sendPostRequestForServiceResult('/Auth/SignInInternal', signInInternalForm, resultCallback, errorCallback); + }, - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; + /** +      * Возвращает форму входа пользователя в систему через внешний провайдер. +      * +      * @public +      */ + getSignInExternalForm: function (successUrl, failureUrl, resultCallback, errorCallback) { + this.getExternalLoginForm('/Auth/SignInExternal', successUrl, failureUrl, resultCallback, errorCallback); }, - renderItems: function (parentId) { - var - view = this, - $nodes, - model = this.model, - collection = model.get('items'), - parentSelector = model.get('parentSelector'), - keySelector = model.get('keySelector'), - nodeConstructor = this.getNodeConstructor(), - itemTemplate = model.get('itemTemplate'), - itemsMap = this.ItemsMap; + /** +      * Возвращает форму добавления текущему пользователю имени входа у внешнего провайдера. +      * +      * @public +      */ + getLinkExternalLoginForm: function (successUrl, failureUrl, resultCallback, errorCallback) { + this.getExternalLoginForm('/Auth/LinkExternalLogin', successUrl, failureUrl, resultCallback, errorCallback); + }, - itemsMap.clear(); + /** +      * Удаляет у текущего пользователя имя входа у внешнего провайдера. +      * +      * @public +      */ + unlinkExternalLogin: function (provider, providerKey, resultCallback, errorCallback) { + var unlinkExternalLoginForm = { + Provider: provider, + ProviderKey: providerKey + }; - $nodes = renderNodes(); - this.$el.append($nodes); + this.sendPostRequest('/Auth/UnlinkExternalLogin', unlinkExternalLoginForm, resultCallback, errorCallback); + }, - function renderNodes (parentId) { - return collection.toArray() - .filter(function (item) { - var parent = parentSelector(null, {value: item}); - return isEmpty(parentId) ? isEmpty(parent) : parent === parentId; - }) - .map(function (item) { - var node = new nodeConstructor().render(); - var $node = node.$el; - var $item = itemTemplate(null, { - value: item, - index: collection.indexOf(item) - }).render(); + /** +      * Выход пользователя из системы. +      * +      * @public +      */ + signOut: function (resultCallback, errorCallback) { + var signOutInternalForm = { + "id" : null, + "changesObject" : {}, + "replace" : false + }; - $node.data('pl-data-item', item); + this.sendPostRequestForServiceResult('/Auth/SignOut', null, function(){ + InfinniUI.user.onReadyDeferred = $.Deferred(); + InfinniUI.user.onReadyDeferred.resolve(null); - node.listenTo(model, 'change:selectedItem', function (model, selectedItem) { - node.setSelected(selectedItem === item); - }); + var args = _.toArray(arguments); + if(resultCallback){ + resultCallback.apply(this, args); + } - node.listenTo(model, 'change:value', function (model, value) { - var multiSelect = model.get('multiSelect'); + this.handlers.onSignOut.fire.apply(this.handlers.onSignOut, args); - var checked; - if (!multiSelect) { - checked = isValueForItem(value); - } else if (Array.isArray(value)) { - checked = value.some(isValueForItem) - } else { - checked = false; - } - node.setChecked(checked); - }); + }.bind(this), errorCallback); + }, - view.listenTo(node, 'select', view.onSelectNodeHandler.bind(view, item, node)); - view.listenTo(node, 'check', view.onCheckNodeHandler.bind(view, item, node)); + getExternalLoginForm: function (requestUri, successUrl, failureUrl, resultCallback, errorCallback) { + var url = this.baseAddress + requestUri; + this.sendPostRequest('/Auth/GetExternalProviders', {}, + function (result) { + var formElement = $(document.createElement('form')); + formElement.attr('method', 'POST'); + formElement.attr('action', url); - node.setItemContent($item); - var key = keySelector(null, {value: item}), - $subitems = renderNodes(key); - node.setItemsContent($subitems); + var successUrlElement = $(document.createElement('input')); + successUrlElement.attr('type', 'hidden'); + successUrlElement.attr('name', 'SuccessUrl'); + successUrlElement.attr('value', successUrl); + formElement.append(successUrlElement); - itemsMap.add(key, item); + var failureUrlElement = $(document.createElement('input')); + failureUrlElement.attr('type', 'hidden'); + failureUrlElement.attr('name', 'FailureUrl'); + failureUrlElement.attr('value', failureUrl); + formElement.append(failureUrlElement); - return $node; + if (result !== null && result !== undefined) { + for (var i = 0; i < result.length; ++i) { + var providerInfo = result[i]; + var providerType = providerInfo.Type; + var providerName = providerInfo.Name; - function isValueForItem(value) { - return model.itemByValue(value) === item; + var loginButton = $(document.createElement('button')); + loginButton.attr('type', 'submit'); + loginButton.attr('name', 'Provider'); + loginButton.attr('value', providerType); + loginButton.text(providerName); + formElement.append(loginButton); } - }); - } + } - function isEmpty(value) { - return value === null || typeof value === 'undefined'; - } + resultCallback(formElement); + }, + errorCallback + ); }, - getNodeConstructor: function () { - var multiSelect = this.model.get('multiSelect'); - - return (multiSelect === true) ? TreeViewNodeCheckbox : TreeViewNodeRadio; + sendGetRequest: function (requestUri, resultCallback, errorCallback) { + $.ajax(this.baseAddress + requestUri, { + type: 'GET', + xhrFields: { + withCredentials: true + }, + beforeSend: this.onBeforeRequest(), + success: this.onSuccessRequest(resultCallback), + error: this.onErrorRequest(function (error) { + if(errorCallback) { + errorCallback(error.responseJSON); + } + }) + }); }, - onSelectNodeHandler: function(item , index) { - var model = this.model; - - var multiSelect = model.get('multiSelect'); + sendPostRequest: function (requestUri, requestData, resultCallback, errorCallback) { + var that = this; - model.set('selectedItem', item); - if (!multiSelect) { - //Клик по элементу одновременно переключает значение и делает элемент выделенным - this.tryToggleValue(item); + if (requestData !== null) { + requestData = JSON.stringify(requestData); } + $.ajax(this.baseAddress + requestUri, { + type: 'POST', + xhrFields: { + withCredentials: true + }, + data: requestData, + contentType: 'application/json', + beforeSend: this.onBeforeRequest(), + success: this.onSuccessRequest(resultCallback), + error: this.onErrorRequest(function (error) { + if(error.status != 200) { + if(errorCallback) { + errorCallback(error.responseJSON); + } + } else { + that.onSuccessRequest(resultCallback).apply(that, arguments); + } + }) + }); }, - onCheckNodeHandler: function (item, index) { - var model = this.model; + sendPostRequestForServiceResult: function (requestUri, requestData, successCallback, errorCallback) { + var resultCallback = function(){ + var args = _.toArray(arguments), + serviceResult = args[0]; + + if(serviceResult['Success']){ + args[0] = serviceResult['Result']; - var multiSelect = model.get('multiSelect'); + if( _.isFunction(successCallback) ){ + successCallback.apply(this, args); + } + } else { + args[0] = serviceResult['Error']; - this.tryToggleValue(item); + if( _.isFunction(errorCallback) ){ + errorCallback.apply(this, args); + } + } + }; - if (!multiSelect) { - //Клик по элементу одновременно переключает значение и делает элемент выделенным - model.set('selectedItem', item); - } + this.sendPostRequest(requestUri, requestData, resultCallback, errorCallback); }, - tryToggleValue: function(item){ - var model = this.model; - var isDisabledItem = this.isDisabledItem(item); + onActiveRoleChanged: function(handler){ + this.handlers.onActiveRoleChanged.add(handler); + }, - if(!isDisabledItem){ - var value = model.valueByItem(item); - model.toggleValue(value); - } + onSignInInternal: function(handler){ + this.handlers.onSignInInternal.add(handler); }, - isDisabledItem: function(item){ - if(item == null){ - return false; - } + onSignOut: function(handler){ + this.handlers.onSignOut.add(handler); + } +}); - return this.model.isDisabledItem(item) || this.isDisabledItem(this.getParent(item)); - }, +_.extend(AuthenticationProvider.prototype, ajaxRequestMixin); + +InfinniUI.global.session = new AuthenticationProvider(InfinniUI.config.serverUrl); +//####app/controls/button/commonView/buttonView.js +/** + * @class ButtonView + * @augments ControlView + */ +var CommonButtonView = ControlView.extend({ - getParent: function(item){ - var parentSelector = this.model.get('parentSelector'), - parentId = parentSelector(null, {value: item}); + className: 'pl-button', - return parentId && this.ItemsMap.get(parentId); - }, + template: InfinniUI.Template["controls/button/commonView/template/button.tpl.html"], - getTemplate: function () { - return this.template; + UI: { + button: 'button' }, - updateProperties: function () { - ListEditorBaseView.prototype.updateProperties.call(this); - this.updateMultiSelect(); + events: { + 'click button': 'onClickHandler' }, - updateMultiSelect: function () { - var multiSelect = this.model.get('multiSelect'); - this.$el.toggleClass(this.classNameMultiSelect, !!multiSelect); - this.$el.toggleClass(this.classNameSingleSelect, !multiSelect); + initialize: function () { + ControlView.prototype.initialize.apply(this, arguments); + this.initHighlightMixin(); }, - updateEnabled: function () { - ListEditorBaseView.prototype.updateEnabled.call(this); - - var enabled = this.model.get('enabled'); + updateProperties: function(){ + ControlView.prototype.updateProperties.call(this); + this.updateContent(); + this.updateType(); }, - updateValue: function () { - + updateType: function() { + var type = this.model.get('type'); + this.getButtonElement().attr('type', type); }, - updateSelectedItem: function () { + updateContent: function(){ + var contentTemplate = this.model.get('contentTemplate'); + var content = this.model.get('content'); + var args = { + content: content + }; + var contentElement; + var $button = this.getButtonElement(); - }, + if(contentTemplate){ + contentElement = contentTemplate(null, args); + $button.html(contentElement.render()); - updateGrouping: function () { + }else if(content !== undefined && content !== null){ + $button.html(content); + } }, - updateDisabledItem: function() { - var model = this.model; - var disabledItemCondition = model.get('disabledItemCondition'); - var nodes = this.$el.find('.pl-treeview-node'); + updateText: function(){ + var textForButton = this.model.get('text'); + var $button = this.getButtonElement(); - nodes.removeClass('pl-disabled-list-item'); + if($button) { + $button.html(textForButton); + } + }, - if( disabledItemCondition != null){ - nodes.each(function(i, el){ - var $el = $(el), - item = $el.data('pl-data-item'); + updateFocusable: function () { + var focusable = this.model.get('focusable'); - if(model.isDisabledItem(item)){ - $el.addClass('pl-disabled-list-item'); - } - }); + if (!focusable) { + this.getButtonElement().attr('tabindex', -1); + } else { + this.getButtonElement().removeAttr('tabindex'); } }, - rerender: function () { + updateEnabled: function(){ + ControlView.prototype.updateEnabled.call(this); - } + var isEnabled = this.model.get('enabled'); + this.getButtonElement().prop('disabled', !isEnabled); + }, + updateBackground: function () { + var customStyle = this.model.get('background'); -}); + if (this.currentBackground) { + this.getButtonElement() + .removeClass(this.valueToBackgroundClassName(this.currentBackground)); + } -//####app/controls/treeView/node/treeViewNodeBase.js -var TreeViewNodeBase = Backbone.View.extend({ + if (customStyle) { + this.getButtonElement() + .addClass(this.valueToBackgroundClassName(customStyle)); + } - className: 'pl-treeview-node', + this.currentBackground = customStyle; + }, - classNameCheckerChecked: 'pl-treeview-item__checker_checked', - classNameContentSelected: 'pl-treeview-item__content_selected', - classNameItemsExpanded: 'pl-treeview-node__items_expanded', - classNameItemsCollapsed: 'pl-treeview-node__items_collapsed', - classNameButtonCollapse: 'pl-treeview-node__button_collapse', - classNameButtonExpand: 'pl-treeview-node__button_expand', + render: function () { + this.prerenderingActions(); - UI: { - checker: '.pl-treeview-item__checker', - content: '.pl-treeview-item__content', - items: '.pl-treeview-node__items', - button: '.pl-treeview-node__button' - }, + this.renderTemplate(this.template); + this.updateProperties(); + this.trigger('render'); - initialize: function () { - var model = new Backbone.Model({collapsed: true}); - this.model = model; - this.listenTo(model, 'change:selected', this.updateSelected); - this.listenTo(model, 'change:checked', this.updateChecked); - this.listenTo(model, 'change:collapsed', this.updateCollapsed); + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; }, - updateChecked: function () { - var checked = this.model.get('checked'); - this.ui.checker.toggleClass(this.classNameCheckerChecked, checked === true); + getButtonElement: function(){ + return this.ui.button; }, - updateSelected: function () { - var selected = this.model.get('selected'); - this.ui.content.toggleClass(this.classNameContentSelected, selected === true); - }, + setFocus: function () { + this.getButtonElement().focus(); + } - updateCollapsed: function () { - var collapsed = !!this.model.get('collapsed'); - this.ui.items.toggleClass(this.classNameItemsExpanded, !collapsed); - this.ui.items.toggleClass(this.classNameItemsCollapsed, collapsed); - this.ui.button.toggleClass(this.classNameButtonCollapse, !collapsed); - this.ui.button.toggleClass(this.classNameButtonExpand, collapsed); - }, - updateState: function () { - this.updateCollapsed(); - this.updateSelected(); - this.updateChecked(); - }, - render: function () { - this.$el.html(this.template); - this.bindUIElements(); - this.updateState(); - this.initDomEventsHandlers(); - return this; - }, +}); - initDomEventsHandlers: function () { - this.ui.button.on('click', this.onClickEventHandler.bind(this)); - this.ui.content[0].addEventListener('click', this.onClickItemHandler.bind(this), true); - this.ui.checker[0].addEventListener('click', this.onClickCheckHandler.bind(this), true); - }, +_.extend(CommonButtonView.prototype, highlightMixin.controlView); - onClickItemHandler: function (event) { - this.trigger('select'); - }, - onClickCheckHandler: function (event) { - this.trigger('check'); - }, +InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.Button.common', CommonButtonView); + +//####app/controls/button/linkView/buttonView.js +/** + * @class ButtonView + * @augments ControlView + */ +var LinkButtonView = CommonButtonView.extend({ - toggle: function () { - var model = this.model; - var collapsed = model.get('collapsed'); + tagName: 'a', - this.model.set('collapsed', !collapsed); - }, + className: 'pl-button', - setItemContent: function ($itemContent) { - this.ui.content.empty(); - this.ui.content.append($itemContent); + attributes: { + href: 'javascript:;' }, - setItemsContent: function ($itemsContent) { - this.ui.items.empty(); - this.ui.items.append($itemsContent); + events: { + 'click': 'onClickHandler' }, - onClickEventHandler: function (event) { - this.toggle(); - }, + template: function(){return '';}, - setSelected: function (selected) { - this.model.set('selected', selected); + UI: { }, - setChecked: function (checked) { - this.model.set('checked', checked); + getButtonElement: function(){ + return this.$el; } -}); - -_.extend(TreeViewNodeBase.prototype, bindUIElementsMixin); -//####app/controls/treeView/node/treeViewNodeCheckbox.js -var TreeViewNodeCheckbox = TreeViewNodeBase.extend({ - - template: InfinniUI.Template["controls/treeView/template/node-checkbox.tpl.html"] - -}); -//####app/controls/treeView/node/treeViewNodeRadio.js -var TreeViewNodeRadio = TreeViewNodeBase.extend({ - - template: InfinniUI.Template["controls/treeView/template/node-radio.tpl.html"] }); -//####app/controls/checkBox/checkBoxControl.js -function CheckBoxControl(parent) { - _.superClass(CheckBoxControl, this, parent); - this.initialize_editorBaseControl(); -} - -_.inherit(CheckBoxControl, Control); +InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.Button.link', LinkButtonView); -_.extend(CheckBoxControl.prototype, { +//####app/controls/button/buttonControl.js +/** + * + * @param parent + * @constructor + * @augments Control + */ +function ButtonControl(viewMode) { + _.superClass(ButtonControl, this, viewMode); +} + +_.inherit(ButtonControl, Control); + +_.extend( + ButtonControl.prototype, + highlightMixin.control, { + + createControlModel: function () { + return new ButtonModel(); + }, + + createControlView: function (model, viewMode) { + if (!viewMode || !viewMode in window.InfinniUI.viewModes.Button) { + viewMode = 'common'; + } + + var ViewClass = window.InfinniUI.viewModes.Button[viewMode]; + + return new ViewClass({model: model}); + }, + + setType: function(type) { + this.controlModel.set('type', type); + }, + + getType: function() { + return this.controlModel.get('type'); + } + + }, buttonControlMixin); + - createControlModel: function () { - return new CheckBoxModel(); - }, +//####app/controls/button/buttonModel.js +/** + * @class + * @augments ControlModel + */ +var ButtonModel = ControlModel.extend({ + + defaults: _.defaults({ + content: null, + contentTemplate: null, + horizontalAlignment: 'Left', + type: 'button' + }, ControlModel.prototype.defaults), + + initialize: function () { + ControlModel.prototype.initialize.apply(this, arguments); + } + +}); - createControlView: function (model) { - return new CheckBoxView({model: model}); - } -}, editorBaseControlMixin); +//####app/controls/button/menuItemView/buttonView.js +/** + * @class ButtonView + * @augments ControlView + */ +var MenuItemButtonView = LinkButtonView.extend({ + updateHorizontalAlignment: function(){ + var horizontalAlignment = this.model.get('horizontalAlignment'); + var that = this; + var $el; -//####app/controls/checkBox/checkBoxModel.js -var CheckBoxModel = ControlModel.extend( _.extend({ + domHelper.whenReady( + function(){ + $el = that.$el.parent().parent(); + return $el.length > 0; + }, - defaults: _.defaults({ - value: false - }, ControlModel.prototype.defaults), + function(){ + if(horizontalAlignment == 'Right'){ + $el + .addClass('pull-right'); + }else{ + $el + .removeClass('pull-right'); + } + } + ); - initialize: function () { - ControlModel.prototype.initialize.apply(this, arguments); - this.initialize_editorBaseModel(); } -}, editorBaseModelMixin)); -//####app/controls/checkBox/checkBoxView.js -/** - * @class CheckBoxView - * @augments ControlView - * @mixes editorBaseViewMixin - */ -var CheckBoxView = ControlView.extend(/** @lends CheckBoxView.prototype */ _.extend({}, editorBaseViewMixin, { +}); - template: InfinniUI.Template["controls/checkBox/template/checkBox.tpl.html"], +InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.Button.menuItem', MenuItemButtonView); +//####app/controls/buttonEdit/buttonEditControl.js +/** + * + * @param parent + * @constructor + * @augments TextBoxControl + */ +function ButtonEditControl(parent) { + _.superClass(ButtonEditControl, this, parent); +} + +_.inherit(ButtonEditControl, TextBoxControl); + +_.extend(ButtonEditControl.prototype, { + + createControlModel: function () { + return new ButtonEditModel(); + }, + + createControlView: function (model) { + return new ButtonEditView({model: model}); + }, + + onButtonClick: function (handler) { + this.controlView.on('buttonClick', handler); + } +}); + - UI: _.extend({}, editorBaseViewMixin.UI, { - text: '.checkbox-label', - input: 'input' - }), +//####app/controls/buttonEdit/buttonEditModel.js +var ButtonEditModel = TextBoxModel.extend({ + + defaults: _.defaults({ + showClear: true, + readOnly: true + }, TextBoxModel.prototype.defaults), + + initialize: function () { + TextBoxModel.prototype.initialize.apply(this, arguments); + }, + + clearValue: function () { + var enabled = this.get('enabled'); + + if (enabled) { + this.set('value', null); + } + } + +}); +//####app/controls/buttonEdit/buttonEditView.js +var ButtonEditView = TextBoxView.extend(/** @lends ButtonEditView.prototype */{ + + template: { + oneline: InfinniUI.Template["controls/buttonEdit/template/textBoxInput.tpl.html"], + multiline: InfinniUI.Template["controls/buttonEdit/template/textBoxArea.tpl.html"] + }, + + className: 'pl-button-edit form-group', + + UI: _.extend({}, TextBoxView.prototype.UI, { + iconAction: '.pl-button-edit-button__icon_action', + buttonClear: '.pl-button-edit-button_clear', + buttons: '.pl-button-edit-button' + }), + + events: _.extend({}, TextBoxView.prototype.events, { + 'click .pl-button-edit-button_action': 'onClickButtonHandler', + 'click .pl-button-edit-button_clear': 'onClickClearHandler' + }), + + initHandlersForProperties: function () { + TextBoxView.prototype.initHandlersForProperties.call(this); + this.listenTo(this.model, 'change:icon', this.updateIcon); + this.listenTo(this.model, 'change:showClear', this.updateShowClear); + this.listenTo(this.model, 'change:readOnly', this.updateReadOnly); + }, + + updateProperties: function () { + TextBoxView.prototype.updateProperties.call(this); + this.updateIcon(); + this.updateShowClear(); + this.updateReadOnly(); + }, + + updateIcon: function () { + var icon = this.model.get('icon'); + this.switchClass('fa', icon, this.ui.iconAction); + }, + + updateShowClear: function () { + var showClear = this.model.get('showClear'); + var value = this.model.get('value'); + + this.ui.buttonClear.toggleClass('hidden', !showClear || _.isEmpty(value)); + }, + + updateReadOnly: function () { + var readOnly = this.model.get('readOnly'); + + this.ui.control.prop('readonly', readOnly); + }, + + updateEnabled: function () { + var enabled = this.model.get('enabled'); + TextBoxView.prototype.updateEnabled.call(this); + + //@TODO Update button states + this.ui.buttons.toggleClass('pl-button-edit-button_disabled', !enabled); + }, + + updateValue: function () { + TextBoxView.prototype.updateValue.call(this); + this.updateShowClear(); + }, + + onClickButtonHandler: function (event) { + var enabled = this.model.get('enabled'); + + if (enabled) { + this.trigger('buttonClick', event); + } + }, + + onClickClearHandler: function (event) { + this.model.clearValue(); + } + +}); +//####app/controls/comboBox/dropdown/comboBoxDropdownView.js +var ComboBoxDropdownView = Backbone.View.extend({ + className: "pl-dropdown-container", events: { - 'click input': 'onClickHandler' - }, - - initHandlersForProperties: function(){ - ControlView.prototype.initHandlersForProperties.call(this); - editorBaseViewMixin.initHandlersForProperties.call(this); + 'click .backdrop': 'onClickBackdropHandler', + 'keyup .pl-combobox-filter-text': 'onKeyUpHandler', + 'keydown .pl-combobox-filter-text': 'onFilterKeyDownHandler' }, - updateProperties: function(){ - ControlView.prototype.updateProperties.call(this); - editorBaseViewMixin.updateProperties.call(this); + UI: { + items: '.pl-combobox-items', + filter: '.pl-combobox-filter', + text: '.pl-combobox-filter-text', + noItems: '.pl-combobox-items-empty', + search: '.pl-combobox-items-empty > span' }, - updateFocusable: function () { - var focusable = this.model.get('focusable'); + initialize: function () { + var isGrouped = this.model.get('groupValueSelector') != null; - if (!focusable) { - this.ui.input.attr('tabindex', -1); + if (isGrouped) { + this.strategy = new ComboBoxGroupViewStrategy(this); } else { - this.ui.input.removeAttr('tabindex'); + this.strategy = new ComboBoxPlainViewStrategy(this); } - }, - updateText: function () { - var text = this.model.get('text'); + this.listenTo(this.model, 'change:dropdown', this.onChangeDropdownHandler); + this.listenTo(this.model, 'change:autocompleteValue', this.onChangeSearchHandler); + this.listenTo(this.model, 'change:autocomplete', this.updateAutocomplete); + this.listenTo(this.model, 'change:selectedItem', this.onChangeSelectedItem); + this.listenTo(this.strategy, 'click', this.onClickItemHandler); + this.listenTo(this.strategy, 'mouseenter', this.onMouseEnterItemHandler); + this.model.onValueChanged(this.onChangeValueHandler.bind(this)); - this.ui.text.text(text ? text : ''); + var items = this.model.get('items'); + + var view = this; + items.onChange(function () { + view.renderItems(); + }); }, - updateEnabled: function () { - ControlView.prototype.updateEnabled.call(this); - var enabled = this.model.get('enabled'); - this.ui.input.prop('disabled', !enabled); + updateProperties: function () { + this.updateAutocomplete(); }, render: function () { - this.prerenderingActions(); - this.renderTemplate(this.template); + var template = this.strategy.getTemplate(); + this.$el.html(template({ + multiSelect: this.model.get('multiSelect') + })); + this.bindUIElements(); this.updateProperties(); - - this.trigger('render'); - this.postrenderingActions(); + this.renderItems(); //devblockstart window.InfinniUI.global.messageBus.send('render', {element: this}); //devblockstop - return this; + return this.$el; }, - onClickHandler: function () { - var model = this.model; + renderItems: function () { + this.$el.hide(); + var $items = this.strategy.renderItems(); + this.$items = $items; + var items = this.model.get('items'); - var enabled = model.get('enabled'); - if (enabled) { - model.set('value', !model.get('value')); - } - }, + var noItems = (items && items.length == 0); + this.ui.noItems.toggleClass('hidden', !noItems); - updateValue: function () { - var value = this.model.get('value'); - this.ui.input.prop('checked', !!value); + this.markSelectedItems(); + this.markCheckedItems(); + + this.trigger('itemsRendered2'); + this.$el.show(); }, - setFocus: function () { - this.ui.input.focus(); - } -})); + setItemsContent: function (content) { + var $items = this.ui.items; + $items.empty(); + $items.append(content); + }, -//####app/controls/comboBox/comboBoxControl.js -function ComboBoxControl(viewMode) { - _.superClass(ListBoxControl, this, viewMode); -} + close: function () { + this.model.set('dropdown', false); + }, -_.inherit(ComboBoxControl, ListEditorBaseControl); + setSearchFocus: function () { + this.ui.text.focus(); + }, -_.extend(ComboBoxControl.prototype, { + onClickBackdropHandler: function () { + this.close(); + }, - createControlModel: function () { - return new ComboBoxModel(); + onChangeValueHandler: function () { + this.markCheckedItems(); }, - createControlView: function (model) { - return new ComboBoxView({model: model}); - } -}); + markSelectedItems: function () { + var model = this.model; + if (!Array.isArray(this.$items)) { + return; + } + var $container = this.ui.items; + var $items = this.$items; + var selectedItem = model.getSelectedItem(); -//####app/controls/comboBox/comboBoxModel.js -var ComboBoxModel = ListEditorBaseModel.extend({ + $items.forEach(function ($item) { + var selected = selectedItem === $item.data('pl-data-item'); + $item.toggleClass('pl-combobox-selected', selected); + }); - defaults: _.defaults({ - showClear: true, - autocomplete: false, - autocompleteValue: '', - valueTemplate: function(context, args){ - return { - render: function(){ - return args.value; - } - }; - } - }, ListEditorBaseModel.prototype.defaults), + this.ensureVisibleSelectedItem(); - initialize: function () { - ListEditorBaseModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - this.on('change:value', this.syncSelectedItem); }, - setSelectedItemToValue: function () { - var autocomplete = this.get('autocomplete'); - var multiSelect = this.get('multiSelect'); + ensureVisibleSelectedItem: function () { + var model = this.model; + if (!Array.isArray(this.$items)) { + return; + } + + var $container = this.ui.items; + var $items = this.$items; + var selectedItem = model.getSelectedItem(); + + $items.some(function ($item) { + var selected = selectedItem === $item.data('pl-data-item'); + if (selected) { + ensureItem($container, $item); + } + return selected; + }); + + function ensureItem($container, $item) { + var newScrollTop; + + var scrollTop = $container.scrollTop(); + var itemTop = $item.position().top; + var itemHeight = $item.outerHeight(); + var viewHeight = $container.innerHeight(); + if (itemTop + itemHeight > viewHeight) { + newScrollTop = scrollTop + itemTop + itemHeight - viewHeight; + } else if (itemTop < 0) { + newScrollTop = scrollTop + itemTop; + } - if (autocomplete || multiSelect) { - return; + if (typeof newScrollTop !== 'undefined') { + $container.scrollTop(newScrollTop); + } } - - var selectedItem = this.getSelectedItem(); - var value = this.valueByItem(selectedItem); - this.set('value', value); - - }, - - syncSelectedItem: function (model, value) { - //var value = this.getValue(); - var selectedItem = this.itemByValue(value); - this.setSelectedItem(selectedItem); }, - getSelectedItem: function () { - var selectedItem = this.get('selectedItem'); - return selectedItem; - }, + markCheckedItems: function () { + var model = this.model; + var value = model.getValue(); - setSelectedItem: function (item) { - this.set('selectedItem', item); - }, + if (!Array.isArray(this.$items)) { + return; + } - selectNextItem: function () { - var items = this.get('items'); - var selectedItem = this.getSelectedItem(); + var $items = this.$items; + var isMultiSelect = !!model.get('multiSelect'); + var items = []; - if (items.length > 0) { - var itemIndex = 0; - if (selectedItem) { - itemIndex = items.indexOf(selectedItem); - if (itemIndex === -1) { - itemIndex = 0; - } else { - itemIndex = Math.min(items.length - 1, itemIndex + 1); - } - } - selectedItem = items.getByIndex(itemIndex); + if (isMultiSelect && Array.isArray(value)) { + items = value.map(function (val) { + return model.itemByValue(val); + }); } else { - selectedItem = null; + items = [model.itemByValue(value)]; } - this.setSelectedItem(selectedItem); - this.setSelectedItemToValue(); - }, - selectPrevItem: function () { - var items = this.get('items'); - var selectedItem = this.getSelectedItem(); + $items.forEach(function ($item) { + var selected = items.indexOf($item.data('pl-data-item')) !== -1; + $item.toggleClass('pl-combobox-checked', selected); + }); + }, - if (items.length > 0) { - var itemIndex = 0; - if (selectedItem) { - itemIndex = items.indexOf(selectedItem); - if (itemIndex === -1) { - itemIndex = 0; - } else { - itemIndex = Math.max(0, itemIndex - 1); - } - } - selectedItem = items.getByIndex(itemIndex); + onChangeDropdownHandler: function (model, dropdown) { + if (!dropdown) { + this.remove(); } - this.setSelectedItem(selectedItem); - this.setSelectedItemToValue(); }, - selectFirstItem: function () { - var items = this.get('items'); - var selectedItem = null; - - if (items.length > 0) { - selectedItem = items.getByIndex(0); - } - this.setSelectedItem(selectedItem); - this.setSelectedItemToValue(); + updateAutocomplete: function () { + var autocomplete = this.model.get('autocomplete'); + this.ui.filter.toggleClass('hidden', !autocomplete); }, - selectLastItem: function () { - var items = this.get('items'); - var selectedItem = null; + onMouseEnterItemHandler: function (item) { + this.model.setSelectedItem(item); + }, - if (items.length > 0) { - selectedItem = items.getByIndex(items.length - 1); + onClickItemHandler: function (item) { + var isEnabled = !this.model.isDisabledItem(item); + if(isEnabled) { + this.model.toggleItem(item); + this.close(); } - this.setSelectedItem(selectedItem); - this.setSelectedItemToValue(); }, - toggleItem: function (item, toggle) { - var value = this.valueByItem(item); - this.toggleValue(value, toggle); - this.trigger('toggle'); - } -}); -//####app/controls/comboBox/comboBoxView.js -var ComboBoxView = ListEditorBaseView.extend({ - - className: 'pl-combobox form-group', - - template: InfinniUI.Template["controls/comboBox/template/combobox.tpl.html"], - - events: { - 'click .pl-combobox__grip': 'onClickGripHandler', - 'click .pl-combobox__value': 'onClickValueHandler', - 'click .pl-combobox__clear': 'onClickClearHandler', - 'click .pl-control': 'onClickValueHandler', - 'keydown .pl-control': 'onKeyDownControlHandler' + onKeyUpHandler: function (event) { + //@TODO grow input + var text = this.ui.text.val(); + this.trigger('search', text); }, - UI: _.defaults({ - control: '.pl-control', - label: '.pl-control-label', - value: '.pl-combobox__value', - clear: '.pl-combobox__clear' - }, ListEditorBaseView.prototype.UI), - - isControlElement: function (el) { - var res = ListEditorBaseView.prototype.isControlElement.call(this, el); - - if (res) { - return res; - } + onKeyDownHandler: function (event) { + var model = this.model; + event.preventDefault(); + this.onFilterKeyDownHandler(event); + }, - if (!this.dropDownView) { - return false; + onFilterKeyDownHandler: function (event) { + var model = this.model; + switch (event.which) { + case 36://Home; + model.selectFirstItem(); + break; + case 35: //End + model.selectLastItem(); + break; + case 38: //Up + model.selectPrevItem(); + break; + case 40: //Down + model.selectNextItem(); + break; + case 13: + this.onClickItemHandler(model.getSelectedItem()); + break; + case 9: + this.close(); + break; + case 27://Escape + this.close(); + event.stopPropagation(); + break; } - - return $.contains(this.dropDownView.el, el); }, - updateFocusable: function () { - var focusable = this.model.get('focusable'); - var enabled = this.model.get('enabled'); + onChangeSearchHandler: function (model, value) { + this.ui.search.text(value); + }, - if (focusable && enabled) { - this.ui.control.attr('tabindex', 0); - } else { - this.ui.control.removeAttr('tabindex'); - } + onChangeSelectedItem: function (model, value) { + this.markSelectedItems(); }, - initialize: function (options) { - ListEditorBaseView.prototype.initialize.call(this, options); - var model = this.model, - view = this; + updatePosition: function (parentDOMElement) { + var direction = this.getDropdownDirection(parentDOMElement); + this.setPositionFor(parentDOMElement, direction ); + }, - //this.on('beforeClick', this.activateControl); + setPositionFor: function (parentDOMElement, direction) { + clearInterval(this._intervalId); - this.on('render', function () { - view.renderValue(); + this.applyStyle(parentDOMElement, direction); + this._intervalId = setInterval(this.applyStyle.bind(this, parentDOMElement, direction), 100); + }, - model.on('change:dropdown', function (model, dropdown) { - if (dropdown) { - model.set('autocompleteValue', '');//Сброс фильтра - model.set('focused', true); - if (view.dropDownView) { - view.dropDownView.remove(); - } - var dropdownView = new ComboBoxDropdownView({ - model: model - }); - view.dropDownView = dropdownView; + remove: function () { + clearInterval(this._intervalId); + return Backbone.View.prototype.remove.apply(this, arguments); + }, - this.listenTo(dropdownView, 'search', _.debounce(view.onSearchValueHandler.bind(view), 300)); + getDropdownDirection: function (parentDOMElement) { - var $dropdown = dropdownView.render(); - $('body').append($dropdown); - - dropdownView.updatePosition(view.el); - view.dropDownView.on('itemsRendered2', function(){ - dropdownView.updatePosition(view.el); - }); + var windowHeight = $(window).height(); + var rect = parentDOMElement.getBoundingClientRect(); + var height = this.$el.height(); - if (model.get('autocomplete')) { - dropdownView.setSearchFocus(); - } else { - view.ui.control.focus(); - } - setTimeout(dropdownView.ensureVisibleSelectedItem.bind(dropdownView), 0); - } else { - view.ui.control.focus(); - } - }); - model.onValueChanged(this.onChangeValueHandler.bind(this)); + var direction = 'bottom'; + if (rect.bottom + height + 30 > windowHeight && rect.bottom > windowHeight / 2) { + direction = 'top'; + } - }, this); + return direction; }, - initHandlersForProperties: function(){ - ListEditorBaseView.prototype.initHandlersForProperties.call(this); - this.listenTo(this.model, 'change:showClear', this.updateShowClear); - this.listenTo(this.model, 'change:labelText', this.updateLabelText); - }, + applyStyle: function (parentDOMElement, direction) { + var rect = parentDOMElement.getBoundingClientRect(); - render: function () { - this.prerenderingActions(); + var style = { + left: window.pageXOffset + rect.left, + width: Math.round(rect.width) - 1 + }; - //var preparedItems = this.strategy.prepareItemsForRendering(); - //var template = this.strategy.getTemplate(); + if (direction === 'bottom') { + style.top = window.pageYOffset + rect.bottom; + } else { + style.top = window.pageYOffset + rect.top - this.$el.height(); + } - //this.removeChildElements(); + this.$el.css(style); + } - this.renderTemplate(this.getTemplate()); +}); - this.updateProperties(); +_.extend(ComboBoxDropdownView.prototype, bindUIElementsMixin); - this.trigger('render'); +//####app/controls/comboBox/dropdown/viewBaseStrategy.js +/** + * @abstract + * @param dropdownView + * @constructor + */ +function ComboBoxBaseViewStrategy(dropdownView) { + this.dropdownView = dropdownView; +} - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, +/** + * + * @param {string} attributeName + * @returns {*} + */ +ComboBoxBaseViewStrategy.prototype.getModelAttribute = function (attributeName) { + var model = this.dropdownView.model; - getTemplate: function () { - return this.template; - }, + return model.get(attributeName); +}; - onKeyDownControlHandler: function (event) { - var enabled = this.model.get('enabled'); +ComboBoxBaseViewStrategy.prototype.isEnabledItem = function (item) { + return !this.dropdownView.model.isDisabledItem(item); +}; - if (!enabled) { - event.preventDefault(); - return; - } +/** + * @description Рендеринг элементов списка + * @abstract + * @returns {Array.} Элементы списка + */ +ComboBoxBaseViewStrategy.prototype.renderItems = function () { + throw new Error('Method renderItems not implemented'); +}; - if (event.ctrlKey || event.altKey) { - return; - } +/** + * @abstract + */ +ComboBoxBaseViewStrategy.prototype.getTemplate = function () { - if (this.isDropdown()) { - return this.dropDownView.onKeyDownHandler.call(this.dropDownView, event); - } - switch (event.which) { - case 40: //Down Arrow - case 13: //Ennter - event.preventDefault(); - this.toggleDropdown(); - break; - } - }, +}; - onClickClearHandler: function () { - var enabled = this.model.get('enabled'); - if (enabled) { - this.model.set('value', null); - this.ui.control.focus(); - } - }, +/** + * Рендеринг заданных элементов списка + * @param {Array.} items + * @returns {Array.} + * @private + */ +ComboBoxBaseViewStrategy.prototype._renderItems = function (items) { + var + $items, + collection = this.getModelAttribute('items'), + itemTemplate = this.getModelAttribute('itemTemplate'); - onClickGripHandler: function () { - var enabled = this.model.get('enabled'); - if (enabled) { - this.toggleDropdown(); + $items = items.map(function (item) { + var itemEl = itemTemplate(undefined, { + value: item, + index: collection.indexOf(item) + }); + var $item = itemEl.render(); + + if (typeof item !== 'undefined') { + $item.data('pl-data-item', item); } - }, - updateProperties: function(){ - ListEditorBaseView.prototype.updateProperties.call(this); + this.addOnClickEventListener($item, item); + this.addOnHoverEventListener($item, item); - this.updateLabelText(); - this.updateShowClear(); - }, + itemEl.setEnabled( this.isEnabledItem(item) ); - updateGrouping: function(){ - this.toggleDropdown(false); - }, + return $item; + }, this); - updateLabelText: function () { - var labelText = this.model.get('labelText'); - if (labelText && labelText !== '') { - this.ui.label.toggleClass('hidden', false); - } else { - this.ui.label.toggleClass('hidden', true); - } + return $items; +}; - this.ui.label.text(labelText); - }, +/** + * + * @param {jQuery} $el + */ +ComboBoxBaseViewStrategy.prototype.addOnClickEventListener = function ($el) { + var el = $el[0]; + var params = Array.prototype.slice.call(arguments, 1); + var handler = this.trigger.bind(this, 'click'); + el.addEventListener('click', function () { + handler.apply(this, params); + }); +}; - updateEnabled: function () { - ListEditorBaseView.prototype.updateEnabled.call(this); - var enabled = this.model.get('enabled'); +ComboBoxBaseViewStrategy.prototype.addOnHoverEventListener = function ($el) { + var el = $el[0]; + var params = Array.prototype.slice.call(arguments, 1); + var handler = this.trigger.bind(this, 'mouseenter'); + $el.on('mouseenter', function () { + handler.apply(this, params); + }); +}; - if (!enabled) { - //Prevent got focus - this.ui.control.removeAttr('tabindex'); - } else { - this.updateFocusable(); - } +_.extend(ComboBoxBaseViewStrategy.prototype, Backbone.Events); +//####app/controls/comboBox/dropdown/viewGroupStrategy.js +/** + * + * @param {ComboBoxDropdownView} dropdownView + * @augments ComboBoxBaseViewStrategy + * @constructor + */ +function ComboBoxGroupViewStrategy(dropdownView) { + ComboBoxBaseViewStrategy.call(this, dropdownView); +} - }, +ComboBoxGroupViewStrategy.prototype = Object.create(ComboBoxBaseViewStrategy.prototype); +ComboBoxGroupViewStrategy.prototype.constructor = ComboBoxGroupViewStrategy; - updateValue: function(){ - this.updateShowClear(); - }, +ComboBoxGroupViewStrategy.prototype.template = InfinniUI.Template["controls/comboBox/dropdown/template/group/template.tpl.html"]; - updateShowClear: function () { - var - model = this.model, - showClear = model.get('showClear'), - value = model.get('value'), - noValue = value === null || typeof value === 'undefined'; +ComboBoxGroupViewStrategy.prototype.renderItems = function () { + var + collection = this.getModelAttribute('items'), + groupingFunction = this.getModelAttribute('groupValueSelector'), + groups = {}, + $items; - this.ui.clear.toggleClass('hidden', !showClear || noValue); - }, + collection.forEach(function (item, index) { + var groupKey = groupingFunction(undefined, {value: item, index: index}); - updateSelectedItem: function () { + if (!(groupKey in groups)) { + groups[groupKey] = []; + } - }, + groups[groupKey].push(item); + }); - updateDisabledItem: function () { - this.toggleDropdown(false); - }, + $items = this.renderGroups(groups); + return $items; +}; - isDropdown: function () { - var model = this.model; - return !!model.get('dropdown'); - }, +/** + * @description Рендереинг группированных элементов + * @param {Array.} groups + * @returns {Array.} Элементы групп + */ +ComboBoxGroupViewStrategy.prototype.renderGroups = function (groups) { + var + groupItemTemplate = this.getModelAttribute('groupItemTemplate'), + collection = this.getModelAttribute('items'), + $items= [], + $groupItems, + $groups = []; - toggleDropdown: function (toggle) { - var model = this.model; - if (typeof toggle === 'undefined') { - toggle = !model.get('dropdown'); - } - model.set('dropdown', toggle); - }, + for (var name in groups) { + var items = groups[name]; + //Шаблонизированный заголовок группы + var $header = groupItemTemplate(undefined, { + index: collection.indexOf(items[0]), + item: items[0] + } + ); + //Шаблонизированные элементы группы + var $groupItems = this._renderItems(items); - onChangeValueHandler: function () { - this.renderValue(); - }, + var groupView = new ComboBoxGroupView({ + header: $header.render(), + items: $groupItems + }); - rerender: function () { + Array.prototype.push.apply($items, $groupItems); + $groups.push(groupView.render()); + } - }, + this.dropdownView.setItemsContent($groups); - renderValue: function () { - var model = this.model, - multiSelect = model.get('multiSelect'), - value = this.model.get('value'), - $value = [], - valueTemplate = this.model.get('valueTemplate'); + return $items; +}; - if (multiSelect && Array.isArray(value)) { - var valueView = new ComboBoxValues({ - items: value.map(function(val, i) { - return { - "$value": valueTemplate(null, {value: val, index: i}).render(), - "value": val, - "index": i - }; - }) - }); - valueView.listenTo(model, 'toggle', valueView.setFocus); - this.listenTo(valueView, 'remove', this.onRemoveValueHandler); - this.listenTo(valueView, 'search', _.debounce(this.onSearchValueHandler.bind(this), 300)); - $value = valueView.render(); - } else { - $value = valueTemplate(null, {value: value}).render(); - } - this.ui.value.empty(); - this.ui.value.append($value); - editorBaseViewMixin.updateValueState.call(this); - }, +ComboBoxGroupViewStrategy.prototype.getTemplate = function () { + return this.template; +}; - onRemoveValueHandler: function (value) { - this.model.toggleValue(value, false); - }, - /** - * @description Устанока фильтра быстрого выбора элемента из списка - * @param {string} text - */ - onSearchValueHandler: function (text) { - this.toggleDropdown(true); - this.model.set('autocompleteValue', text); - }, +//####app/controls/comboBox/dropdown/viewPlainStrategy.js +/** + * + * @param {ComboBoxDropdownView} dropdownView + * @augments ComboBoxBaseViewStrategy + * @constructor + */ +function ComboBoxPlainViewStrategy(dropdownView) { + ComboBoxBaseViewStrategy.call(this, dropdownView); +} - onClickValueHandler: function (event) { - var enabled = this.model.get('enabled'); +ComboBoxPlainViewStrategy.prototype = Object.create(ComboBoxBaseViewStrategy.prototype); +ComboBoxPlainViewStrategy.prototype.constructor = ComboBoxPlainViewStrategy; - if (enabled) { - this.toggleDropdown(true); - } +ComboBoxPlainViewStrategy.prototype.renderItems = function () { + var + $items = [], + items = this.getModelAttribute('items'); + + if (items) { + $items = this._renderItems(items.toArray()); } -}); + this.dropdownView.setItemsContent($items); -//####app/controls/contextMenu/contextMenuControl.js -function ContextMenuControl() { - _.superClass(ContextMenuControl, this); -} + return $items; +}; -_.inherit(ContextMenuControl, ContainerControl); +ComboBoxPlainViewStrategy.prototype.template = InfinniUI.Template["controls/comboBox/dropdown/template/plain/template.tpl.html"]; -_.extend(ContextMenuControl.prototype, /** @lends ContextMenuControl.prototype */ { +ComboBoxPlainViewStrategy.prototype.getTemplate = function () { + return this.template; +}; - createControlModel: function () { - return new ContextMenuModel(); +//####app/controls/comboBox/dropdown/group/groupView.js +var ComboBoxGroupView = Backbone.View.extend({ + + template: InfinniUI.Template["controls/comboBox/dropdown/group/template/template.tpl.html"], + + UI: { + header: '.pl-combobox-group__header', + items: '.pl-combobox-group__items' }, - createControlView: function (model) { - return new ContextMenuView({model: model}); + initialize: function (options) { + this.options = { + header: options.header, + items: options.items + }; + + }, + + render: function () { + var options = this.options; + this.$el.html(this.template()); + this.bindUIElements() + this.ui.header.append(options.header); + this.ui.items.append(options.items); + + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + + return this.$el; } }); +_.extend(ComboBoxGroupView.prototype, bindUIElementsMixin); -//####app/controls/contextMenu/contextMenuModel.js -var ContextMenuModel = ContainerModel.extend({ +//####app/controls/comboBox/values/comboBoxValue.js +var ComboBoxValueModel = Backbone.Model.extend({ }); -//####app/controls/contextMenu/contextMenuView.js -var ContextMenuView = ContainerView.extend({ +var ComboBoxValue = Backbone.View.extend({ - contextMenuTemplate: InfinniUI.Template["controls/contextMenu/template/contextMenu.tpl.html"], + template: InfinniUI.Template["controls/comboBox/values/template/value.tpl.html"], - updateProperties: function(){ - ContainerView.prototype.updateProperties.call(this); + tagName: 'li', - this.updateContent(); - }, + className: 'pl-combobox-value', - updateContent: CommonButtonView.prototype.updateContent, - updateText: CommonButtonView.prototype.updateText, + events: { + "click .pl-combobox-value-remove": "onClickRemoveHandler" + }, - updateHorizontalAlignment: function(){ - var horizontalAlignment = this.model.get('horizontalAlignment'); - var that = this; - var $el; + UI: { + item: '.pl-combobox-value-item' + }, - this.whenReady( - function(){ - $el = that.$el.parent().parent(); - return $el.length > 0; - }, + initialize: function (options) { + this.model = new ComboBoxValueModel(options); + }, - function(){ - if(horizontalAlignment == 'Right'){ - $el - .addClass('pull-right'); - }else{ - $el - .removeClass('pull-right'); - } - } - ); - }, + render: function () { + this.$el.html(this.template()); - getButtonElement: function(){ - return this.ui.button; - }, + this.bindUIElements(); + var $value = this.model.get('$value'); + this.ui.item.append($value); + return this.$el; + }, - render: function () { - var exchange = window.InfinniUI.global.messageBus, - that = this; + onClickRemoveHandler: function () { + var value = this.model.get('value'); + this.trigger('remove', value); + } - this.prerenderingActions(); +}); - this.removeChildElements(); +_.extend(ComboBoxValue.prototype, bindUIElementsMixin); +//####app/controls/comboBox/values/comboBoxValues.js +var ComboBoxValuesModel = Backbone.Model.extend({ + defaults: { + enabled: true + }, - this.$el = this.renderDropdown(); + initialize: function () { + this.items = []; + } +}); - this.bindUIElements(); +var ComboBoxValues = Backbone.View.extend({ - this.updateProperties(); + tagName: 'ul', - this.trigger('render'); + className: 'pl-combobox-values', - this.postrenderingActions(); + template: InfinniUI.Template["controls/comboBox/values/template/values.tpl.html"], - exchange.subscribe(messageTypes.onOpenContextMenu.name, function (context, args) { - that.open(args.value); - }); + events: { + 'keypress .pl-combobox-search-text': 'onKeyPressHandler', + 'keydown .pl-combobox-search-text': 'onKeyDownHandler', + 'keyup .pl-combobox-search-text': 'onKeyUpHandler', + 'click': 'onClickHandler' + }, - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop + UI: { + search: ".pl-combobox-search", + text: ".pl-combobox-search-text" + }, - return this; - }, + initialize: function (options) { + this.model = new ComboBoxValuesModel(options); + }, - renderDropdown: function(){ - var template = this.contextMenuTemplate; - var items = this.model.get('items').toArray(); - var $result = $(template({items: items})); + render: function () { - this.appendItemsContent($result, items); - $result.on('click', function () { - this.close(); - }.bind(this)); - $result.on('contextmenu', function (event) { - event.preventDefault(); - }.bind(this)); - return $result; - }, + this.$el.empty(); - appendItemsContent: function($dropdown, items){ - var that = this, - itemTemplate = this.model.get('itemTemplate'), - itemEl, $el; + this.$el.html(this.template()); + this.bindUIElements(); - $dropdown.find('.pl-popup-button__item').each(function(i, el){ - $el = $(el); - itemEl = itemTemplate(undefined, {index: i, item: items[i]}); - that.addChildElement(itemEl); - $el.append(itemEl.render()); - }); - }, + var model = this.model; + var $items = + model.get('items') + .map(function(item) { + var view = new ComboBoxValue({ + "$value": item.$value, + "value": item.value + }); + + this.listenTo(view, 'remove', this.onRemoveValueHandler); + return view.render(); + }, this); - open: function(rightclickCoords){ - var that = this; + this.ui.search.before($items); - $('body').append(this.$el); + return this.$el; + }, - var $parent = this.$el.parent(); + KeyCode: { + enter: 13, + backspace: 8, + left: 37, + right: 39, + home: 36, + end: 35, + tab: 9 + }, - this.$el.addClass('open'); - $parent.addClass('open'); + setFocus: function () { + this.ui.text.focus(); + }, - this.alignDropdown(rightclickCoords); + onKeyPressHandler: function (event) { + var key = event.which; - var $ignoredElements = this.$el; - new ActionOnLoseFocus($ignoredElements, function(){ - that.close(); - }); - }, + if (key === this.KeyCode.enter) { - close: function(){ - this.$el.removeClass('open'); - this.$el.parent().removeClass('open'); - this.$el.detach(); - }, + } - alignDropdown: function(rightclickCoords){ - var horizontalAlignment = this.model.get('horizontalAlignment'), - $parent = this.$el.parent(), - parentDimentions = {width: $parent.width(), height: $parent.height()}, - elDimentions = {width: this.$el[0].children[0].clientWidth, height: this.$el[0].children[0].clientHeight}; + console.log('onKeyPressHandler', event.which, this.ui.text.val()); + }, - if(rightclickCoords.x + elDimentions.width > parentDimentions.width){ - rightclickCoords.x -= elDimentions.width; - } - if(rightclickCoords.y + elDimentions.height > parentDimentions.height){ - rightclickCoords.y -= elDimentions.height; - } + onKeyDownHandler: function (event) { + //handle left/right/tab/Shift-tab/backspace/end/home + var key = event.which; + if (key === this.KeyCode.left) { - this.$el.offset({ - top: rightclickCoords.y, - left: rightclickCoords.x - }); - }, + } else { - updateGrouping: function(){}, + } + console.log('onKeyDownHandler', event.which, this.ui.text.val()); + }, - whenReady: function(conditionFunction, onConditionFunction, n){ - var that = this; + onKeyUpHandler: function (event) { + //@TODO grow input + var text = this.ui.text.val(); + this.trigger('search', text); + }, - if(n === undefined){ - n = 100; - } + onRemoveValueHandler: function (value) { + this.trigger('remove', value); + }, - if(!conditionFunction()){ - if(n>0){ - setTimeout( function(){ - that.whenReady(conditionFunction, onConditionFunction, n-1); - }, 10); - } - }else{ - onConditionFunction(); - } - } + onClickHandler: function (event) { + this.setFocus(); + } }); -//####app/controls/divider/dividerControl.js -/** - * - * @param parent - * @constructor - * @arguments Control - */ -function DividerControl(parent) { - _.superClass(DividerControl, this, parent); -} +_.extend(ComboBoxValues.prototype, bindUIElementsMixin); +//####app/controls/dataGrid/dataGridControl.js +/** + * + * @constructor + * @augments ListEditorBaseControl + */ +function DataGridControl() { + _.superClass(DataGridControl, this); +} + +_.inherit(DataGridControl, ListEditorBaseControl); + +_.extend(DataGridControl.prototype, { + + createControlModel: function () { + return new DataGridModel(); + }, + + createControlView: function (model) { + return new DataGridView({model: model}); + }, + + onCheckAllChanged: function (handler) { + this.controlModel.onCheckAllChanged(handler); + }, + + setEnabled: function(value) { + this.controlModel.set('enabled', value); + }, + + onRowClick: function(callback) { + this.controlView.$el.on('click', 'tbody .pl-datagrid-row', callback); + }, + + onRowDoubleClick: function(callback) { + this.controlView.$el.on('dblclick', 'tbody .pl-datagrid-row', callback); + } +}); + -_.inherit(DividerControl, Control); +//####app/controls/dataGrid/dataGridModel.js +/** + * @constructor + * @augments ListEditorBaseModel + */ +var DataGridModel = ListEditorBaseModel.extend({ + defaults: _.defaults({ + showSelectors: true, + checkAllVisible: false, + checkAll: false, + focusable: false, + sortedColumn: null + }, ListEditorBaseModel.prototype.defaults), + + initialize: function () { + ListEditorBaseModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + this.initColumns(); + }, + + toggleCheckAll: function () { + this.set('checkAll', !this.get('checkAll')); + }, + + onCheckAllChanged: function (handler) { + this.on('change:checkAll', function (model, checkAll) { + handler.call(null, {value: checkAll}); + }); + }, + + /** + * @protected + */ + initColumns: function () { + this.set('columns', new Collection()); + } +}); -_.extend(DividerControl.prototype, { +//####app/controls/dataGrid/dataGridView.js +/** + * @constructor + * @augments ListEditorBaseView + */ +var DataGridView = ListEditorBaseView.extend({ + + template: { + "grid": InfinniUI.Template["controls/dataGrid/template/dataGrid.tpl.html"], + "gridStretched": InfinniUI.Template["controls/dataGrid/template/dataGridStretched.tpl.html"], + "headerCell": InfinniUI.Template["controls/dataGrid/template/headerCell.tpl.html"], + "sizeCell": InfinniUI.Template["controls/dataGrid/template/sizeCell.tpl.html"] + }, + + className: 'pl-datagrid', + + events: _.extend({}, + ListEditorBaseView.prototype.events, + { + "click .pl-datagrid-toggle_all": "onClickCheckAllHandler", + 'click thead .pl-datagrid-row__cell': 'onClickToHeaderCellHandler' + } + ), + + UI: _.defaults({ + body: ".pl-datagrid__body", + head: ".pl-datagrid__head", + headContainer: ".pl-datagrid-container_head", + + header: '.pl-datagrid-row_header', + firstRows: '.pl-datagrid-row_first', + toggleCell: ".pl-toggle-cell", + checkAll: ".pl-datagrid-toggle__button", + items: 'tbody' + }, ListEditorBaseView.prototype.UI), + + initialize: function (options) { + ListEditorBaseView.prototype.initialize.call(this, options); + this.rowElements = new HashMap(); + }, + + initHandlersForProperties: function(){ + ListEditorBaseView.prototype.initHandlersForProperties.call(this); + + this.listenTo(this.model, 'change:showSelectors', this.updateShowSelectors); + this.listenTo(this.model, 'change:checkAllVisible', this.updateCheckAllVisible); + this.listenTo(this.model, 'change:checkAll', this.updateCheckAll); + + /** Update hash item => element when item changed **/ + var rowElements = this.rowElements; + var model = this.model; + this.model.get('items').onChange(function(event){ + if (event.action === 'replace') { + event.oldItems.forEach(function (oldItem, index) { + rowElements.add(event.newItems[index], rowElements.get(oldItem)); + rowElements.remove(oldItem); + }); + } + }); + }, + + updateProperties: function () { + ListEditorBaseView.prototype.updateProperties.call(this); + this.updateShowSelectors(); + this.updateCheckAllVisible(); + this.updateCheckAll(); + this.updateDisabledItem(); + }, + + updateShowSelectors: function () { + var showSelectors = this.model.get('showSelectors'); + this.$el.toggleClass('pl-datagrid_selectors_show', showSelectors); + this.$el.toggleClass('pl-datagrid_selectors_hide', !showSelectors); + }, + + updateGrouping: function () { + + }, + + updateVerticalAlignment: function () { + ListEditorBaseView.prototype.updateVerticalAlignment.call(this); + this.switchClass('verticalAlignment', this.model.get('verticalAlignment'), this.ui.body, false); + }, + + updateCheckAll: function () { + var checkAll = this.model.get('checkAll'); + this.ui.checkAll.prop('checked', checkAll); + }, + + getHorizontalScrollBarWidth: function () { + + if (typeof DataGridView.scrollbarWidth === 'undefined') { + var scrollDiv = document.createElement('div'); + var body = document.body; + + scrollDiv.className = 'modal-scrollbar-measure'; + var style = { + position: "absolute", + top: "-9999px", + width: "50px", + height: "50px", + overflow: "scroll" + }; + + for(var name in style) { + scrollDiv.style[name] = style[name] + } + + body.appendChild(scrollDiv); + DataGridView.scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; + body.removeChild(scrollDiv); + } + + return DataGridView.scrollbarWidth; + }, + + updateCheckAllVisible: function () { + var checkAllVisible = this.model.get('checkAllVisible'); + this.ui.checkAll.toggleClass('hidden', !checkAllVisible); + }, + + updateMultiSelect: function () { + ListEditorBaseView.prototype.updateMultiSelect.call(this); + + var multiSelect = this.model.get('multiSelect'); + this.$el.toggleClass('pl-datagrid_select_multi', multiSelect === true); + this.$el.toggleClass('pl-datagrid_select_single', multiSelect !== true); + }, + + updateValue: function () { + var + model = this.model, + value = model.get('value'), + indices = [], + items = model.get('items'); + + if(!model.get('multiSelect') && value !== undefined && value !== null){ + value = [value]; + } + + if (Array.isArray(value)) { + indices = value.map(function (val) { + return model.itemIndexByValue(val); + }) + .filter(function (index) { + return index !== -1; + }); + } + + this.rowElements.forEach(function (rowElement, item) { + var index = items.indexOf(item); + var toggle = indices.indexOf(index) !== -1; + rowElement.toggle(toggle); + }); + + }, + + updateSelectedItem: function () { + var model = this.model, + selectedItem = model.get('selectedItem'); + + this.rowElements.forEach(function (rowElement, item) { + rowElement.setSelected(item === selectedItem); + }); + }, + + updateDisabledItem: function () { + var model = this.model, + disabledItemCondition = model.get('disabledItemCondition'), + isEnabled; + + if( disabledItemCondition != null ) { + this.rowElements.forEach(function (rowElement, item) { + isEnabled = !disabledItemCondition( undefined, {value: item} ); + if( rowElement.getSelected() === item && isEnabled === false ) { + model.set('selectedItem', null); + } + rowElement.setEnabled(isEnabled); + }); + } else { + this.rowElements.forEach(function (rowElement, item) { + rowElement.setEnabled(true); + }); + } + }, + + updateEnabled: function() { + var isEnabled = this.model.get('enabled'); + if( isEnabled ) { + this.updateDisabledItem(); + } else { + this.disableDataGridItems(); + } + }, + + disableDataGridItems: function() { + this.model.set('selectedItem', null); + this.rowElements.forEach(function (rowElement, item) { + rowElement.setEnabled(false); + }); + }, + + render: function () { + var that = this; + this.prerenderingActions(); + + var verticalAlignment = this.model.get('verticalAlignment'); + var template = (verticalAlignment === 'Stretch') ? this.template.gridStretched : this.template.grid; + this.$el.html(template()); + + this.bindUIElements(); + + this.renderHeaders(); + this.renderItems(); + + this.trigger('render'); + + this.applyColumnWidth(); + this.syncBodyAndHead(); + this.postrenderingActions(); + setTimeout(function() { + that.updateProperties(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: that}); + //devblockstop + }, 0); + return this; + }, + + applyColumnWidth: function () { + var columns = this.model.get('columns'); + var fixedTableLayout = false; + + this.ui.firstRows.children().each(function (i, el) { + var columnIndex = i % (columns.length + 1); + + if (columnIndex === 0) { + //skip columns with checkbox/radiobutton + return; + } + + var column = columns.getByIndex(columnIndex - 1); + var width = column && column.getWidth(); + + if (width) { + $(el).css('width', width); + fixedTableLayout = true; + } + }); + + this.$el.toggleClass('pl-datagrid_layout_fixed', fixedTableLayout); + }, + + syncBodyAndHead: function () { + //var $body = this.ui.body; + var $head = this.ui.head; + + $head.css('padding-right', this.getHorizontalScrollBarWidth() + "px"); + + this.ui.body + .off('scroll') + .on('scroll', this.onScrollBodyHandler.bind(this)); + + }, + + onScrollBodyHandler: function () { + this.ui.headContainer.scrollLeft(this.ui.body.scrollLeft()); + }, + + renderHeaders: function () { + var that = this; + var columns = this.model.get('columns'); + // var templateHeaderCell = this.template.headerCell(); + var sizeCells = []; + var templateSizeCells = this.template.sizeCell(); + + var $headers = columns.toArray().map(function (column) { + + sizeCells.push(templateSizeCells); + // @TODO remove hardcoded template when the memory leaks of dataBindings would have fixed + // bug related to task JK-4516 + var $th = $(''); + + var headerTemplate = column.getHeaderTemplate(); + var header = column.getHeader(); + + $th.data('pl-column', column); + + if( column.getSortable() ) { + $th.addClass('sortable'); + + if( column.getSortDirection() ) { + setTimeout(function() { + that.setUpColumnSort(column, $th, column.getSortDirection(), false); + }, 0); + } + } + + var headerElement; + + if (headerTemplate) { + headerElement = headerTemplate(null, {value: header}); + $th.append(headerElement.render()); + + } else { + $th.append(header); + } + return $th; + }); + + this.ui.header.append($headers); + this.ui.firstRows.append(sizeCells); + }, + + renderItems: function () { + var + model = this.model, + valueSelector = model.get('valueSelector'), + itemTemplate = model.get('itemTemplate'), + items = model.get('items'), + $items = this.ui.items, + that = this; + + this.removeRowElements(); + + items.forEach(function (item, index) { + setTimeout(function() { + var element = itemTemplate(undefined, {index: index, item: item}); + + element.onBeforeClick(function() { + var items = model.get('items'), + item = items.getByIndex(index), + rowItem = that.rowElements.get(item); + if( rowItem.getEnabled() !== false ) { + model.set('selectedItem', item); + } + }); + + element.onToggle(function() { + var enabled = this.model.get('enabled'); + var items = model.get('items'); + + if(enabled){ + model.toggleValue(valueSelector(undefined, {value:items.getByIndex(index)})); + } + }); + that.addRowElement(item, element); + + var $element = element.render(); + $items.append($element); + }, 0); + }, this); + + }, + + updateFocusable: function () { + var focusable = this.model.get('focusable'); + + this.rowElements.values.forEach(function (element) { + if (focusable) { + element.control.controlView.$el.attr('tabindex', 0); + } else { + element.control.controlView.$el.removeAttr('tabindex'); + } + }) + }, + + addRowElement: function(item, element){ + this.addChildElement(element); + this.rowElements.add(item, element); + }, + + removeRowElements: function () { + this.removeChildElements(); + this.rowElements.clear(); + }, + + onClickCheckAllHandler: function () { + this.model.toggleCheckAll(); + }, + + onClickToHeaderCellHandler: function (e) { + var $th = $(e.currentTarget), + column = $th.data('pl-column'); + + if( column && column.isSortable() ){ + if(column.getSortDirection() === null) { + this.resetSort(); + this.setUpColumnSort(column, $th, 'asc'); + } else if( column.getSortDirection() === 'asc' ) { + this.resetSort('asc'); + this.setUpColumnSort(column, $th, 'desc'); + } else if( column.getSortDirection() === 'desc' ) { + this.resetSort('desc'); + this.setUpColumnSort(column, $th, 'asc'); + } + } + }, + + setUpColumnSort: function(column, $th, direction, triggerEvent) { + column.setSortDirection(direction); + this.model.set('sortedColumn', column); + if( !column.getIsHeaderTemplateEmpty() ) { + $th.addClass('sorted headerTemplate-sorted-' + direction); + } else { + $th.addClass('sorted sorted-' + direction); + } + if( triggerEvent !== false ) { + column.trigger('onSort', {sortDirection: direction}); + } + }, + + resetSort: function(direction) { + if( !direction ) { + var $sortableCell = this.$el.find('.sorted'); + $sortableCell.removeClass('sorted headerTemplate-sorted-asc headerTemplate-sorted-desc sorted-asc sorted-desc'); + var sortedCell = this.model.get('sortedColumn'); + if( sortedCell ) { + sortedCell.setSortDirection(null); + } + } else { + var $sortableCell = this.$el.find('.sorted'); + $sortableCell.removeClass('headerTemplate-sorted-' + direction + ' sorted-' + direction); + } + } + + +}); + + - createControlModel: function () { - return new DividerModel(); - }, +//####app/controls/dataGrid/dataGridRow/dataGridRowControl.js +/** + * + * @constructor + * @augments ListEditorBaseControl + */ +function DataGridRowControl() { + _.superClass(DataGridRowControl, this); +} + +_.inherit(DataGridRowControl, Control); + +_.extend(DataGridRowControl.prototype, { + + onToggle: function (handler) { + this.controlView.on('toggle', handler); + }, + + createControlModel: function () { + return new DataGridRowModel(); + }, + + createControlView: function (model) { + return new DataGridRowView({model: model}); + } +}); + - createControlView: function (model) { - return new DividerView({model: model}); - } +//####app/controls/dataGrid/dataGridRow/dataGridRowModel.js +var DataGridRowModel = ControlModel.extend({ + }); +//####app/controls/dataGrid/dataGridRow/dataGridRowView.js +var DataGridRowView = ControlView.extend({ + + className: 'pl-datagrid-row pl-datagrid-row_data', + + classNameSelected: 'info', + + tagName: 'tr', + + events: {}, + + template: { + singleSelect: InfinniUI.Template["controls/dataGrid/dataGridRow/template/singleSelect.tpl.html"], + multiSelect: InfinniUI.Template["controls/dataGrid/dataGridRow/template/multiSelect.tpl.html"], + dataCell: InfinniUI.Template["controls/dataGrid/dataGridRow/template/dataCell.tpl.html"] + }, + + UI: { + toggleCell: '.pl-datagrid-row__cell_toggle', + toggle: '.pl-datagrid-toggle', + toggleControl: '.pl-datagrid-toggle input' + }, + + initialize: function () { + ControlView.prototype.initialize.call(this); + + this.on('render', function () { + this.ui.toggleCell.on('click', this.onToggleHandler.bind(this)); + }, this); + }, + + initHandlersForProperties: function () { + ControlView.prototype.initHandlersForProperties.call(this); + this.listenTo(this.model, 'change:toggle', this.updateToggle); + this.listenTo(this.model, 'change:selected', this.updateSelected); + }, + + updateProperties: function () { + ControlView.prototype.updateProperties.call(this); + this.updateToggle(); + this.updateSelected(); + this.updateShowSelectors(); + }, + + updateVerticalAlignment: function () { + //Use Vertical alignment for DataGrid + }, + + render: function () { + this.prerenderingActions(); + var $el = this.$el; + var row = this; + + var templateName = this.model.get('multiSelect') ? 'multiSelect' : 'singleSelect'; + var template = this.template[templateName]; + $el.html(template()); + this.bindUIElements(); + + var cellElements = this.model.get('cellElements'); + // var templateDataCell = this.template.dataCell(); + if (Array.isArray(cellElements)) { + cellElements.forEach(function (cellElement, index) { + // @TODO remove hardcoded template when the memory leaks of dataBindings would have fixed + // bug related to task JK-4516 + var $cell = $(''); + $cell.append(cellElement.render()); + $el.append($cell); + }); + } + this.updateProperties(); + + this.trigger('render'); + + this.postrenderingActions(); + return this; + }, + + updateShowSelectors: function () { + var showSelectors = this.model.get('showSelectors'); + this.ui.toggleCell.toggleClass('hidden', !showSelectors); + }, + + updateToggle: function () { + var toggle = this.model.get('toggle'); + this.ui.toggleControl.prop('checked', !!toggle); + }, + + updateSelected: function () { + var selected = this.model.get('selected'); + this.$el.toggleClass(this.classNameSelected, !!selected); + }, + + updateEnabled: function () { + ControlView.prototype.updateEnabled.call(this); + + var enabled = this.model.get('enabled'); + this.ui.toggleControl.attr('disabled', enabled ? null : 'disabled'); + }, + + onToggleHandler: function (event) { + this.trigger('toggle'); + } + + +}); + +//####app/controls/dataNavigation/buttons/dataNavigationBaseButton.js +var DataNavigationBaseButtonModel = Backbone.Model.extend({ + + initialize: function () { + this.on('change:parent', this.subscribeToParent, this); + }, + + subscribeToParent: function () { + + } +}); + +var DataNavigationBaseButton = Backbone.View.extend({ + + tagName: 'li', + + initialize: function (options) { + Backbone.View.prototype.initialize.call(this, options); + this.once('render', function () { + this.initHandlersForProperties() + }, this); + }, + + initHandlersForProperties: function () { + + }, + + updateProperties: function () { + + }, + + getData: function () { + return this.model.toJSON(); + }, + + setParent: function (parent) { + this.model.set('parent', parent); + this.subscribeForParent(parent); + }, + + render: function () { + var template = this.template(this.getData()); + this.$el.html(template); + this.trigger('render'); + this.updateProperties(); + return this; + }, + + subscribeForParent: function (parent) { + + } + +}); + -//####app/controls/divider/dividerModel.js -/** - * @class - * @arguments ControlModel - */ -var DividerModel = ControlModel.extend(/** @lends DividerModel.prototype */{ +//####app/controls/dataNavigation/buttons/dataNavigationNextButton.js +var DataNavigationNextButton = DataNavigationBaseButton.extend({ + + template: InfinniUI.Template["controls/dataNavigation/buttons/template/next.tpl.html"], + + events: { + "click": "onClickHandler" + }, + + initialize: function (options) { + this.model = new DataNavigationBaseButtonModel(); + DataNavigationBaseButton.prototype.initialize.call(this, options); + }, + + onClickHandler: function (event) { + this.trigger('command', "next"); + } + +}); - initialize: function () { - ControlModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - } +//####app/controls/dataNavigation/buttons/dataNavigationPageButton.js +var DataNavigationPageButton = DataNavigationBaseButton.extend({ + template: InfinniUI.Template["controls/dataNavigation/buttons/template/page.tpl.html"], + + events: { + "click": "onClickHandler" + }, + + initialize: function (options) { + this.model = new DataNavigationPageButtonModel(); + DataNavigationBaseButton.prototype.initialize.call(this, options); + this.model.set('pageNumber', options.pageNumber); + }, + + initHandlersForProperties: function () { + DataNavigationBaseButton.prototype.initHandlersForProperties.call(this); + this.listenTo(this.model, 'change:isCurrent', this.updateIsCurrent); + }, + + updateProperties: function () { + DataNavigationBaseButton.prototype.updateProperties.call(this); + this.updateIsCurrent(); + }, + + updateIsCurrent: function () { + this.$el.toggleClass('active', this.model.get('isCurrent')); + }, + + onClickHandler: function (event) { + this.trigger('command', "page", {pageNumber: this.model.get('pageNumber')}); + } + +}); + + +var DataNavigationPageButtonModel = DataNavigationBaseButtonModel.extend({ + + defaults: { + isCurrent: false + }, + + subscribeToParent: function () { + DataNavigationBaseButtonModel.prototype.subscribeToParent.call(this); + + var parent = this.get('parent'); + this.listenTo(parent.model, 'change:pageNumber', function () { + this.updateIsCurrent(); + }); + this.updateIsCurrent(); + }, + + updateIsCurrent: function () { + var parent = this.get('parent'); + var isCurrent = parent.model.get('pageNumber') === this.get('pageNumber'); + this.set("isCurrent", isCurrent); + } + +}); +//####app/controls/dataNavigation/buttons/dataNavigationPrevButton.js +var DataNavigationPrevButton = DataNavigationBaseButton.extend({ + + template: InfinniUI.Template["controls/dataNavigation/buttons/template/prev.tpl.html"], + + events: { + "click": "onClickHandler" + }, + + initialize: function (options) { + this.model = new DataNavigationBaseButtonModel(); + DataNavigationBaseButton.prototype.initialize.call(this, options); + }, + + onClickHandler: function (event) { + this.trigger('command', "prev"); + } + +}); +//####app/controls/dataNavigation/dataNavigationButtonFactory.js +function DataNavigationButtonFactory (dataNavigation) { + + this._dataNavigation = dataNavigation; +} + +DataNavigationButtonFactory.prototype.buttons = { + "prev": DataNavigationPrevButton, + "page": DataNavigationPageButton, + "next": DataNavigationNextButton +}; + +DataNavigationButtonFactory.prototype.createButton = function (type, options) { + + var buttonConstructor = this.buttons[type]; + if (typeof buttonConstructor !== 'function') { + console.error('Wrong button type: ' + type); + return; + } + + var button = new buttonConstructor(options); + button.setParent(this._dataNavigation); + return button; +}; +//####app/controls/dataNavigation/dataNavigationControl.js +function DataNavigationControl (parent) { + _.superClass(DataNavigationControl, this, parent); +} + +_.inherit(DataNavigationControl, Control); + +_.extend(DataNavigationControl.prototype, { + + createControlModel: function () { + return new DataNavigationModel(); + }, + + createControlView: function (model) { + return new DataNavigationView({model: model}); + }, + + onPageNumberChanged: function (handler) { + this.controlModel.onPageNumberChanged(handler); + }, + + onPageSizeChanged: function (handler) { + this.controlModel.onPageSizeChanged(handler); + } + +}); +//####app/controls/dataNavigation/dataNavigationModel.js +var DataNavigationModel = ControlModel.extend({ + + defaults: _.defaults({ + pageNumber: 0, + pageStart: 0, + _buttonsCount: 5, + _buttonsTemplate: ['prev', 'page', 'next'], + pageCount: null, + isDataReady: false + }, + ControlModel.prototype.defaults + ), + + initialize: function () { + ControlModel.prototype.initialize.apply(this, arguments); + this.set('availablePageSizes', new Collection()); + this.on('change:pageNumber', this.updatePageStart, this); + this.on('change:pageSize', this.updatePageSize, this); + }, + + updatePageStart: function () { + var + pageNumber = this.get('pageNumber'), + pageStart = this.get('pageStart'), + buttonsCount = this.get('_buttonsCount'); + + if (pageNumber + 1 >= pageStart + buttonsCount) { + //Выбрана последняя страница по кнопкам навигации. переместить ее в центр + pageStart = pageStart + Math.floor(buttonsCount / 2); + } else if (pageNumber === pageStart) { + //Сдвинуть кнопки навигации вправо, чтобы выбранная страница была в центре + pageStart = Math.max(0, pageStart - Math.floor(buttonsCount / 2)); + } else if (pageNumber + 1 < pageStart) { + pageStart = Math.max(0, pageNumber - 1); + } + this.set('pageStart', pageStart); + }, + + updatePageSize: function () { + //сьрос навигации + this.set('pageNumber', 0); + }, + + nextPage: function () { + var pageNumber = this.get('pageNumber'); + this.set('pageNumber', pageNumber + 1); + }, + + prevPage: function () { + var pageNumber = this.get('pageNumber'); + if (pageNumber > 0) { + this.set('pageNumber', pageNumber - 1); + } + }, + + onPageNumberChanged: function (handler) { + this.on('change:pageNumber', function (model, value) { + handler.call(null, {value: value}); + }); + }, + + onPageSizeChanged: function (handler) { + this.on('change:pageSize', function (model, value) { + handler.call(null, {value: value}); + }); + } + }); +//####app/controls/dataNavigation/dataNavigationView.js +var DataNavigationView = ControlView.extend({ + + template: InfinniUI.Template["controls/dataNavigation/template/dataNavigation.tpl.html"], + + className: 'pl-data-navigation', + + UI: { + buttons: 'ul', + sizes: '.pl-page-size' + }, + + initialize: function (options) { + ControlView.prototype.initialize.call(this, options); + this._childViews = []; + this.buttonsFactory = new DataNavigationButtonFactory(this); + this._pageSizes = new DataNavigationPageSizes(); + this._pageSizes.setParent(this); + }, + + initHandlersForProperties: function() { + ControlView.prototype.initHandlersForProperties.call(this); + this.listenTo(this.model, 'change:pageStart', this.updateButtons); + this.listenTo(this.model, 'change:pageCount', this.updateButtons); + this.listenTo(this.model, 'change:isDataReady', this.updateButtons); + }, + + updateProperties: function() { + ControlView.prototype.updateProperties.call(this); + this.updateButtons(); + }, + + render: function () { + this.prerenderingActions(); + + this.renderTemplate(this.template); + this.updateProperties(); + this.trigger('render'); + this.renderPageSizes(); + this.postrenderingActions(); + + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, + + renderPageSizes: function () { + this.ui.sizes.append(this._pageSizes.render().$el); + }, + + renderButtons: function () { + var + template = this.model.get('_buttonsTemplate'), + buttonsCount = this.model.get('_buttonsCount'), + pageCount = this.model.get('pageCount'), + pageNumber = this.model.get('pageNumber'), + pageStart = this.model.get('pageStart'), + isDataReady = this.model.get('isDataReady'), + buttons, + nowManyElementsRemove; + + this._removeChildViews(); + + if(!isDataReady){ + return; + } + + var + buttonsFactory = this.buttonsFactory, + model = this.model; + + buttons = template.reduce(function (buttons, buttonType) { + if (buttonType === 'page') { + for (var i = 0; i < buttonsCount; i = i + 1) { + var button = buttonsFactory.createButton(buttonType, {pageNumber: pageStart + i}); + buttons.push(button) + } + } else { + var button = buttonsFactory.createButton(buttonType); + buttons.push(button); + } + + return buttons; + }, []); + + if(typeof pageCount == 'number' && pageStart + buttonsCount >= pageCount){ + nowManyElementsRemove = pageStart + buttonsCount - pageCount + 1; + + if(pageCount == 0){ + nowManyElementsRemove += 1; + } + + buttons.splice(buttons.length - nowManyElementsRemove, 100); + } + + var $buttons = buttons.map(function (button) { + this.listenTo(button, 'command', this.onCommandHandler); + this._appendChildView(button); + return button.render().$el; + }, this); + + this.ui.buttons.append($buttons); + }, + + updateButtons: function () { + this.renderButtons() + }, + + onCommandHandler: function (name, options) { + switch (name) { + case "prev": + this.model.prevPage(); + break; + case "next": + this.model.nextPage(); + break; + case "page": + this.model.set('pageNumber', options.pageNumber); + break; + } + }, + + _removeChildViews: function () { + this._childViews.forEach(function (view) { + this.stopListening(view); + view.remove(); + }, this); + this._childViews.length = 0; + }, + + _appendChildView: function (view) { + this._childViews.push(view); + } + +}); -//####app/controls/divider/dividerView.js +//####app/controls/dataNavigation/pageSizes/dataNavigationPageSizes.js +var DataNavigationPageSizes = Backbone.View.extend({ + + className: "btn-group", + + template: InfinniUI.Template["controls/dataNavigation/pageSizes/template/pageSizes.tpl.html"], + + events: { + "click button": "onClickButtonHandler" + }, + + setParent: function (parent) { + this.model = parent.model; + var collection = this.model.get('availablePageSizes'); + collection.onChange(this.onAvailablePageSizesChanged.bind(this)); + this.model.on('change:pageSize', this.renderButtons, this); + }, + + render: function () { + this.renderButtons(); + return this; + }, + + renderButtons: function () { + var collection = this.model.get('availablePageSizes'); + var pageSize = this.model.get('pageSize'); + + var html = collection.toArray().map(function (size) { + return this.template({size: size, active: pageSize === size}); + }, this); + + this.$el.html(html); + }, + + onAvailablePageSizesChanged: function () { + this.renderButtons(); + }, + + onClickButtonHandler: function (event) { + var $el = $(event.target); + + var pageSize = parseInt($el.attr('data-size'), 10); + this.model.set('pageSize', pageSize); + } + +}); + +//####app/controls/label/commonView/labelView.js /** - * @class - * @arguments ControlView + * @class LabelView + * @augments ControlView + * @mixes editorBaseViewMixin */ -var DividerView = ControlView.extend( - /** @lends DividerView.prototype */ - { - tagName: 'hr', +var CommonLabelView = ControlView.extend(_.extend({}, editorBaseViewMixin, /** @lends LabelView.prototype */{ + className: 'pl-label', - className: 'pl-divider', + template: InfinniUI.Template["controls/label/commonView/template/label.tpl.html"], - initialize: function (options) { - ControlView.prototype.initialize.call(this, options); - }, + UI: _.extend({}, editorBaseViewMixin.UI, { + control: '.label-control' + }), - render: function () { - this.prerenderingActions(); + initialize: function () { + ControlView.prototype.initialize.apply(this); + }, - this.updateProperties(); - this.trigger('render'); + initHandlersForProperties: function(){ + ControlView.prototype.initHandlersForProperties.call(this); + editorBaseViewMixin.initHandlersForProperties.call(this); - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - } + this.listenTo(this.model, 'change:displayFormat', this.updateDisplayFormat); + this.listenTo(this.model, 'change:textWrapping', this.updateTextWrapping); + this.listenTo(this.model, 'change:textTrimming', this.updateTextTrimming); + }, - } -); + updateProperties: function(){ + ControlView.prototype.updateProperties.call(this); + editorBaseViewMixin.updateProperties.call(this); -//####app/controls/extensionPanel/extensionPanel.js -var ExtensionPanelControl = function () { - _.superClass(ExtensionPanelControl, this); -}; + this.updateDisplayFormat(); + this.updateTextWrapping(); + this.updateTextTrimming(); + }, -_.inherit(ExtensionPanelControl, ContainerControl); + updateFocusable: function () { + var focusable = this.model.get('focusable'); -_.extend(ExtensionPanelControl.prototype, { + if (focusable) { + this.ui.control.attr('tabindex', 0); + } else { + this.ui.control.removeAttr('tabindex'); + } + }, - createControlModel: function () { - return new ExtensionPanelModel(); + updateValue: function(){ + var escapeHtml = this.model.get('escapeHtml'); + var setContent = escapeHtml ? 'text' : 'html'; + var textForLabel = this.getLabelText(); + var $label = this.getLabelElement(); + + $label[setContent](textForLabel); + var title = String(textForLabel); + $label.attr('title', title.replace(/<\/?[^>]+>/g, '')); //strip html tags }, - createControlView: function (model) { - return new ExtensionPanelView({model: model}); - } -}); -//####app/controls/extensionPanel/extensionPanelModel.js -var ExtensionPanelModel = ContainerModel.extend({ - defaults: _.defaults({ - extensionName: null, - context: null - }, ContainerModel.prototype.defaults), + updateDisplayFormat: function(){ + this.updateValue(); + }, - initialize: function () { - ContainerModel.prototype.initialize.apply(this); - } -}); -//####app/controls/extensionPanel/extensionPanelView.js -var ExtensionPanelView = ContainerView.extend({ - className: 'pl-extension-panel', + updateTextWrapping: function(){ + var textWrapping = this.model.get('textWrapping'); + this.getLabelElement().toggleClass('pl-text-wrapping', textWrapping); + }, - initialize: function () { - ContainerView.prototype.initialize.apply(this); - this.extensionObject = null; + updateTextTrimming: function(){ + var textTrimming = this.model.get('textTrimming'); + this.getLabelElement().toggleClass('pl-text-trimming', textTrimming); + }, + + updateText: function () { + this.updateValue(); + }, + + getData: function () { + return _.extend( + {}, + ControlView.prototype.getData.call(this), + editorBaseViewMixin.getData.call(this), + { + text: this.getLabelText() + } + ); }, render: function () { this.prerenderingActions(); - - if (!this.extensionObject) { - this.initExtensionObject(); - } - - this.extensionObject.render(); + this.renderTemplate(this.template); this.updateProperties(); - this.trigger('render'); + this.trigger('render'); this.postrenderingActions(); //devblockstart window.InfinniUI.global.messageBus.send('render', {element: this}); @@ -14741,853 +11623,801 @@ var ExtensionPanelView = ContainerView.extend({ return this; }, - updateGrouping: function(){ + getLabelText: function () { + var model = this.model; + var value = model.get('value'); + var text; + var format = model.get('displayFormat'); - }, + if (typeof value !== 'undefined' && value !== null) { + text = typeof format === 'function' ? format(null, {value: value}) : value; + }else{ + text = this.model.get('text'); + if (typeof text === 'undefined' || text == null) { + text = ''; + } + } - initExtensionObject: function () { - var extensionName = this.model.get('extensionName'), - context = this.model.get('context'), - itemTemplate = this.model.get('itemTemplate'), - parameters = this.model.get('parameters'), - items = this.model.get('items'), - builder = this.model.get('builder'); + return text; + }, - this.extensionObject = new window[extensionName](context, {$el: this.$el, parameters: parameters, itemTemplate: itemTemplate, items: items, builder: builder}); + getLabelElement: function(){ + return this.ui.control; } -}); -//####app/controls/fileBox/fileBoxControl.js -/** - * - * @param parent - * @constructor - * @augments Control - * @mixes editorBaseControlMixin - */ -function FileBoxControl(parent) { - _.superClass(FileBoxControl, this, parent); +})); + +InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.Label.common', CommonLabelView); + +//####app/controls/label/label.js +var LabelControl = function (viewMode) { + _.superClass(LabelControl, this, viewMode); this.initialize_editorBaseControl(); -} +}; -_.inherit(FileBoxControl, Control); +_.inherit(LabelControl, Control); -_.extend(FileBoxControl.prototype, { +_.extend(LabelControl.prototype, { createControlModel: function () { - return new FileBoxModel(); + return new LabelModel(); }, - createControlView: function (model) { - return new FileBoxView({model: model}); + createControlView: function (model, viewMode) { + if(!viewMode || ! (viewMode in window.InfinniUI.viewModes.Label)){ + viewMode = 'simple'; + } + + var ViewClass = window.InfinniUI.viewModes.Label[viewMode]; + + return new ViewClass({model: model}); + }, + + getDisplayValue: function () { + return this.controlView.getLabelText(); } }, editorBaseControlMixin); - -//####app/controls/fileBox/fileBoxModel.js -/** - * @constructor - * @augments ControlModel - * @mixes editorBaseModelMixin - */ -var FileBoxModel = ControlModel.extend( _.extend({ +//####app/controls/label/labelModel.js +var LabelModel = ControlModel.extend(_.extend({ defaults: _.defaults({ + horizontalTextAlignment: 'Left', + verticalAlignment: 'Top', + textWrapping: true, + textTrimming: true, + escapeHtml: true, + focusable: false + }, ControlModel.prototype.defaults), - }, - editorBaseModelMixin.defaults_editorBaseModel, - ControlModel.prototype.defaults - ), - initialize: function () { + initialize: function(){ ControlModel.prototype.initialize.apply(this, arguments); this.initialize_editorBaseModel(); + } +}, editorBaseModelMixin)); +//####app/controls/label/simpleView/labelView.js +/** + * @class SimpleLabelView + * @augments ControlView + * @mixes editorBaseViewMixin + */ +var SimpleLabelView = CommonLabelView.extend({ + tagName: 'span', - this.set('acceptTypes', new Collection()); - this.on('change:file', this.onChangeFileHandler); - this.on('change:value', function (model, value) { - if (value instanceof File) { - model.set('fileName', value.name); - } - }); - - this.on("invalid", function(model, error) { - this.set('errorText', error); - }); - }, - - validate: function (attrs, options) { - var file = attrs.file; - var maxSize = this.get('maxSize'); - var acceptTypes = this.get('acceptTypes'); - if (file) { - if (maxSize) { - if (file.size > maxSize) { - return 'Размер выбранного файла ' + (file.size/(1024*1024)).toFixed(1) + 'Мб больше допустимого размера ' + (maxSize/(1024*1024)).toFixed(1) + 'Мб'; - } - } - - if (acceptTypes.length) { - var acceptType = acceptTypes.contains(file.type); - var fileName = file.name.toLowerCase(); - if (!acceptType) { - var len = fileName.length; - var acceptType = acceptTypes.some(function(name) { - return fileName.lastIndexOf(name.toLowerCase()) === len - name.length; - }); - } - - if (!acceptType) { - return 'Загрузка данного типа файла не разрешена'; - } - - } + template: function(){return '';}, + UI: _.extend({}, editorBaseViewMixin.UI, { + }), - } - }, + updateFocusable: function () { + var focusable = this.model.get('focusable'); - setFile: function (file) { - if (this.set('file', file, {validate: true})) { - this.set('errorText', ''); + if (focusable) { + this.$el.attr('tabindex', 0); + } else { + this.$el.removeAttr('tabindex'); } }, - removeFile: function () { - this.setFile(null); - }, - - onChangeFileHandler: function (model, file) { - if (file) { - model.set('fileName', file.name); - model.set('fileSize', file.size); - } else { - model.set('fileName', null); - model.set('fileSize', null); - } - model.set('value', file); - //model.set('value', null); + getLabelElement: function(){ + return this.$el; } - //stopLoadingFile: function () { - // var fileLoader = this.fileLoader; - // if (fileLoader && fileLoader.state() === 'pending') { - // fileLoader.reject(); - // } - //}, - - //loadPreview: function (file) { - // var defer = $.Deferred(); - // var reader = new FileReader(); - // reader.onload = (function (file) { - // return function (event) { - // defer.resolve(file, event.target.result); - // }; - // }(file)); - // reader.onerror = function (event) { - // defer.reject(event); - // }; - // reader.readAsDataURL(file); - // return defer.promise(); - //} +}); -}, editorBaseModelMixin)); -//####app/controls/fileBox/fileBoxView.js -/** - * @augments ControlView - * @mixes editorBaseViewMixin - * @constructor - */ -var FileBoxView = ControlView.extend(/** @lends FileBoxView.prototype */ _.extend({}, editorBaseViewMixin, { +InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.Label.simple', SimpleLabelView); +//####app/controls/listBox/baseView/listBoxView.js +var BaseListBoxView = ListEditorBaseView.extend({ - template: InfinniUI.Template["controls/fileBox/template/template.tpl.html"], + template: { + plain: InfinniUI.Template["controls/listBox/baseView/template/listBox.tpl.html"], + grouped: InfinniUI.Template["controls/listBox/baseView/template/listBoxGrouped.tpl.html"] + }, - className: 'pl-file-box', - UI: _.extend({}, editorBaseViewMixin.UI, { - label: '.pl-control-label', - btnRemove: '.pl-filebox-btn-remove', - btnPick: '.pl-filebox-btn-pick', - fileEmpty: '.pl-filebox-file-empty', - fileUpload: '.pl-filebox-file-upload', - fileDownload: '.pl-filebox-file-download', - fileDownloadUrl: '.pl-filebox-file-download-url', - edit: '.pl-filebox-edit', - control: '.form-control', - - input: 'input' - }), + className: 'pl-listbox', events: { - 'change input': 'onChangeFileHandler', - 'click .pl-filebox-btn-remove': 'onClickRemoveImageHandler' + 'change .pl-listbox-input': 'onChangeHandler' }, - initHandlersForProperties: function(){ - ControlView.prototype.initHandlersForProperties.call(this); - this.listenTo(this.model, 'change:labelText', this.updateLabelText); - this.listenTo(this.model, 'change:fileName', this.updateFileName); - this.listenTo(this.model, 'change:fileSize', this.updateFileSize); - this.listenTo(this.model, 'change:fileTime', this.updateFileTime); - this.listenTo(this.model, 'change:fileType', this.updateFileType); - this.listenTo(this.model, 'change:value', this.updateValue); + UI: _.defaults({ + items: '.pl-listbox-i', + checkingInputs: '.pl-listbox-input input' + }, ListEditorBaseView.prototype.UI), - this.listenTo(this.model, 'change:hintText', this.updateHintText); - this.listenTo(this.model, 'change:errorText', this.updateErrorText); - this.listenTo(this.model, 'change:warningText', this.updateWarningText); + initialize: function (options) { + //@TODO Реализовать обработку значений по умолчанию! + ListEditorBaseView.prototype.initialize.call(this, options); + }, - this.listenTo(this.model, 'invalid', this.onInvalidHandler); + updateGrouping: function(){ + var isGrouped = this.model.get('groupValueSelector') != null; - var acceptTypes = this.model.get('acceptTypes'); - acceptTypes.onChange(this.updateAcceptTypes.bind(this)); + if(isGrouped){ + this.strategy = new ListBoxViewGroupStrategy(this); + }else{ + this.strategy = new ListBoxViewPlainStrategy(this); + } }, - updateProperties: function(){ - ControlView.prototype.updateProperties.call(this); + updateValue: function(){ + this.ui.items.removeClass('pl-listbox-i-chosen'); + this.ui.checkingInputs.prop('checked', false); - this.updateLabelText(); - this.updateFileName(); - this.updateFileSize(); - this.updateFileType(); - this.updateFileTime(); - this.updateAcceptTypes(); - this.updateValue(); + var value = this.model.get('value'), + choosingItem, $choosingItem; - this.updateHintText(); - this.updateErrorText(); - this.updateWarningText(); - }, + if(!this.isMultiselect() && value !== undefined && value !== null){ + value = [value]; + } - updateLabelText: function () { - var labelText = this.model.get('labelText'); + if($.isArray(value)){ + for(var i= 0, ii=value.length; i < ii; i++){ + choosingItem = this.model.itemByValue(value[i]); + $choosingItem = this._getElementByItem(choosingItem); - if(labelText != '') { - this.ui.label - .css({display: 'inline-block'}) - .text(labelText); - } else { - this.ui.label.css({display: 'none'}); + if($choosingItem){ + $choosingItem.addClass('pl-listbox-i-chosen'); + $choosingItem.find('.pl-listbox-input input').prop('checked', true); + } + } } }, - updateAcceptTypes: function () { - var acceptTypes = this.model.get('acceptTypes'); - if (acceptTypes.length === 0) { - this.ui.input.removeAttr('accept'); - } else { - var accept = acceptTypes.toArray().join(','); - this.ui.input.attr('accept', accept); + updateSelectedItem: function(ignoreWasRendered){ + if(!this.wasRendered && ignoreWasRendered != true){ + return; } - }, - updateFocusable: function () { - var focusable = this.model.get('focusable'); + this.ui.items.removeClass('pl-listbox-i-selected'); - if (focusable) { - this.ui.control.attr('tabindex', 0); - } else { - this.ui.control.removeAttr('tabindex'); + var selectedItem = this.model.get('selectedItem'), + $selectedItem = this._getElementByItem(selectedItem); + + if( $selectedItem && !$selectedItem.hasClass('pl-disabled-list-item') ) { + $selectedItem.addClass('pl-listbox-i-selected'); } }, - updateText: function () { - var text = this.model.get('text'); - this.ui.btnPick.attr('title', text); - }, + render: function () { + this.prerenderingActions(); - updateHintText: function(){ - var hintText = this.model.get('hintText'); - if(hintText){ - this.ui.hintText - .text(hintText) - .removeClass('hidden'); - }else{ - this.ui.hintText - .text('') - .addClass('hidden'); - } + var preparedItems = this.strategy.prepareItemsForRendering(); + var template = this.strategy.getTemplate(); - }, + this.removeChildElements(); - updateErrorText: function(){ - var errorText = this.model.get('errorText'); - if(errorText){ - this.ui.errorText - .text(errorText) - .removeClass('hidden'); - }else{ - this.ui.errorText - .text('') - .addClass('hidden'); - } + this.$el.html(template(preparedItems)); + this.bindUIElements(); - }, + this.strategy.appendItemsContent(preparedItems); - updateWarningText: function(){ - var warningText = this.model.get('warningText'); - if(warningText){ - this.ui.warningText - .text(warningText) - .removeClass('hidden'); - }else{ - this.ui.warningText - .text('') - .addClass('hidden'); - } + this.updateProperties(); + + this.trigger('render'); + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; }, - updateEnabled: function () { - ControlView.prototype.updateEnabled.call(this); + getItems: function(){ + return this.model.get('items'); + }, - var isEnabled = this.model.get('enabled'); + getItemTemplate: function(){ + return this.model.get('itemTemplate'); + }, - this.ui.input.prop('disabled', !isEnabled); - this.ui.btnRemove.prop('disabled', !isEnabled); - this.ui.btnPick.toggleClass('disabled', !isEnabled); + getGroupValueSelector: function(){ + return this.model.get('groupValueSelector'); + }, + isMultiselect: function(){ + return this.model.get('multiSelect'); }, - updateFileName: function () { - var fileName = this.model.get('fileName'); - this.ui.fileUpload.text(fileName); - this.ui.fileDownloadUrl.text(fileName); + isFocusable: function () { + return this.model.get('focusable'); }, - updateFileSize: function () { - //var fileSize = this.model.get('fileSize'); - // - //var text = ''; - //if (typeof fileSize !== 'undefined' && fileSize !== null) { - // text = InfinniUI.format.humanFileSize(fileSize); - //} - //this.ui.fileSize.text(text); + getGroupItemTemplate: function(){ + return this.model.get('groupItemTemplate'); }, - updateFileInfo: function() { - return; - var model = this.model; - var - value = model.get('value'), - fileName = model.get('fileName'); + onChangeHandler: function(){ + var $checked = this.ui.checkingInputs.filter(':checked').parent().parent(), + valueForModel = null, + model = this.model, + val; - if (!value || value.length === 0) { - this.ui.info.toggleClass('hidden', true); - this.ui.empty.toggleClass('hidden', false); - } else { - if (!fileName || fileName.length === 0) { - fileName = 'Скачать файл'; + if(this.isMultiselect()){ + valueForModel = []; + + $checked.each(function(i, el){ + val = $(el).data('pl-data-item'); + valueForModel.push(model.valueByItem(val)); + }); + + }else{ + if($checked.length > 0){ + valueForModel = model.valueByItem($checked.data('pl-data-item')); } - this.ui.download.text(fileName); - this.ui.info.toggleClass('hidden', false); - this.ui.empty.toggleClass('hidden', true); } - }, - updateFileTime: function () { - var time = this.model.get('fileTime'); - - //@TODO Update file's datetime on view + this.model.set('value', valueForModel); }, - updateFileType: function () { - var fileType = this.model.get('fileType'); - - //@TODO Update file's mime type on view - }, + updateDisabledItem: function(){ + var model = this.model, + disabledItemCondition = model.get('disabledItemCondition'); - updateValue: function () { - var model = this.model; - var value = model.get('value'); + this.ui.items.removeClass('pl-disabled-list-item'); + this.ui.checkingInputs.attr('disabled', null); - var fileEmpty = false, - fileUpload = false, - fileDownload = false; + if( disabledItemCondition != null ){ + this.ui.items.each(function (i, el) { + var $el = $(el), + item = $el.data('pl-data-item'), + isDisabled = disabledItemCondition( undefined, {value: item}); - if (value === null || typeof value === 'undefined') { - //No file - fileEmpty = value === null || typeof value === 'undefined'; - this.ui.input.val(null); - this.updateUrl(null); - } else if (value && typeof value === 'object') { - //File instance - fileUpload = value && typeof value === 'object'; - this.updateUrl(null); - } else { - //Url - fileDownload = true; - this.updateUrl(value); + if(isDisabled){ + if( $el.hasClass('pl-listbox-i-selected') ) { + this.model.set('selectedItem', null); + } + $el.toggleClass('pl-disabled-list-item', true); + $el.find('input').attr('disabled', 'disabled'); + $el.find('button').attr('disabled', 'disabled'); + } + }) } - - this.ui.fileEmpty.toggleClass('hidden', !fileEmpty); - this.ui.fileUpload.toggleClass('hidden', !fileUpload); - this.ui.fileDownload.toggleClass('hidden', !fileDownload); - - this.ui.btnRemove.toggleClass('hidden', fileEmpty); - this.ui.btnPick.toggleClass('hidden', !fileEmpty); }, - updateUrl: function (url) { - this.ui.fileDownloadUrl.attr('href', url); - var none = url === null || typeof url === 'undefined'; - this.$el.toggleClass('pl-empty', none); - this.updateFileInfo(); + disableAll: function() { + this.ui.items.addClass('pl-disabled-list-item'); }, - onClickRemoveImageHandler: function () { - this.model.removeFile(); - this.ui.input.val(''); - }, + _getElementByItem: function(item){ + var element = _.find(this.ui.items, function(listboxItem){ + return $(listboxItem).data('pl-data-item') == item; + }); - onChangeFileHandler: function () { - var file = null; - var files = this.ui.input[0].files; + return $(element); + } +}); - if (files && files[0]) { - file = files[0]; - } - this.model.setFile(file); - }, +InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.ListBox.base', BaseListBoxView); - render: function () { - this.prerenderingActions(); +//####app/controls/listBox/baseView/viewGroupStrategy.js +function ListBoxViewGroupStrategy(listbox) { + this.listbox = listbox; +}; - this.renderTemplate(this.template); - this.updateProperties(); +_.extend(ListBoxViewGroupStrategy.prototype, { - this.trigger('render'); + prepareItemsForRendering: function(){ + var items = this.listbox.getItems(), + inputName = 'listbox-' + guid(), + result = { + isMultiselect: this.listbox.isMultiselect(), + focusable: this.listbox.isFocusable(), + inputName: inputName, + groups: [] + }, + groups = {}, + groupingFunction = this.listbox.getGroupValueSelector(); - this.postrenderingActions(); + items.forEach(function(item, index){ + var groupKey = groupingFunction(undefined, {value:item}); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop + if(! (groupKey in groups)){ + groups[groupKey] = []; + } - return this; + groups[groupKey].push({index: index, item: item}); + }); + + for(var k in groups){ + result.groups.push({ + items: groups[k] + }) + } + + return result; }, - onInvalidHandler: function () { - this.ui.input.val(null); - } + getTemplate: function(){ + return this.listbox.template.grouped; + }, -})); + appendItemsContent: function(preparedItems){ + var $listbox = this.listbox.$el, + itemTemplate = this.listbox.getItemTemplate(), + groupTitleTemplate = this.listbox.getGroupItemTemplate(), + groups = preparedItems.groups, + listbox = this.listbox, + item, itemEl, titleEl, $el, group; -//####app/controls/form/formControl.js -function FormControl(parent) { - _.superClass(FormControl, this, parent); -} + $listbox.find('.pl-listbox-group-i').each(function(i, el){ -_.inherit(FormControl, StackPanelControl); + group = groups[i]; + titleEl = groupTitleTemplate(undefined, {index: group.items[0].index, item: group}); + listbox.addChildElement(titleEl); -_.extend(FormControl.prototype, { + $el = $(el); + $el.find(".pl-listbox-group-title").append(titleEl.render()); - createControlModel: function () { - return new FormModel(); - }, + $el.find(".pl-listbox-body").each(function(j, bodyEl){ + item = group.items[j].item; + itemEl = itemTemplate(undefined, {index: group.items[j].index, item: item}); - createControlView: function (model) { - return new FormView({model: model}); - }, + listbox.addChildElement(itemEl); - onSubmit: function (callback) { - this.controlView.$el.on('submit', callback); - }, + $(bodyEl).append(itemEl.render()); + $(bodyEl).parent() + .data('pl-data-item', item); + }); - setSubmitFunction: function(func) { - this.controlModel.set('submitFunction', func); - }, + }); + } +}); +//####app/controls/listBox/baseView/viewPlainStrategy.js +function ListBoxViewPlainStrategy(listbox) { + this.listbox = listbox; +}; - getSubmitFunction: function() { - return this.controlModel.get('submitFunction'); - }, +_.extend(ListBoxViewPlainStrategy.prototype, { - setMethod: function(method) { - this.controlModel.set('method', method); - }, + prepareItemsForRendering: function(){ + var items = this.listbox.getItems(), + inputName = 'listbox-' + guid(), + result = { + isMultiselect: this.listbox.isMultiselect(), + focusable: this.listbox.isFocusable(), + inputName: inputName, + items: items.toArray() + }; - getMethod: function() { - return this.controlModel.get('method'); - }, + return result; + }, - setAction: function(action) { - this.controlModel.set('action', action); - }, + getTemplate: function(){ + return this.listbox.template.plain; + }, - getAction: function() { - return this.controlModel.get('action'); - } + appendItemsContent: function(preparedItems){ + var $listbox = this.listbox.$el, + itemTemplate = this.listbox.getItemTemplate(), + items = preparedItems.items, + listbox = this.listbox, + itemEl, $el; + + $listbox.find('.pl-listbox-body').each(function(i, el){ + $el = $(el); + itemEl = itemTemplate(undefined, {index: i, item: items[i]}); + listbox.addChildElement(itemEl); + $el.append(itemEl.render()); + $el.parent().data('pl-data-item', items[i]); + }); + } }); +//####app/controls/listBox/listBoxControl.js +function ListBoxControl(viewMode) { + _.superClass(ListBoxControl, this, viewMode); +} -//####app/controls/form/formModel.js -var FormModel = StackPanelModel.extend({ +_.inherit(ListBoxControl, ListEditorBaseControl); - defaults: _.defaults({ - submitFunction: null, - method: '', - action: '' - }, StackPanelModel.prototype.defaults) +_.extend(ListBoxControl.prototype, { -}); + createControlModel: function () { + return new ListBoxModel(); + }, -//####app/controls/form/formView.js -/** - * @class FormView - * @augments StackPanelView - */ -var FormView = StackPanelView.extend({ + createControlView: function (model, viewMode) { + if(!viewMode || ! viewMode in window.InfinniUI.viewModes.ListBox){ + viewMode = 'common'; + } - className: 'pl-form', + var ViewClass = window.InfinniUI.viewModes.ListBox[viewMode]; - tagName: 'form', + return new ViewClass({model: model}); + }, - template: { - plain: InfinniUI.Template["controls/form/template/form.tpl.html"] - }, + updateDisabledItem: function() { + this.controlView.updateDisabledItem(); + }, - events: { - 'submit': 'onSubmit' - }, + disableAll: function() { + this.controlView.disableAll(); + } - onSubmit: function (e) { - e.preventDefault(); - }, +}); - initialize: function (options) { - StackPanelView.prototype.initialize.call(this, options); - this.listenTo(this.model, 'change:method', this.updateMethod); - this.listenTo(this.model, 'change:action', this.updateAction); - }, +//####app/controls/listBox/listBoxModel.js +var ListBoxModel = ListEditorBaseModel.extend({ + initialize: function () { + ListEditorBaseModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + } +}); +//####app/controls/listBox/checkingView/listBoxView.js +var CheckingListBoxView = BaseListBoxView.extend({ + className: 'pl-listbox', - updateGrouping: function(){ - this.strategy = new StackPanelViewPlainStrategy(this); - }, + template: { + plain: InfinniUI.Template["controls/listBox/checkingView/template/listBox.tpl.html"], + grouped: InfinniUI.Template["controls/listBox/checkingView/template/listBoxGrouped.tpl.html"] + }, - render: function () { - this.prerenderingActions(); + events: _.extend( { - this.removeChildElements(); + }, BaseListBoxView.prototype.events), - var preparedItems = this.strategy.prepareItemsForRendering(); - var template = this.strategy.getTemplate(); + initialize: function (options) { + BaseListBoxView.prototype.initialize.call(this, options); + this.initDomHandlers(); + }, - this.$el.html(template(preparedItems)); + updateEnabled: function () { + ListEditorBaseView.prototype.updateEnabled.call(this); - this.strategy.appendItemsContent(preparedItems, '.pl-form-i'); + var enabled = this.model.get('enabled'); - this.bindUIElements(); - this.updateProperties(); - this.trigger('render'); + this.ui.checkingInputs.attr('disabled', !enabled); + }, - this.postrenderingActions(); + initDomHandlers: function(){ + var $listBox = this.$el, + that = this; - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - - return this; - }, + $listBox.get(0).addEventListener('click', function(e){ + e = $.event.fix(e); + var $el = $(e.target), + $currentListItem, item, isDisabledItem; - updateProperties: function() { - StackPanelView.prototype.updateProperties.call(this); + if (!that.model.get('enabled')) { + return; + } - this.updateMethod(); - this.updateAction(); - }, + while($el.get(0) != $listBox.get(0)){ + if($el.hasClass('pl-listbox-i')){ + $currentListItem = $el; + } - updateMethod: function() { - var method = this.model.get('method'); + $el = $el.parent(); + } - this.$el.attr('method', method); - }, + if($currentListItem && $currentListItem.length > 0){ + item = $currentListItem.data('pl-data-item'); + isDisabledItem = that.model.isDisabledItem(item); - updateAction: function() { - var action = this.model.get('action'); + if(!isDisabledItem) { + that.model.toggleValue(item); + } - this.$el.attr('action', action); - } + that.model.set('selectedItem', item); + } + }, true); + } }); -//####app/controls/frame/frameControl.js -/** - * - * @constructor - * @augments Control - * @mixes editorBaseControlMixin - */ -var FrameControl = function () { - _.superClass(FrameControl, this); - this.initialize_editorBaseControl(); -}; +InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.ListBox.checking', CheckingListBoxView); +//####app/controls/listBox/commonView/listBoxView.js +var CommonListBoxView = BaseListBoxView.extend({ + className: 'pl-listbox pl-listbox-common-mode', -_.inherit(FrameControl, Control); + events: _.extend( { -_.extend(FrameControl.prototype, { + }, BaseListBoxView.prototype.events), - createControlModel: function () { - return new FrameModel(); + initialize: function (options) { + BaseListBoxView.prototype.initialize.call(this, options); + this.initDomHandlers(); }, - createControlView: function (model) { - return new FrameView({model: model}); - } + initDomHandlers: function(){ + var $listBox = this.$el, + that = this; -}, editorBaseControlMixin); -//####app/controls/frame/frameModel.js -var FrameModel = ControlModel.extend(_.extend({ + $listBox.get(0).addEventListener('click', function(e){ + e = $.event.fix(e); + var $el = $(e.target), + $currentListItem, item, isDisabledItem; - defaults: _.defaults({}, - editorBaseModelMixin.defaults_editorBaseModel, - ControlModel.prototype.defaults - ), + while($el.get(0) != $listBox.get(0)){ + if($el.hasClass('pl-listbox-i')){ + $currentListItem = $el; + } - initialize: function(){ - ControlModel.prototype.initialize.apply(this, arguments); - this.initialize_editorBaseModel(); + $el = $el.parent(); + } + + if($currentListItem.length > 0){ + item = $currentListItem.data('pl-data-item'); + isDisabledItem = that.model.isDisabledItem(item); + + if(!isDisabledItem){ + that.model.toggleValue(item); + } + + that.model.set('selectedItem', item); + } + + }, true); } -}, editorBaseModelMixin)); -//####app/controls/frame/frameView.js -/** - * @class FrameView - * @augments ControlView - * @mixes editorBaseViewMixin - */ -var FrameView = ControlView.extend(_.extend({}, editorBaseViewMixin, /** @lends FrameView.prototype */{ +}); - className: 'pl-frame', +InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.ListBox.common', CommonListBoxView); +//####app/controls/popupButton/commonView/popupButtonView.js +var CommonPopupButtonView = ContainerView.extend({ - template: InfinniUI.Template["controls/frame/template/frame.tpl.html"], + className: 'pl-popup-button', - UI: _.extend({}, editorBaseViewMixin.UI, { - iframe: 'iframe' - }), + template: InfinniUI.Template["controls/popupButton/commonView/template/popupButton.tpl.html"], + dropdownTemplate: InfinniUI.Template["controls/popupButton/commonView/template/popupButton.dropdown.tpl.html"], - initialize: function () { - ControlView.prototype.initialize.apply(this); + events: { + 'click': 'onClickHandler' }, - initHandlersForProperties: function(){ - ControlView.prototype.initHandlersForProperties.call(this); - editorBaseViewMixin.initHandlersForProperties.call(this); + UI: { + button: '.pl-popup-button__button', + grip: '.pl-popup-button__grip' }, updateProperties: function(){ - ControlView.prototype.updateProperties.call(this); - editorBaseViewMixin.updateProperties.call(this); - }, - - updateValue: function(){ - var value = this.model.get('value'); + ContainerView.prototype.updateProperties.call(this); - this.ui.iframe.attr('src', value); + this.updateContent(); }, - getData: function () { - return _.extend( - {}, - ControlView.prototype.getData.call(this), - editorBaseViewMixin.getData.call(this), - { + updateContent: CommonButtonView.prototype.updateContent, + updateText: CommonButtonView.prototype.updateText, - } - ); + getButtonElement: function(){ + return this.ui.button; }, render: function () { - var model = this.model; - this.prerenderingActions(); - this.renderTemplate(this.template); + + var items = this.model.get('items').toArray(); + var template = this.template; + + this.removeChildElements(); + + this.$el.html(template({items: items})); + this.bindUIElements(); + + this.$dropdown = this.renderDropdown(); + + this.$dropdown.on('click', this.close.bind(this)); this.updateProperties(); this.trigger('render'); + this.postrenderingActions(); //devblockstart window.InfinniUI.global.messageBus.send('render', {element: this}); //devblockstop return this; - } + }, -})); + renderDropdown: function(){ + var template = this.dropdownTemplate; + var items = this.model.get('items').toArray(); + var $result = $(template({items: items})); -//####app/controls/gridPanel/gridPanelControl.js -/** - * - * @param parent - * @constructor - * @augments ContainerControl - */ -function GridPanelControl(parent) { - _.superClass(GridPanelControl, this, parent); -} + this.appendItemsContent($result, items); -_.inherit(GridPanelControl, ContainerControl); + return $result; + }, + + appendItemsContent: function($dropdown, items){ + var that = this, + itemTemplate = this.model.get('itemTemplate'), + itemEl, $el; + + $dropdown.find('.pl-popup-button__item').each(function(i, el){ + $el = $(el); + itemEl = itemTemplate(undefined, {index: i, item: items[i]}); + that.addChildElement(itemEl); + $el.append(itemEl.render()); + }); + }, + + open: function(){ + var that = this; + + $('body').append(this.$dropdown); + + this.$dropdown.addClass('open'); + this.alignDropdown(); + + var $ignoredElements = this.$dropdown.add (this.ui.grip); + }, + + close: function(){ + this.$dropdown.removeClass('open'); + this.$dropdown.detach(); + }, + + alignDropdown: function(){ + var offset = this.$el.offset(), + $elHeight = this.$el.height(), + $elWidth = this.$el.width(), + dropdownList = this.$dropdown.find('.pl-popup-button__items')[0], + $dropdownHeight = dropdownList.offsetHeight, + $dropdownWidth = dropdownList.offsetWidth, + left = offset.left, + top = offset.top + $elHeight; -_.extend(GridPanelControl.prototype, - /** @lends GridPanelControl.prototype */ - { - createControlModel: function () { - return new GridPanelModel(); - }, + if( (offset.left + $dropdownWidth) >= window.innerWidth ) { + left += ($elWidth - $dropdownWidth); + } - createControlView: function (model) { - return new GridPanelView({model: model}); + if( (top + $dropdownHeight) >= window.innerHeight ) { + top -= ($elHeight + $dropdownHeight + 2); } - } -); + this.$dropdown.offset({ + top: top, + left: left + }); + }, -//####app/controls/gridPanel/gridPanelModel.js -/** - * @constructor - * @augments ContainerModel - */ -var GridPanelModel = ContainerModel.extend( - /** @lends GridPanelModel.prototype */ - { - initialize: function () { - ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + toggle: function(){ + if(!this.$dropdown.hasClass('open')){ + this.open(); + }else{ + this.close(); } - } -); -//####app/controls/gridPanel/gridPanelView.js -/** - * @class - * @augments ControlView - */ -var GridPanelView = ContainerView.extend( - /** @lends GridPanelView.prototype */ - { - className: 'pl-grid-panel pl-clearfix', + }, - columnCount: 12, + onClickHandler: function(){ + this.toggle(); + }, - template: { - row: InfinniUI.Template["controls/gridPanel/template/row.tpl.html"] - }, + updateGrouping: function(){} - initialize: function (options) { - ContainerView.prototype.initialize.call(this, options); - }, +}); - render: function () { - this.prerenderingActions(); +InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.PopupButton.common', CommonPopupButtonView); - this.removeChildElements(); +//####app/controls/popupButton/popupButtonControl.js +function PopupButtonControl(viewMode) { + _.superClass(PopupButtonControl, this, viewMode); +} + +_.inherit(PopupButtonControl, ContainerControl); + +_.extend(PopupButtonControl.prototype, /** @lends PopupButtonControl.prototype */ { + + createControlModel: function () { + return new PopupButtonModel(); + }, + + createControlView: function (model, viewMode) { + if(!viewMode || ! viewMode in window.InfinniUI.viewModes.PopupButton){ + viewMode = 'common'; + } + + var ViewClass = window.InfinniUI.viewModes.PopupButton[viewMode]; + + return new ViewClass({model: model}); + } + +}, buttonControlMixin); + - this.renderItemsContents(); - this.updateProperties(); - this.trigger('render'); +//####app/controls/popupButton/popupButtonModel.js +var PopupButtonModel = ContainerModel.extend({ + +}); +//####app/controls/popupButton/forMenuView/popupButtonView.js +var ForMenuPopupButtonView = CommonPopupButtonView.extend({ - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, + tagName: 'a', + className: 'pl-popup-button', + attributes: { + href: 'javascript:;' + }, - renderItemsContents: function(){ - var items = this.model.get('items'), - itemTemplate = this.model.get('itemTemplate'), - view = this, - row = [], - rowSize = 0, - element, item; + template: InfinniUI.Template["controls/popupButton/forMenuView/template/popupButton.tpl.html"], + dropdownTemplate: InfinniUI.Template["controls/popupButton/commonView/template/popupButton.dropdown.tpl.html"], - //this.$el.hide(); - items.forEach(function(item, i){ - element = itemTemplate(undefined, {item: item, index: i}); - var span = element.getColumnSpan(); - if (rowSize + span > view.columnCount) { - view.renderRow(row); - row.length = 0; - rowSize = 0; - } + events: { + 'click': 'onClickGripHandler' + //'click .pl-popup-button__button': 'onClickHandler' + }, - row.push(element); - rowSize += span; - }); + UI: { + button: '.pl-popup-button__button', + grip: '.pl-popup-button__grip' + }, - if (row.length) { - view.renderRow(row); - } - //this.$el.show(); - }, + updateProperties: function(){ + ContainerView.prototype.updateProperties.call(this); - renderRow: function (row) { - var view = this; - var $row = $(this.template.row()); - $row.append(row.map(function(element) { - view.addChildElement(element); - return element.render(); - })); - this.$el.append($row); - }, + this.updateContent(); + }, - updateGrouping: function(){} - } -); + updateContent: CommonButtonView.prototype.updateContent, + updateText: CommonButtonView.prototype.updateText, -//####app/controls/icon/iconControl.js -/** - * - * @param parent - * @constructor - * @augments Control - */ -function IconControl() { - _.superClass(IconControl, this); -} + updateHorizontalAlignment: function(){ + var horizontalAlignment = this.model.get('horizontalAlignment'); + var that = this; + var $el; -_.inherit(IconControl, Control); + this.whenReady( + function(){ + $el = that.$el.parent().parent(); + return $el.length > 0; + }, -_.extend(IconControl.prototype, { + function(){ + if(horizontalAlignment == 'Right'){ + $el + .addClass('pull-right'); + }else{ + $el + .removeClass('pull-right'); + } + } + ); - createControlModel: function () { - return new IconModel(); }, - createControlView: function (model) { - return new IconView({model: model}); - } - -}); -//####app/controls/icon/iconModel.js -/** - * @class - * @augments ControlModel - */ -var IconModel = ControlModel.extend({ - - defaults: _.defaults({ - value: null, - focusable: false + getButtonElement: function(){ + return this.ui.button; + }, - }, ControlModel.prototype.defaults), + render: function () { + this.prerenderingActions(); - initialize: function () { - ControlModel.prototype.initialize.apply(this, arguments); - } + var items = this.model.get('items').toArray(); + var template = this.template; -}); -//####app/controls/icon/iconView.js -/** - * @class IconView - * @arguments ControlView - */ -var IconView = ControlView.extend({ + this.removeChildElements(); - className: 'pl-icon fa', + this.$el.html(template({items: items})); + this.bindUIElements(); - tagName: 'i', + this.$dropdown = this.renderDropdown(); - render: function(){ - this.prerenderingActions(); this.updateProperties(); + this.trigger('render'); + this.postrenderingActions(); //devblockstart window.InfinniUI.global.messageBus.send('render', {element: this}); @@ -15595,573 +12425,515 @@ var IconView = ControlView.extend({ return this; }, - renderIcon: function () { - var value = this.model.get('value'); - this.switchClass('fa', value); - }, - - initHandlersForProperties: function () { - ControlView.prototype.initHandlersForProperties.call(this); - this.listenTo(this.model, 'change:value', this.updateValue); - }, - - updateProperties: function () { - ControlView.prototype.updateProperties.call(this); - this.updateValue(); - }, - - updateFocusable: function () { - var focusable = this.model.get('focusable'); - - if (focusable) { - this.$el.attr('tabindex', 0); - } else { - this.$el.removeAttr('tabindex'); - } - }, - - updateValue: function () { - this.renderIcon(); - } - -}); - -//####app/controls/imageBox/imageBoxControl.js -/** - * - * @param parent - * @constructor - * @augments Control - * @mixes editorBaseControlMixin - */ -function ImageBoxControl(parent) { - _.superClass(ImageBoxControl, this, parent); - this.initialize_editorBaseControl(); -} + renderDropdown: function(){ + var template = this.dropdownTemplate; + var items = this.model.get('items').toArray(); + var $result = $(template({items: items})); -_.inherit(ImageBoxControl, Control); + this.appendItemsContent($result, items); + $result.on('click', function () { + this.close(); + }.bind(this)); + return $result; + }, -_.extend(ImageBoxControl.prototype, { + appendItemsContent: function($dropdown, items){ + var that = this, + itemTemplate = this.model.get('itemTemplate'), + itemEl, $el; - createControlModel: function () { - return new ImageBoxModel(); + $dropdown.find('.pl-popup-button__item').each(function(i, el){ + $el = $(el); + itemEl = itemTemplate(undefined, {index: i, item: items[i]}); + that.addChildElement(itemEl); + $el.append(itemEl.render()); + }); }, - createControlView: function (model) { - return new ImageBoxView({model: model}); - } + open: function(){ + var that = this; + var $parent = this.$el.parent(); -}, editorBaseControlMixin); + $('body').append(this.$dropdown); + this.$dropdown.addClass('open'); + $parent.addClass('open'); -//####app/controls/imageBox/imageBoxModel.js -/** - * @constructor - * @augments ControlModel - * @mixes editorBaseModelMixin - */ -var ImageBoxModel = ControlModel.extend( _.extend({ + this.alignDropdown(); - defaults: _.defaults({ - text: 'Выбрать изображение' - }, - editorBaseModelMixin.defaults_editorBaseModel, - ControlModel.prototype.defaults - ), + var $ignoredElements = this.$dropdown.add (this.$el); + new ActionOnLoseFocus($ignoredElements, function(){ + that.close(); + }); + }, - initialize: function () { - ControlModel.prototype.initialize.apply(this, arguments); - this.initialize_editorBaseModel(); + close: function(){ + this.$dropdown.removeClass('open'); + this.$el.parent().removeClass('open'); + this.$dropdown.detach(); + }, + + alignDropdown: function(){ + var horizontalAlignment = this.model.get('horizontalAlignment'); + var $el = this.$el.parent(); + var offset = $el.offset(); + var top = offset.top + $el.height()- 2; + var $dropdownMenu = this.$dropdown.find('.dropdown-menu'); + var left; - this.set('acceptTypes', new Collection()); - this.on('change:file', this.onChangeFileHandler); + if(horizontalAlignment == "Right"){ + left = offset.left - ($dropdownMenu.width() - $el.width()); + }else{ + left = offset.left; + } - this.on("invalid", function(model, error) { - this.set('errorText', error); + this.$dropdown.offset({ + top: top, + left: left }); }, - validate: function (attrs, options) { - var file = attrs.file; - var maxSize = this.get('maxSize'); - var acceptTypes = this.get('acceptTypes'); - if (file) { - if (maxSize) { - if (file.size > maxSize) { - return 'Размер выбранного файла ' + (file.size/(1024*1024)).toFixed(1) + 'Мб больше допустимого размера ' + (maxSize/(1024*1024)).toFixed(1) + 'Мб'; - } - } + onClickGripHandler: function(){ + this.toggle(); + }, - if (acceptTypes.length && !acceptTypes.contains(file.type)) { - return 'Загрузка данного типа файла не разрешена'; - } + updateGrouping: function(){}, + + whenReady: function(conditionFunction, onConditionFunction, n){ + var that = this; + + if(n === undefined){ + n = 100; } - }, - setFile: function (file) { - if (this.set('file', file, {validate: true})) { - this.set('errorText', ''); + if(!conditionFunction()){ + if(n>0){ + setTimeout( function(){ + that.whenReady(conditionFunction, onConditionFunction, n-1); + }, 10); + } + }else{ + onConditionFunction(); } - }, + } - removeFile: function () { - this.setFile(null); - }, +}); - onChangeFileHandler: function (model, file) { - //this.stopLoadingFile(); - //if (file) { - // var fileLoader = this.loadPreview(file); - // - // this.fileLoader = fileLoader; - // - // fileLoader.then(function (file, content) { - // model.set('value', content); - // }, function (err) { - // console.log(err); - // }); - //} else { - // model.set('value', null); - //} - }, +InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI, 'viewModes.PopupButton.forMenu', ForMenuPopupButtonView); - //stopLoadingFile: function () { - // var fileLoader = this.fileLoader; - // if (fileLoader && fileLoader.state() === 'pending') { - // fileLoader.reject(); - // } - //}, - // - //loadPreview: function (file) { - // var defer = $.Deferred(); - // var reader = new FileReader(); - // reader.onload = (function (file) { - // return function (event) { - // defer.resolve(file, event.target.result); - // }; - // }(file)); - // reader.onerror = function (event) { - // defer.reject(event); - // }; - // reader.readAsDataURL(file); - // return defer.promise(); - //} +//####app/controls/stackPanel/stackPanelControl.js +/** + * + * @param parent + * @constructor + * @augments ContainerControl + */ +function StackPanelControl(viewMode) { + _.superClass(StackPanelControl, this, viewMode); +} + +_.inherit(StackPanelControl, ContainerControl); + +_.extend(StackPanelControl.prototype, + /** @lends StackPanelControl.prototype */ + { + createControlModel: function () { + return new StackPanelModel(); + }, + + createControlView: function (model, viewMode) { + var view = new StackPanelView({model: model}); + + view.viewMode = viewMode; + + return view; + } + } +); + -}, editorBaseModelMixin)); -//####app/controls/imageBox/imageBoxView.js +//####app/controls/stackPanel/stackPanelModel.js +/** + * @constructor + * @augments ContainerModel + */ +var StackPanelModel = ContainerModel.extend( + /** @lends StackPanelModel.prototype */ + { + initialize: function () { + ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + } + } +); +//####app/controls/stackPanel/baseView/stackPanelView.js /** + * @class * @augments ControlView - * @mixes editorBaseViewMixin - * @constructor */ -var ImageBoxView = ControlView.extend(/** @lends ImageBoxView.prototype */ _.extend({}, editorBaseViewMixin, { +var StackPanelView = ContainerView.extend( + /** @lends StackPanelView.prototype */ + { + tagName: 'ul', + className: 'pl-stack-panel pl-clearfix', - className: 'pl-imagebox', + template: { + plain: InfinniUI.Template["controls/stackPanel/baseView/template/stackPanel.tpl.html"], + grouped: InfinniUI.Template["controls/stackPanel/baseView/template/stackPanelGrouped.tpl.html"] + }, - template: InfinniUI.Template["controls/imageBox/template/imageBox.tpl.html"], + UI: { + items: '.stackpanel-items' + }, - UI: _.extend({}, editorBaseViewMixin.UI, { - input: 'input', - img: 'img', - file: '.pl-image-file', - remove: '.pl-image-remove', - uploadButton: '.pl-image-file-upload-button' - }), + initialize: function (options) { + ContainerView.prototype.initialize.call(this, options); - events: { - 'change input': 'onChangeFileHandler', - 'click .pl-image-remove': 'onClickRemoveImageHandler' - }, + this.initOrientation(); + }, + updateGrouping: function(){ + var isGrouped = this.model.get('groupValueSelector') != null; - initHandlersForProperties: function(){ - ControlView.prototype.initHandlersForProperties.call(this); + if(isGrouped){ + this.strategy = new StackPanelViewGroupStrategy(this); + }else{ + this.strategy = new StackPanelViewPlainStrategy(this); + } + }, - this.listenTo(this.model, 'change:value', this.updateValue); - this.listenTo(this.model, 'change:hintText', this.updateHintText); - this.listenTo(this.model, 'change:errorText', this.updateErrorText); - this.listenTo(this.model, 'change:warningText', this.updateWarningText); - }, + render: function () { + this.prerenderingActions(); - updateProperties: function(){ - ControlView.prototype.updateProperties.call(this); + this.removeChildElements(); - this.updateValue(); - this.updateHintText(); - this.updateErrorText(); - this.updateWarningText(); - }, + var preparedItems = this.strategy.prepareItemsForRendering(); + var template = this.strategy.getTemplate(); - updateFocusable: function () { - var focusable = this.model.get('focusable'); + this.$el.html(template(preparedItems)); - if (focusable) { - this.ui.file.attr('tabindex', 0); - } else { - this.ui.file.removeAttr('tabindex'); - } - }, + this.strategy.appendItemsContent(preparedItems); - updateText: function () { - var text = this.model.get('text'); - this.ui.uploadButton.text(text); - }, + this.bindUIElements(); + this.updateProperties(); - updateEnabled: function () { - ControlView.prototype.updateEnabled.call(this); - var isEnabled = this.model.get('enabled'); - this.ui.input.prop('disabled', !isEnabled); - }, + this.trigger('render'); + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, - updateValue: function () { - var model = this.model; - var value = model.get('value'); + initOrientation: function () { + this.listenTo(this.model, 'change:orientation', this.updateOrientation); + this.updateOrientation(); + }, + + updateOrientation: function () { + var orientation = this.model.get('orientation'); + this.$el.toggleClass('horizontal-orientation', orientation == 'Horizontal'); + this.$el.toggleClass('pl-stack-panel_horizontal', orientation == 'Horizontal'); + }, - if (value && typeof value === 'object') { - //Native FileAPI File instance, start loading preview - this.stopLoadingFile(); - var fileLoader = this.loadPreview(value); + getItems: function(){ + return this.model.get('items'); + }, - this.fileLoader = fileLoader; + getItemTemplate: function(){ + return this.model.get('itemTemplate'); + }, - fileLoader.then(function (file, content) { - this.updateUrl(content); - }.bind(this), function (err) { - console.log(err); - }); - } else { - this.updateUrl(value); - } - }, + getGroupValueSelector: function(){ + return this.model.get('groupValueSelector'); + }, - updateUrl: function (url) { - this.ui.img.attr('src', url); - var none = url === null || typeof url === 'undefined'; - this.$el.toggleClass('pl-empty', none); - }, + getGroupItemTemplate: function(){ + return this.model.get('groupItemTemplate'); + }, + } +); - stopLoadingFile: function () { - var fileLoader = this.fileLoader; - if (fileLoader && fileLoader.state() === 'pending') { - fileLoader.reject(); - } - }, +//####app/controls/stackPanel/baseView/viewGroupStrategy.js +function StackPanelViewGroupStrategy(stackPanel) { + this.stackPanel = stackPanel; +} - loadPreview: function (file) { - var defer = $.Deferred(); - var reader = new FileReader(); - reader.onload = (function (file) { - return function (event) { - defer.resolve(file, event.target.result); - }; - }(file)); - reader.onerror = function (event) { - defer.reject(event); - }; - reader.readAsDataURL(file); - return defer.promise(); - }, +_.extend(StackPanelViewGroupStrategy.prototype, { - onClickRemoveImageHandler: function () { - this.model.removeFile(); - this.ui.input.val(''); - }, + groupTemplate: InfinniUI.Template["controls/stackPanel/baseView/template/stackPanelGroup.tpl.html"], - onChangeFileHandler: function () { - var file = null; - var files = this.ui.input[0].files; + prepareItemsForRendering: function(){ + var items = this.stackPanel.getItems(), + inputName = 'listbox-' + guid(), + result = { + inputName: inputName, + groups: [] + }, + groups = {}, + groupingFunction = this.stackPanel.getGroupValueSelector(); - if (files && files[0]) { - file = files[0]; - } - this.model.setFile(file); - }, + items.forEach(function(item, index){ + var groupKey = groupingFunction(undefined, {value:item}); - render: function () { - this.prerenderingActions(); + if(! (groupKey in groups)){ + groups[groupKey] = []; + } - this.renderTemplate(this.template); - this.updateProperties(); + groups[groupKey].push(item); + }); - this.trigger('render'); + for(var k in groups){ + if (!groups.hasOwnProperty(k)) { + continue; + } + result.groups.push({ + items: groups[k], + indices: groups[k].map(function (item) { + return items.indexOf(item); + }) + }); + } - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - } + return result; + }, -})); + getTemplate: function(){ + return this.stackPanel.template.grouped; + }, -//####app/controls/indeterminateCheckBox/indeterminateCheckBoxControl.js -function IndeterminateCheckBoxControl(parent) { - _.superClass(IndeterminateCheckBoxControl, this, parent); - this.initialize_editorBaseControl(); -} + /** + * + * @param {Object} preparedItems + * @param {Array} preparedItems.groups + */ + appendItemsContent: function (preparedItems) { + var + stackPanel = this.stackPanel, + $stackPanel = stackPanel.$el, + groupTemplate = this.groupTemplate, + groupHeaderTemplate = this.stackPanel.getGroupItemTemplate(), + itemTemplate = this.stackPanel.getItemTemplate(), + $groups, + groups = preparedItems.groups; -_.inherit(IndeterminateCheckBoxControl, CheckBoxControl); + $groups = groups.map(function (group, groupIndex) { -_.extend(IndeterminateCheckBoxControl.prototype, { + var $items, + items = group.items || [], + indices = group.indices || [], + $group = $(groupTemplate({items: items})), + groupHeader = groupHeaderTemplate(null, { + index: indices[0], //Индекс любого элемента в этой группе + item: group + }); - createControlModel: function () { - return new IndeterminateCheckBoxModel(); - }, + stackPanel.addChildElement(groupHeader); - createControlView: function (model) { - return new IndeterminateCheckBoxView({model: model}); - } + $items = items.map(function (item, itemIndex) { + var element = itemTemplate(null, {index: indices[itemIndex], item: item}); + stackPanel.addChildElement(element); + return element.render(); + }); -}, editorBaseControlMixin); + $('.pl-stack-panel-group__header', $group).append(groupHeader.render()); + $('.pl-stack-panel-list__item', $group).each(function (i, el) { + $(el).append($items[i]); + }); -//####app/controls/indeterminateCheckBox/indeterminateCheckBoxModel.js -var IndeterminateCheckBoxModel = CheckBoxModel.extend({ + return $group; - defaults: _.defaults({ - value: 'unchecked' - }, CheckBoxModel.prototype.defaults) + }); + $stackPanel.append($groups); + } }); +//####app/controls/stackPanel/baseView/viewPlainStrategy.js +function StackPanelViewPlainStrategy(stackPanel) { + this.stackPanel = stackPanel; +}; -//####app/controls/indeterminateCheckBox/indeterminateCheckBoxView.js -/** - * @class IndeterminateCheckBoxView - * @augments ControlView - * @mixes editorBaseViewMixin - */ -var IndeterminateCheckBoxView = CheckBoxView.extend({ +_.extend(StackPanelViewPlainStrategy.prototype, { - className: 'pl-indeterminate-checkbox', + prepareItemsForRendering: function(){ + var items = this.stackPanel.getItems(), + result = { + items: items.toArray() + }; - onClickHandler: function () { - var model = this.model; + return result; + }, - var enabled = model.get('enabled'); - if (enabled) { - var newValue = model.get('value'); - newValue = newValue === 'indeterminate' ? 'unchecked' : newValue === 'unchecked' ? 'checked' : 'unchecked'; - model.set('value', newValue); - } - }, + getTemplate: function(){ + return this.stackPanel.template.plain; + }, - updateValue: function () { - var value = this.model.get('value'); - if( value === 'checked' ) { - this.ui.input.prop('indeterminate', false); - this.ui.input.prop('checked', true); - } else if( value === 'unchecked' ) { - this.ui.input.prop('indeterminate', false); - this.ui.input.prop('checked', false); - } else if( value === 'indeterminate' ) { - this.ui.input.prop('checked', false); - this.ui.input.prop('indeterminate', true); - } + appendItemsContent: function(preparedItems, childElementsClass){ + var $stackPanel = this.stackPanel.$el, + itemTemplate = this.stackPanel.getItemTemplate(), + items = preparedItems.items, + stackPanel = this.stackPanel, + itemEl, $el; - } + childElementsClass = childElementsClass || '.pl-stack-panel-i'; + + $stackPanel.find(childElementsClass).each(function(i, el){ + $el = $(el); + itemEl = itemTemplate(undefined, {index: i, item: items[i]}); + stackPanel.addChildElement(itemEl); + $el.append(itemEl.render()); + + $el.parent().data('pl-data-item', items[i]); + }); + } }); -//####app/controls/link/linkElementControl.js +//####app/controls/tablePanel/tablePanelControl.js /** * * @param parent * @constructor - * @augments Control + * @augments ContainerControl */ -function LinkElementControl() { - _.superClass(LinkElementControl, this); +function TablePanelControl(parent) { + _.superClass(TablePanelControl, this, parent); } -_.inherit(LinkElementControl, ButtonControl); - -_.extend( - LinkElementControl.prototype, { +_.inherit(TablePanelControl, ContainerControl); +_.extend(TablePanelControl.prototype, + /** @lends TablePanelControl.prototype */ + { createControlModel: function () { - return new LinkElementModel(); + return new TablePanelModel(); }, createControlView: function (model) { - return new LinkElementView({model: model}); + return new TablePanelView({model: model}); } + } +); - }); -//####app/controls/link/linkElementModel.js +//####app/controls/tablePanel/tablePanelModel.js /** - * @class - * @augments ButtonModel + * @constructor + * @augments ContainerModel */ -var LinkElementModel = ButtonModel.extend({ - - defaults: _.defaults({ - href: "javascript:;", - target: "self" - }, ButtonModel.prototype.defaults), - - initialize: function () { - ButtonModel.prototype.initialize.apply(this, arguments); +var TablePanelModel = ContainerModel.extend( + /** @lends TablePanelModel.prototype */ + { + initialize: function () { + ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + } } - -}); - -//####app/controls/link/linkElementView.js +); +//####app/controls/tablePanel/tablePanelView.js /** - * @class LinkElementView - * @augments CommonButtonView + * @class + * @augments ControlView */ -var LinkElementView = CommonButtonView.extend({ - - tagName: 'a', - - className: 'pl-link', - - events: { - 'click': 'onClickHandler' - }, - - template: function(){return '';}, - - updateProperties: function(){ - CommonButtonView.prototype.updateProperties.call(this); - - this.updateHref(); - this.updateTarget(); - }, - - getButtonElement: function(){ - return this.$el; - }, - - initHandlersForProperties: function(){ - CommonButtonView.prototype.initHandlersForProperties.call(this); - - this.listenTo(this.model, 'change:href', this.updateHref); - this.listenTo(this.model, 'change:target', this.updateTarget); - }, +var TablePanelView = ContainerView.extend( + /** @lends TablePanelView.prototype */ + { + className: 'pl-table-panel', - updateHref: function() { - var newHref = this.model.get('href'), - $link = this.getButtonElement(); + initialize: function (options) { + ContainerView.prototype.initialize.call(this, options); + }, - $link.attr('href', newHref); - }, + render: function () { + this.prerenderingActions(); - updateTarget: function() { - var newTarget = this.model.get('target'), - $link = this.getButtonElement(); + this.removeChildElements(); - $link.attr('target', '_' + newTarget); - }, + this.renderItemsContents(); + this.updateProperties(); + this.trigger('render'); - onClickHandler: function(e) { - var href = this.model.get('href'); - if( href.indexOf('http://') === -1 ) { - InfinniUI.AppRouter.navigate(href, {trigger: true}); - if( e.which !== 2 ) { - e.preventDefault(); - } - } - } + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, -}); + renderItemsContents: function(){ + var items = this.model.get('items'), + itemTemplate = this.model.get('itemTemplate'), + that = this, + element, item; -//####app/controls/loaderIndicator/loaderIndicator.js -(function () { - var template = InfinniUI.Template["controls/loaderIndicator/template.tpl.html"]; - - InfinniUI.loaderIndicator = { - show: function(){ - $.blockUI({ - message: $(template()), - ignoreIfBlocked: true, - baseZ: 99999 + items.forEach(function(item, i){ + element = itemTemplate(undefined, {item: item, index: i}); + that.addChildElement(element); + that.$el + .append(element.render()); }); }, - hide: function(){ - $.unblockUI(); - } - }; - if (!InfinniUI.config.useLoaderIndicator) { - return; + updateGrouping: function(){} } +); - jQuery(function () { - var $indicator = $(template()); - $('body').append($indicator); - $.blockUI.defaults.css = {}; - $(document).ajaxStart(function () { - $.blockUI({ - message: $indicator, - ignoreIfBlocked: true, - baseZ: 99999 - }); - }) - .ajaxStop(function () { - $.unblockUI(); - }) - .ajaxError(function () { - $.unblockUI(); - }); - }); - -})(); -//####app/controls/menuBar/menuBarControl.js +//####app/controls/tablePanel/cell/cellControl.js /** * * @param parent * @constructor * @augments ContainerControl */ -function MenuBarControl(parent) { - _.superClass(MenuBarControl, this, parent); +function CellControl(parent) { + _.superClass(CellControl, this, parent); } -_.inherit(MenuBarControl, ContainerControl); +_.inherit(CellControl, ContainerControl); -_.extend(MenuBarControl.prototype, - /** @lends MenuBarControl.prototype */ +_.extend(CellControl.prototype, + /** @lends CellControl.prototype */ { createControlModel: function () { - return new MenuBarModel(); + return new CellModel(); }, createControlView: function (model) { - return new MenuBarView({model: model}); + return new CellView({model: model}); } } ); -//####app/controls/menuBar/menuBarModel.js +//####app/controls/tablePanel/cell/cellModel.js /** * @constructor * @augments ContainerModel */ -var MenuBarModel = ContainerModel.extend( - /** @lends MenuBarModel.prototype */ +var CellModel = ContainerModel.extend( + /** @lends CellModel.prototype */ { + defaults: _.defaults({ + columnSpan: 1 + }, ContainerModel.prototype.defaults), + initialize: function () { ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); } } ); -//####app/controls/menuBar/menuBarView.js +//####app/controls/tablePanel/cell/cellView.js /** * @class * @augments ControlView */ -var MenuBarView = ContainerView.extend( - /** @lends MenuBarView.prototype */ +var CellView = ContainerView.extend( + /** @lends CellView.prototype */ { - tagName: 'nav', - className: 'pl-menu-bar navbar navbar-default', - - template: InfinniUI.Template["controls/menuBar/template/menuBar.tpl.html"], + className: 'pl-cell', - UI: { + initialize: function (options) { + ContainerView.prototype.initialize.call(this, options); + this.initColumnSpan(); }, render: function () { @@ -16169,13 +12941,8 @@ var MenuBarView = ContainerView.extend( this.removeChildElements(); - this.$el.html(this.template({ - items: this.model.get('items') - })); this.renderItemsContents(); - this.bindUIElements(); - this.updateProperties(); this.trigger('render'); @@ -16187,684 +12954,670 @@ var MenuBarView = ContainerView.extend( }, renderItemsContents: function(){ - var $items = this.$el.find('.pl-menu-bar-item'), - items = this.model.get('items'), + var items = this.model.get('items'), itemTemplate = this.model.get('itemTemplate'), that = this, element, item; - $items.each(function(i, el){ - item = items.getByIndex(i); + items.forEach(function(item, i){ element = itemTemplate(undefined, {item: item, index: i}); that.addChildElement(element); - $(el) + that.$el .append(element.render()); }); }, + initColumnSpan: function () { + this.listenTo(this.model, 'change:columnSpan', this.updateColumnSpan); + this.updateColumnSpan(); + }, + + updateColumnSpan: function () { + var columnSpan = this.model.get('columnSpan'), + currentColumnSpan = this.columnSpan; + + if(columnSpan != currentColumnSpan){ + + if(currentColumnSpan){ + this.$el + .removeClass('col-xs-' + currentColumnSpan); + } + + this.$el + .addClass('col-xs-' + columnSpan); + + this.columnSpan = columnSpan; + } + + }, + updateGrouping: function(){} } ); -//####app/controls/numericBox/numericBoxControl.js +//####app/controls/tablePanel/row/rowControl.js /** * * @param parent * @constructor - * @augments TextEditorBaseControl + * @augments ContainerControl */ -function NumericBoxControl(parent) { - _.superClass(NumericBoxControl, this, parent); +function RowControl(parent) { + _.superClass(RowControl, this, parent); } -_.inherit(NumericBoxControl, TextEditorBaseControl); - -_.extend(NumericBoxControl.prototype, { +_.inherit(RowControl, ContainerControl); - createControlModel: function () { - return new NumericBoxModel(); - }, +_.extend(RowControl.prototype, + /** @lends RowControl.prototype */ + { + createControlModel: function () { + return new RowModel(); + }, - createControlView: function (model) { - return new NumericBoxView({model: model}); + createControlView: function (model) { + return new RowView({model: model}); + } } -}); +); -//####app/controls/numericBox/numericBoxModel.js +//####app/controls/tablePanel/row/rowModel.js /** - * @class - * @augments TextEditorBaseModel + * @constructor + * @augments ContainerModel */ -var NumericBoxModel = TextEditorBaseModel.extend(/** @lends TextBoxModel.prototype */{ - defaults: _.defaults( - { - increment: 1, - inputType: 'number' - }, - TextEditorBaseModel.prototype.defaults - ), - - incValue: function () { - var delta = this.get('increment'); - this.addToValue(delta); - }, - - decValue: function () { - var delta = this.get('increment'); - this.addToValue(-delta); - }, - - addToValue: function (delta) { - - var value = this.get('value'); - var startValue = this.get('startValue'); - var minValue = this.get('minValue'); - var maxValue = this.get('maxValue'); - - var newValue = _.isNumber(value) ? value : +value; - - if (this.isSetValue(value) && _.isNumber(value)) { - newValue += delta; - } else { - newValue = (_.isNumber(startValue)) ? startValue : 0; - } - - if (_.isNumber(minValue) && newValue < minValue) { - newValue = minValue; - } else if (_.isNumber(maxValue) && newValue > maxValue) { - newValue = maxValue; - } - - this.set('value', newValue); - }, - - initialize: function () { - TextEditorBaseModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - }, - - validateValue: function (value, callback) { - - var - isValid = true, - min = this.get('minValue'), - max = this.get('maxValue'); - - if (!this.isSetValue(value)) { - return true; - } - - if (_.isNumber(min) && _.isNumber(max)) { - if (value < min || value > max) { - isValid = false - } - } else if (_.isNumber(min) && value < min) { - isValid = false; - } else if (_.isNumber(max) && value > max) { - isValid = false; +var RowModel = ContainerModel.extend( + /** @lends RowModel.prototype */ + { + initialize: function () { + ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); } - - return isValid; } - - -}); -//####app/controls/numericBox/numericBoxView.js +); +//####app/controls/tablePanel/row/rowView.js /** * @class - * @augments TextEditorBaseView + * @augments ControlView */ -var NumericBoxView = TextEditorBaseView.extend(/** @lends TextBoxView.prototype */{ - - className: "pl-numericbox form-group", - - template: InfinniUI.Template["controls/numericBox/template/numericBox.tpl.html"], - - UI: _.extend({}, TextEditorBaseView.prototype.UI, { - min: '.pl-numeric-box-min', - max: '.pl-numeric-box-max' - }), - - events: _.extend({}, TextEditorBaseView.prototype.events, { - 'click .pl-numeric-box-min': 'onClickMinControlHandler', - 'click .pl-numeric-box-max': 'onClickMaxControlHandler', - 'mousedown .pl-numeric-box-min': 'onMousedownMinControlHandler', - 'mousedown .pl-numeric-box-max': 'onMousedownMaxControlHandler' - }), - - render: function () { - this.prerenderingActions(); - this.renderTemplate(this.template); - this.renderNumericBoxEditor(); - this.updateProperties(); - this.trigger('render'); - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, - - getData: function () { - var - model = this.model; - - return _.extend({}, - TextEditorBaseView.prototype.getData.call(this), { - minValue: model.get('minValue'), - maxValue: model.get('maxValue'), - increment: model.get('increment') - }); - }, - - renderNumericBoxEditor: function () { - this.renderControlEditor(); - }, - - onChangeEnabledHandler: function (model, value) { - this.ui.control.prop('disabled', !value); - this.ui.min.prop('disabled', !value); - this.ui.max.prop('disabled', !value); - }, - - onClickMinControlHandler: function () { - if (this.canChangeValue()) { - this.model.decValue(); - } - }, - - onClickMaxControlHandler: function () { - if (this.canChangeValue()) { - this.model.incValue(); - } - }, +var RowView = ContainerView.extend( + /** @lends RowView.prototype */ + { + className: 'pl-row row', - onMousedownMinControlHandler: function (event) { - if (this.canChangeValue()) { - this.repeatUpdateValue(this.model.decValue.bind(this.model)); - } - }, + initialize: function (options) { + ContainerView.prototype.initialize.call(this, options); + }, - onMousedownMaxControlHandler: function (event) { - if (this.canChangeValue()) { - this.repeatUpdateValue(this.model.incValue.bind(this.model)); - } - }, + render: function () { + this.prerenderingActions(); - repeatUpdateValue: function (cb) { - var intervalId; + this.removeChildElements(); - window.document.addEventListener('mouseup', stopRepeat); + this.renderItemsContents(); - intervalId = setInterval(cb, 200); + this.updateProperties(); + this.trigger('render'); - function stopRepeat() { - if (intervalId) { - clearInterval(intervalId); - intervalId = null; - } - window.document.removeEventListener('mouseup', stopRepeat); - } + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, - }, + renderItemsContents: function(){ + var items = this.model.get('items'), + itemTemplate = this.model.get('itemTemplate'), + that = this, + element, item; - canChangeValue: function () { - var model = this.model, - enabled = model.get('enabled'); + items.forEach(function(item, i){ + element = itemTemplate(undefined, {item: item, index: i}); + that.addChildElement(element); + that.$el + .append(element.render()); + }); + }, - return enabled === true; + updateGrouping: function(){} } +); -}); - -//####app/controls/panel/panelControl.js +//####app/controls/tabPanel/tabPanelControl.js /** * * @param parent * @constructor * @augments ContainerControl */ -function PanelControl(parent) { - _.superClass(PanelControl, this, parent); +function TabPanelControl(parent) { + _.superClass(TabPanelControl, this, parent); } -_.inherit(PanelControl, ContainerControl); +_.inherit(TabPanelControl, ContainerControl); + +_.extend(TabPanelControl.prototype, /** @lends TabPanelControl.prototype */ { + + setSelectedItem: function (value) { + /** + * @TODO Отрефакторить! Временное решение т.к. коллекция model.items содержит не экземпляры страниц а метаданные! см. templating в Container + */ + var + selectedItem = null, + model = this.controlModel, + elements = this.controlView.childElements, + items = model.get('items'); + + if (value instanceof TabPage) { + model.set('selectedItem', value) + } else if (Array.isArray(elements)) { + var index = items.indexOf(value); + if (index !== -1) { + selectedItem = elements[index]; + } + this.controlModel.set('selectedItem', selectedItem); + } + }, -_.extend(PanelControl.prototype, /** @lends PanelControl.prototype */ { createControlModel: function () { - return new PanelModel(); + return new TabPanelModel(); }, createControlView: function (model) { - return new PanelView({model: model}); + return new TabPanelView({model: model}); } }); -//####app/controls/panel/panelModel.js +//####app/controls/tabPanel/tabPanelModel.js /** * @constructor * @augments ContainerModel */ -var PanelModel = ContainerModel.extend(/** @lends PanelModel.prototype */ { +var TabPanelModel = ContainerModel.extend(/** @lends TabPanelModel.prototype */ { + initialize: function () { ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - this.on('change:collapsed', function (model, value) { - model.trigger(value ? 'collapsed' : 'expanded', null, {}); - }); - }, - - defaults: _.defaults({ - collapsible: false, - collapsed: false, - collapsibleArea: '' - }, ContainerModel.prototype.defaults), - - set: function (key, val, options) { - if (key == null) return this; - - var attrs; - if (typeof key === 'object') { - attrs = key; - options = val; - } else { - (attrs = {})[key] = val; - } - - var oldValue, newValue; - if ('collapsed' in attrs) { - //Вызов обработчиков перед collapsing/expanding - oldValue = this.get('collapsed'); - newValue = attrs.collapsed; - var allow; - - if (newValue && !oldValue) { - allow = this - .set('_collapsing', true, {validate: false}) - .trigger('collapsing', null, {}) - .get('_collapsing'); - } else if (!newValue && oldValue) { - allow = this - .set('_expanding', true, {validate: false}) - .trigger('expanding', null, {}) - .get('_expanding'); - } - if (allow === false) { - //Если collapsing/expanding отменен в обработчиках collapsing/expanding - не меняем collapsed - delete attrs.collapsed; - } - } - return ContainerModel.prototype.set.call(this, attrs, options); }, - //@TODO Add support an event map syntax - on: function (name, callback, context) { - var handler; - var model = this; - switch (name) { - case 'collapsing': - handler = function () { - var allow = callback(null, {}); - if (allow === false) { - model.set('_collapsing', false); - } - }; - break; - case 'expanding': - handler = function () { - var allow = callback(null, {}); - if (allow === false) { - model.set('_expanding', false); - } - }; - break; - default: - handler = callback; - break; - } - ContainerModel.prototype.on.call(this, name, handler, context); - } + defaults: _.defaults( + { + headerLocation: InfinniUI.TabHeaderLocation.top, + headerOrientation: InfinniUI.TabHeaderOrientation.horizontal + }, + ContainerModel.prototype.defaults + ) }); - -//####app/controls/panel/panelView.js +//####app/controls/tabPanel/tabPanelView.js /** * @class * @augments ControlView */ -var PanelView = ContainerView.extend(/** @lends PanelView.prototype */ { - - className: 'pl-panel panel panel-default', +var TabPanelView = ContainerView.extend(/** @lends TabPanelView.prototype */ { - template: InfinniUI.Template["controls/panel/template/panel.tpl.html"], + className: 'pl-tabpanel', - UI: { - header: '.pl-panel-header', - items: '.panel-items' + template: { + top: InfinniUI.Template["controls/tabPanel/template/tabPanel.top.tpl.html"], + right: InfinniUI.Template["controls/tabPanel/template/tabPanel.right.tpl.html"], + bottom: InfinniUI.Template["controls/tabPanel/template/tabPanel.bottom.tpl.html"], + left: InfinniUI.Template["controls/tabPanel/template/tabPanel.left.tpl.html"], + none: InfinniUI.Template["controls/tabPanel/template/tabPanel.none.tpl.html"] }, - events: { - 'click >.pl-panel-header': 'onClickHeaderHandler' + UI: { + header: '.pl-tabpanel-header', + content: '.pl-tabpanel-content' }, - initialize: function (options) { - ContainerView.prototype.initialize.call(this, options); + initHandlersForProperties: function () { + ContainerView.prototype.initHandlersForProperties.call(this); + this.listenTo(this.model, 'change:headerLocation', this.onChangeHeaderLocation); + this.listenTo(this.model, 'change:headerOrientation', this.updateHeaderOrientation); + this.listenTo(this.model, 'change:selectedItem', this.updateSelectedItem); }, render: function () { this.prerenderingActions(); - this.removeChildElements(); - - this.$el.html(this.template({ - items: this.model.get('items') - })); - - this.bindUIElements(); + this.renderTemplate(this.getTemplate()); this.renderItemsContents(); + this.initSelectedItem(); + + this.postrenderingActions(); this.trigger('render'); this.updateProperties(); - - this.postrenderingActions(); //devblockstart window.InfinniUI.global.messageBus.send('render', {element: this}); //devblockstop return this; }, - initHandlersForProperties: function () { - ContainerView.prototype.initHandlersForProperties.call(this); - this.listenTo(this.model, 'change:collapsed', this.updateCollapsed); - this.listenTo(this.model, 'change:collapsible', this.updateCollapsible); - this.listenTo(this.model, 'change:header', this.updateHeader); + /** + * @protected + */ + renderItemsContents: function () { + var items = this.model.get('items'); + + this.removeChildElements(); + this.ui.content.empty(); + this.model.set('selectedItemIndex', -1); + + var data = []; + items.forEach(function (item, index) { + data.push({ + tabElement: this.renderTabContent(item, index), + item: item, + index: index + }); + }, this); + + this.renderTabHeaders(data); + }, + + /** + * @protected + * @param {Array.} data + */ + renderTabHeaders: function (data) { + var header, + model = this.model, + items = model.get('items'), + selectedItem = model.get('selectedItem'); + + if (Array.isArray(this.tabHeaders)) { + while (header = this.tabHeaders.pop()) { + this.stopListening(header); + header.remove(); + } + } + + this.tabHeaders = data.map(function (data) { + var selected = items.indexOf(data.item) !== -1; + var header = this.renderTabHeader(data.tabElement, selected); + + this.listenTo(header, 'selected', function () { + var isEnabled = data.tabElement.getEnabled(); + if(isEnabled) { + model.set('selectedItem', data.tabElement); + } + }); + + this.listenTo(header, 'close', function () { + var isEnabled = data.tabElement.getEnabled(); + if(isEnabled) { + data.tabElement.close(); + } + }); + + return header; + }, this); + + }, + + /** + * + * @param {TabPage} tabPageElement + * @param {boolean} selected + * @returns {TabHeaderView} + */ + renderTabHeader: function (tabPageElement, selected) { + var header = new TabHeaderView({ + text: tabPageElement.getText(), + canClose: tabPageElement.getCanClose(), + enabled: tabPageElement.getEnabled(), + selected: selected + }), + that = this; + + tabPageElement.onPropertyChanged('text', function () { + header.setText(tabPageElement.getText()); + }); + + tabPageElement.onPropertyChanged('canClose', function () { + header.setCanClose(tabPageElement.getCanClose()); + }); + + tabPageElement.onPropertyChanged('enabled', function () { + header.setEnabled(tabPageElement.getEnabled()); + + var selectedTabPage = that.model.get('selectedItem'); + if(tabPageElement == selectedTabPage){ // если видимость поменяли у выбранного элемента + that.resetDefaultSelectedItem(); + } + }); + + this.ui.header.append(header.render().$el); + return header; + }, + + renderTabContent: function (item, index) { + var + itemTemplate = this.model.get('itemTemplate'), + element = itemTemplate(undefined, {item: item, index: index}); + + this.addChildElement(element); + this.ui.content.append(element.render()); + return element; + }, + + /** + * @protected + * @returns {Function} + */ + getTemplate: function () { + var + template, + headerLocation = this.model.get('headerLocation'); + + switch (headerLocation) { + case InfinniUI.TabHeaderLocation.top: + template = this.template.top; + break; + case InfinniUI.TabHeaderLocation.right: + template = this.template.right; + break; + case InfinniUI.TabHeaderLocation.bottom: + template = this.template.bottom; + break; + case InfinniUI.TabHeaderLocation.left: + template = this.template.left; + break; + case InfinniUI.TabHeaderLocation.none: + default: + template = this.template.none; + break; + } + + return template; }, + /** + * @protected + */ updateProperties: function () { ContainerView.prototype.updateProperties.call(this); - this.updateCollapsed(); - this.updateCollapsible(); - this.updateHeader(); + this.updateHeaderOrientation(); + this.updateSelectedItem(); }, - updateCollapsed: function () { - this.ui.header.toggleClass('pl-collapsed', this.model.get('collapsed')); + /** + * @protected + */ + onChangeHeaderLocation: function () { + //При изменении положения вкладок меняется весь шаблон + this.rerender(); }, - updateCollapsible: function (model, value) { - this.ui.header.toggleClass('pl-collapsible', this.model.get('collapsible')); + /** + * @protected + */ + updateHeaderOrientation: function () { + //@TODO Реализовать TabPanel.updateHeaderOrientation() }, - updateHeader: function () { - var model = this.model; - this.ui.header.empty(); - var headerTemplate = model.get('headerTemplate'); - if (typeof headerTemplate === 'function') { - var header = model.get('header'); - this.ui.header.append(headerTemplate(null, {value: header}).render()); + /** + * @protected + * @description Проверяет чтобы одна из вкладок была активна + */ + initSelectedItem: function () { + var + model = this.model, + tabPages = this.childElements, + selectedItem = model.get('selectedItem'); + + if (!Array.isArray(tabPages) || tabPages.length == 0) { + model.set('selectedItem', null); + } else { + if (tabPages.indexOf(selectedItem) === -1) { + var firstEnabledPageIndex = this._getFirstEnabledPageIndex(); + if(firstEnabledPageIndex != -1) { + model.set('selectedItem', tabPages[firstEnabledPageIndex]); + } + } } }, + resetDefaultSelectedItem: function () { + this.model.set('selectedItem', null); + this.initSelectedItem(); + }, + _getFirstEnabledPageIndex: function() { + var tabPages = this.childElements; - renderItemsContents: function () { - var $items = this.$el.find('.pl-panel-i'), - items = this.model.get('items'), - itemTemplate = this.model.get('itemTemplate'), - that = this, - element, item; + for(var i=0; i 0) { + var itemIndex = 0; + if (selectedItem) { + itemIndex = items.indexOf(selectedItem); + if (itemIndex === -1) { + itemIndex = 0; + } else { + itemIndex = Math.min(items.length - 1, itemIndex + 1); + } + } + selectedItem = items.getByIndex(itemIndex); + } else { + selectedItem = null; + } + this.setSelectedItem(selectedItem); + this.setSelectedItemToValue(); + }, -_.extend(ToggleButtonControl.prototype, { + selectPrevItem: function () { + var items = this.get('items'); + var selectedItem = this.getSelectedItem(); - createControlModel: function () { - return new ToggleButtonModel(); + if (items.length > 0) { + var itemIndex = 0; + if (selectedItem) { + itemIndex = items.indexOf(selectedItem); + if (itemIndex === -1) { + itemIndex = 0; + } else { + itemIndex = Math.max(0, itemIndex - 1); + } + } + selectedItem = items.getByIndex(itemIndex); + } + this.setSelectedItem(selectedItem); + this.setSelectedItemToValue(); }, - createControlView: function (model) { - return new ToggleButtonView({model: model}); - } -}, editorBaseControlMixin); + selectFirstItem: function () { + var items = this.get('items'); + var selectedItem = null; + if (items.length > 0) { + selectedItem = items.getByIndex(0); + } + this.setSelectedItem(selectedItem); + this.setSelectedItemToValue(); + }, -//####app/controls/toggleButton/toggleButtonModel.js -var ToggleButtonModel = ControlModel.extend( _.extend({ + selectLastItem: function () { + var items = this.get('items'); + var selectedItem = null; - defaults: _.defaults({ - value: false, - textOn: 'ON', - textOff: 'OFF', - horizontalAlignment: 'Left' - }, ControlModel.prototype.defaults), + if (items.length > 0) { + selectedItem = items.getByIndex(items.length - 1); + } + this.setSelectedItem(selectedItem); + this.setSelectedItemToValue(); + }, - initialize: function () { - ControlModel.prototype.initialize.apply(this, arguments); - this.initialize_editorBaseModel(); + toggleItem: function (item, toggle) { + var value = this.valueByItem(item); + this.toggleValue(value, toggle); + this.trigger('toggle'); } +}); +//####app/controls/comboBox/comboBoxView.js +var ComboBoxView = ListEditorBaseView.extend({ -}, editorBaseModelMixin)); -//####app/controls/toggleButton/toggleButtonView.js -/** - * @class ToggleButtonView - * @augments ControlView - * @mixes editorBaseViewMixin - */ -var ToggleButtonView = ControlView.extend(/** @lends ToggleButtonView.prototype */ _.extend({}, editorBaseViewMixin, { - - template: InfinniUI.Template["controls/toggleButton/template/toggleButton.tpl.html"], + className: 'pl-combobox form-group', - UI: _.extend({}, editorBaseViewMixin.UI, { - textOn: '.togglebutton-handle-on', - textOff: '.togglebutton-handle-off', - container: '.togglebutton-container' - }), + template: InfinniUI.Template["controls/comboBox/template/combobox.tpl.html"], events: { - 'click .togglebutton-box': 'onClickHandler' + 'click .pl-combobox__grip': 'onClickGripHandler', + 'click .pl-combobox__value': 'onClickValueHandler', + 'click .pl-combobox__clear': 'onClickClearHandler', + 'click .pl-control': 'onClickValueHandler', + 'keydown .pl-control': 'onKeyDownControlHandler' }, - initHandlersForProperties: function(){ - ControlView.prototype.initHandlersForProperties.call(this); - editorBaseViewMixin.initHandlersForProperties.call(this); + UI: _.defaults({ + control: '.pl-control', + label: '.pl-control-label', + value: '.pl-combobox__value', + clear: '.pl-combobox__clear' + }, ListEditorBaseView.prototype.UI), - this.listenTo(this.model, 'change:textOn', this.updateTextOn); - this.listenTo(this.model, 'change:textOff', this.updateTextOff); - }, + isControlElement: function (el) { + var res = ListEditorBaseView.prototype.isControlElement.call(this, el); - updateProperties: function(){ - ControlView.prototype.updateProperties.call(this); - editorBaseViewMixin.updateProperties.call(this); + if (res) { + return res; + } + + if (!this.dropDownView) { + return false; + } - this.updateTextOn(); - this.updateTextOff(); + return $.contains(this.dropDownView.el, el); }, updateFocusable: function () { var focusable = this.model.get('focusable'); + var enabled = this.model.get('enabled'); - if (focusable) { - this.ui.container.attr('tabindex', 0); + if (focusable && enabled) { + this.ui.control.attr('tabindex', 0); } else { - this.ui.container.removeAttr('tabindex'); + this.ui.control.removeAttr('tabindex'); } }, - updateTextOn: function () { - var textOn = this.model.get('textOn'); - this.ui.textOn.html(textOn || ' '); + initialize: function (options) { + ListEditorBaseView.prototype.initialize.call(this, options); + var model = this.model, + view = this; + + //this.on('beforeClick', this.activateControl); + + this.on('render', function () { + view.renderValue(); + + model.on('change:dropdown', function (model, dropdown) { + if (dropdown) { + model.set('autocompleteValue', '');//Сброс фильтра + model.set('focused', true); + if (view.dropDownView) { + view.dropDownView.remove(); + } + var dropdownView = new ComboBoxDropdownView({ + model: model + }); + view.dropDownView = dropdownView; + + this.listenTo(dropdownView, 'search', _.debounce(view.onSearchValueHandler.bind(view), 300)); + + var $dropdown = dropdownView.render(); + $('body').append($dropdown); + + dropdownView.updatePosition(view.el); + view.dropDownView.on('itemsRendered2', function(){ + dropdownView.updatePosition(view.el); + }); + + if (model.get('autocomplete')) { + dropdownView.setSearchFocus(); + } else { + view.ui.control.focus(); + } + setTimeout(dropdownView.ensureVisibleSelectedItem.bind(dropdownView), 0); + } else { + view.ui.control.focus(); + } + }); + model.onValueChanged(this.onChangeValueHandler.bind(this)); + + }, this); }, - updateTextOff: function () { - var textOff = this.model.get('textOff'); - this.ui.textOff.html(textOff || ' '); + initHandlersForProperties: function(){ + ListEditorBaseView.prototype.initHandlersForProperties.call(this); + this.listenTo(this.model, 'change:showClear', this.updateShowClear); + this.listenTo(this.model, 'change:labelText', this.updateLabelText); }, render: function () { this.prerenderingActions(); - this.renderTemplate(this.template); + + //var preparedItems = this.strategy.prepareItemsForRendering(); + //var template = this.strategy.getTemplate(); + + //this.removeChildElements(); + + this.renderTemplate(this.getTemplate()); + this.updateProperties(); this.trigger('render'); + this.postrenderingActions(); //devblockstart window.InfinniUI.global.messageBus.send('render', {element: this}); @@ -17108,6527 +14460,9474 @@ var ToggleButtonView = ControlView.extend(/** @lends ToggleButtonView.prototype return this; }, - getData: function () { - var model = this.model; + getTemplate: function () { + return this.template; + }, - return _.extend({}, - ControlView.prototype.getData.call(this), - editorBaseViewMixin.getData.call(this), - { - textOn: model.get('textOn'), - textOff: model.get('textOff') - } - ); + onKeyDownControlHandler: function (event) { + var enabled = this.model.get('enabled'); + + if (!enabled) { + event.preventDefault(); + return; + } + + if (event.ctrlKey || event.altKey) { + return; + } + + if (this.isDropdown()) { + return this.dropDownView.onKeyDownHandler.call(this.dropDownView, event); + } + switch (event.which) { + case 40: //Down Arrow + case 13: //Ennter + event.preventDefault(); + this.toggleDropdown(); + break; + } }, + onClickClearHandler: function () { + var enabled = this.model.get('enabled'); + if (enabled) { + this.model.set('value', null); + this.ui.control.focus(); + } + }, - onClickHandler: function (event) { - var model = this.model; - model.set('value', !model.get('value')); + onClickGripHandler: function () { + var enabled = this.model.get('enabled'); + if (enabled) { + this.toggleDropdown(); + } }, - updateValue: function () { - var value = this.model.get('value'); - this.switchClass('toggle', value ? 'on' : 'off', this.$el); - } -})); + updateProperties: function(){ + ListEditorBaseView.prototype.updateProperties.call(this); -//####app/controls/toolBar/toolBarControl.js -/** - * - * @param parent - * @constructor - * @augments ContainerControl - */ -function ToolBarControl(parent) { - _.superClass(ToolBarControl, this, parent); -} + this.updateLabelText(); + this.updateShowClear(); + }, -_.inherit(ToolBarControl, ContainerControl); + updateGrouping: function(){ + this.toggleDropdown(false); + }, -_.extend(ToolBarControl.prototype, /** @lends ToolBarControl.prototype */ { + updateLabelText: function () { + var labelText = this.model.get('labelText'); + if (labelText && labelText !== '') { + this.ui.label.toggleClass('hidden', false); + } else { + this.ui.label.toggleClass('hidden', true); + } - createControlModel: function () { - return new ToolBarModel(); + this.ui.label.text(labelText); }, - createControlView: function (model) { - return new ToolBarView({model: model}); - } -}); + updateEnabled: function () { + ListEditorBaseView.prototype.updateEnabled.call(this); + var enabled = this.model.get('enabled'); -//####app/controls/toolBar/toolBarModel.js -/** - * @constructor - * @aurments ContainerModel - */ -var ToolBarModel = ContainerModel.extend({ + if (!enabled) { + //Prevent got focus + this.ui.control.removeAttr('tabindex'); + } else { + this.updateFocusable(); + } -}); + }, -//####app/controls/toolBar/toolBarView.js -/** - * @constructor - * @augments ContainerView - */ -var ToolBarView = ContainerView.extend({ + updateValue: function(){ + this.updateShowClear(); + }, - className: 'pl-tool-bar', + updateShowClear: function () { + var + model = this.model, + showClear = model.get('showClear'), + value = model.get('value'), + noValue = value === null || typeof value === 'undefined'; - template: InfinniUI.Template["controls/toolBar/template/toolBar.tpl.html"], + this.ui.clear.toggleClass('hidden', !showClear || noValue); + }, - itemTemplate: InfinniUI.Template["controls/toolBar/template/toolBarItem.tpl.html"], + updateSelectedItem: function () { - UI: { - container: '.pl-tool-bar__container' }, - render: function () { - this.prerenderingActions(); - - this.renderTemplate(this.template); - this.ui.container.append(this.renderItems()); - this.updateProperties(); - this.trigger('render'); + updateDisabledItem: function () { + this.toggleDropdown(false); + }, - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; + isDropdown: function () { + var model = this.model; + return !!model.get('dropdown'); }, - renderItems: function () { + toggleDropdown: function (toggle) { var model = this.model; - var items = model.get('items'); - var itemTemplate = model.get('itemTemplate'); + if (typeof toggle === 'undefined') { + toggle = !model.get('dropdown'); + } + model.set('dropdown', toggle); + }, - this.removeChildElements(); + onChangeValueHandler: function () { + this.renderValue(); + }, - var $elements = []; + rerender: function () { - items.forEach(function (item, index) { - var template = this.itemTemplate(); - var $template = $(template); + }, - var element = itemTemplate(null, { - index: index, - item: item + renderValue: function () { + var model = this.model, + multiSelect = model.get('multiSelect'), + value = this.model.get('value'), + $value = [], + valueTemplate = this.model.get('valueTemplate'); + + if (multiSelect && Array.isArray(value)) { + var valueView = new ComboBoxValues({ + items: value.map(function(val, i) { + return { + "$value": valueTemplate(null, {value: val, index: i}).render(), + "value": val, + "index": i + }; + }) }); - this.addChildElement(element); - $template.append(element.render()); - $elements.push($template); - }, this); + valueView.listenTo(model, 'toggle', valueView.setFocus); + this.listenTo(valueView, 'remove', this.onRemoveValueHandler); + this.listenTo(valueView, 'search', _.debounce(this.onSearchValueHandler.bind(this), 300)); + $value = valueView.render(); + } else { + $value = valueTemplate(null, {value: value}).render(); + } + this.ui.value.empty(); + this.ui.value.append($value); - return $elements; + editorBaseViewMixin.updateValueState.call(this); }, - updateGrouping: function(){} + onRemoveValueHandler: function (value) { + this.model.toggleValue(value, false); + }, + + /** + * @description Устанока фильтра быстрого выбора элемента из списка + * @param {string} text + */ + onSearchValueHandler: function (text) { + this.toggleDropdown(true); + this.model.set('autocompleteValue', text); + }, + + onClickValueHandler: function (event) { + var enabled = this.model.get('enabled'); + + if (enabled) { + this.toggleDropdown(true); + } + } + }); -//####app/controls/view/viewControl.js -/** - * - * @param parent - * @constructor - * @augments ContainerControl - */ -function ViewControl(parent) { - _.superClass(ViewControl, this, parent); +//####app/controls/contextMenu/contextMenuControl.js +function ContextMenuControl() { + _.superClass(ContextMenuControl, this); } -_.inherit(ViewControl, ContainerControl); +_.inherit(ContextMenuControl, ContainerControl); -_.extend(ViewControl.prototype, - /** @lends ViewControl.prototype */ - { - createControlModel: function () { - return new ViewModel(); - }, +_.extend(ContextMenuControl.prototype, /** @lends ContextMenuControl.prototype */ { - createControlView: function (model) { - return new ViewView({model: model}); - } + createControlModel: function () { + return new ContextMenuModel(); + }, + + createControlView: function (model) { + return new ContextMenuView({model: model}); } -); +}); -//####app/controls/view/viewModel.js -var DialogResult = { - none: 0, - accepted: 1, - canceled: 2 -}; -window.InfinniUI.DialogResult = DialogResult; +//####app/controls/contextMenu/contextMenuModel.js +var ContextMenuModel = ContainerModel.extend({ -var ViewModel = ContainerModel.extend({ +}); - defaults: _.defaults({ - dialogResult: DialogResult.none, - isApplication: false, - closeButtonVisibility: true - }, ContainerModel.prototype.defaults), +//####app/controls/contextMenu/contextMenuView.js +var ContextMenuView = ContainerView.extend({ - initialize: function () { - ContainerModel.prototype.initialize.apply(this); + contextMenuTemplate: InfinniUI.Template["controls/contextMenu/template/contextMenu.tpl.html"], - this.set('scripts', new Collection([], 'name')); - this.set('parameters', new Collection([], 'name')); - this.set('dataSources', new Collection([], 'name')); - } -}); + updateHorizontalAlignment: function(){ + var horizontalAlignment = this.model.get('horizontalAlignment'); + var that = this; + var $el; -//####app/controls/view/viewView.js -/** - * @class - * @augments ContainerView - */ -var ViewView = ContainerView.extend( - /** @lends ViewView.prototype */ - { - className: 'pl-view', + this.whenReady( + function(){ + $el = that.$el.parent().parent(); + return $el.length > 0; + }, - initialize: function (options) { - ContainerView.prototype.initialize.call(this, options); - }, + function(){ + if(horizontalAlignment == 'Right'){ + $el + .addClass('pull-right'); + }else{ + $el + .removeClass('pull-right'); + } + } + ); + }, - render: function () { - this.prerenderingActions(); + render: function () { + var exchange = window.InfinniUI.global.messageBus, + that = this; - this.$el.empty(); + this.prerenderingActions(); - this.renderItemsContents(); + this.removeChildElements(); - this.updateProperties(); - this.trigger('render'); + this.$el = this.renderDropdown(); - this.postrenderingActions(); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - }, + this.bindUIElements(); - renderItemsContents: function(){ - var that = this, - items = this.model.get('items'), - itemTemplate = this.model.get('itemTemplate'), - element; + this.updateProperties(); + + this.trigger('render'); + + this.postrenderingActions(); + + exchange.subscribe(messageTypes.onOpenContextMenu.name, function (context, args) { + that.open(args.value); + }); + + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop - items.forEach(function(item, i){ - element = itemTemplate(undefined, {item: item, index: i}); - if (element) { - that.$el - .append(element.render()); - } - }); - }, + return this; + }, - updateGrouping: function(){} - } -); + renderDropdown: function(){ + var template = this.contextMenuTemplate; + var items = this.model.get('items').toArray(); + var $result = $(template({items: items})); -//####app/controls/viewPanel/viewPanelControl.js -var ViewPanelControl = function () { - _.superClass(ViewPanelControl, this); -}; + this.appendItemsContent($result, items); + $result.on('click', function () { + this.close(); + }.bind(this)); + $result.on('contextmenu', function (event) { + event.preventDefault(); + }.bind(this)); + return $result; + }, -_.inherit(ViewPanelControl, Control); + appendItemsContent: function($dropdown, items){ + var that = this, + itemTemplate = this.model.get('itemTemplate'), + itemEl, $el; -ViewPanelControl.prototype.createControlModel = function () { - return new ViewPanelModel(); -}; + $dropdown.find('.pl-popup-button__item').each(function(i, el){ + $el = $(el); + itemEl = itemTemplate(undefined, {index: i, item: items[i]}); + that.addChildElement(itemEl); + $el.append(itemEl.render()); + }); + }, -ViewPanelControl.prototype.createControlView = function (model) { - return new ViewPanelView({model: model}); -}; + open: function(rightclickCoords){ + var that = this; -var ViewPanelModel = ControlModel.extend({ - defaults: _.defaults({ - layout: null - }, ControlModel.prototype.defaults), + $('body').append(this.$el); - initialize: function(){ - var that = this; + var $parent = this.$el.parent(); - ControlModel.prototype.initialize.apply(this); + this.$el.addClass('open'); + $parent.addClass('open'); - this.once('change:layout', function (model, layout) { - if(layout && layout.onLoaded){ - that.subscribeOnLoaded(); - } - }); - }, + this.alignDropdown(rightclickCoords); - subscribeOnLoaded: function(){ - var that = this; - var layout = this.get('layout'); + var $ignoredElements = this.$el; + new ActionOnLoseFocus($ignoredElements, function(){ + that.close(); + }); + }, - layout.onLoaded(function(){ - that.set('isLoaded', true); - }); - } -}); + close: function(){ + this.$el.removeClass('open'); + this.$el.parent().removeClass('open'); + this.$el.detach(); + }, -var ViewPanelView = ControlView.extend({ - className: 'pl-view-panel', + alignDropdown: function(rightclickCoords){ + var horizontalAlignment = this.model.get('horizontalAlignment'), + $parent = this.$el.parent(), + parentDimentions = {width: $parent.width(), height: $parent.height()}, + elDimentions = {width: this.$el[0].children[0].clientWidth, height: this.$el[0].children[0].clientHeight}; - initialize: function () { - ControlView.prototype.initialize.apply(this); - this.listenTo(this.model, 'change:layout', this.onChangeLayoutHandler); - }, + if(rightclickCoords.x + elDimentions.width > parentDimentions.width){ + rightclickCoords.x -= elDimentions.width; + } + if(rightclickCoords.y + elDimentions.height > parentDimentions.height){ + rightclickCoords.y -= elDimentions.height; + } - onChangeLayoutHandler: function (model, layout) { - this.$el.empty(); - if(layout){ - this.$el.append(layout.render()); - } - }, + this.$el.offset({ + top: rightclickCoords.y, + left: rightclickCoords.x + }); + }, - render: function () { - this.prerenderingActions(); + updateGrouping: function(){}, - var layout = this.model.get('layout'); + whenReady: function(conditionFunction, onConditionFunction, n){ + var that = this; - if(layout){ - this.$el.append(layout.render()); - } + if(n === undefined){ + n = 100; + } - this.updateProperties(); - this.trigger('render'); + if(!conditionFunction()){ + if(n>0){ + setTimeout( function(){ + that.whenReady(conditionFunction, onConditionFunction, n-1); + }, 10); + } + }else{ + onConditionFunction(); + } + } - this.postrenderingActions(false); - //devblockstart - window.InfinniUI.global.messageBus.send('render', {element: this}); - //devblockstop - return this; - } }); -//####app/data/dataSource/_mixins/dataSourceValidationNotifierMixin.js +//####app/controls/divider/dividerControl.js /** * - * @mixin + * @param parent + * @constructor + * @arguments Control */ -var DataSourceValidationNotifierMixin = { - /** - * @param dataSource - */ - initNotifyValidation: function (dataSource) { - dataSource.onErrorValidator(this.notifyOnValidationError.bind(this)); - }, +function DividerControl(parent) { + _.superClass(DividerControl, this, parent); +} - /** - * @param context - * @param args - */ - notifyOnValidationError: function (context, args) { - var result = args.value; +_.inherit(DividerControl, Control); - if (typeof result === 'undefined' || result === null || result['IsValid'] || !Array.isArray(result['Items'])) { - return; - } +_.extend(DividerControl.prototype, { - result['Items'].forEach(function (item) { - var exchange = window.InfinniUI.global.messageBus; - exchange.send(messageTypes.onNotifyUser, {item: item, messageText: item.Message, messageType: 'error'}); - }); - } -}; -//####app/data/dataSource/baseDataSource.js + createControlModel: function () { + return new DividerModel(); + }, + + createControlView: function (model) { + return new DividerView({model: model}); + } +}); + + +//####app/controls/divider/dividerModel.js /** - * @constructor - * @augments Backbone.Model - * @mixes dataSourceFindItemMixin + * @class + * @arguments ControlModel */ -var BaseDataSource = Backbone.Model.extend({ - defaults: { - name: null, - idProperty: '_id', - identifyingMode: 'byId', // byId, byLink. detect automatically +var DividerModel = ControlModel.extend(/** @lends DividerModel.prototype */{ - view: null, + initialize: function () { + ControlModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + } - isDataReady: false, +}); - dataProvider: null, +//####app/controls/divider/dividerView.js +/** + * @class + * @arguments ControlView + */ +var DividerView = ControlView.extend( + /** @lends DividerView.prototype */ + { + tagName: 'hr', - /* - * TreeModel for handling - * model.items - * model.selectedItem - * */ - model: null, + className: 'pl-divider', - modifiedItems: {}, - itemsById: {}, + initialize: function (options) { + ControlView.prototype.initialize.call(this, options); + }, - fillCreatedItem: true, + render: function () { + this.prerenderingActions(); - suspendingList: null, // [] + this.updateProperties(); + this.trigger('render'); - waitingOnUpdateItemsHandlers: null, //[] + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + } - errorValidator: null, + } +); - isRequestInProcess: false, +//####app/controls/extensionPanel/extensionPanel.js +var ExtensionPanelControl = function () { + _.superClass(ExtensionPanelControl, this); +}; - isLazy: true, +_.inherit(ExtensionPanelControl, ContainerControl); - isWaiting: false, +_.extend(ExtensionPanelControl.prototype, { - resolvePriority: 0, + createControlModel: function () { + return new ExtensionPanelModel(); + }, - newItemsHandler: null, + createControlView: function (model) { + return new ExtensionPanelView({model: model}); + } +}); +//####app/controls/extensionPanel/extensionPanelModel.js +var ExtensionPanelModel = ContainerModel.extend({ + defaults: _.defaults({ + extensionName: null, + context: null + }, ContainerModel.prototype.defaults), - isNumRegEx: /^\d/ + initialize: function () { + ContainerModel.prototype.initialize.apply(this); + } +}); +//####app/controls/extensionPanel/extensionPanelView.js +var ExtensionPanelView = ContainerView.extend({ + className: 'pl-extension-panel', + initialize: function () { + ContainerView.prototype.initialize.apply(this); + this.extensionObject = null; }, - initialize: function () { - var view = this.get('view'); - var modelStartTree = { - items: null, - selectedItem: null - }; + render: function () { + this.prerenderingActions(); - this.initDataProvider(); - if (!view) { - throw 'BaseDataSource.initialize: При создании объекта не была задана view.' + if (!this.extensionObject) { + this.initExtensionObject(); } - this.set('suspendingList', []); - this.set('waitingOnUpdateItemsHandlers', []); - this.set('model', new TreeModel(view.getContext(), this, modelStartTree)); - _.extend( this, BaseDataSource.identifyingStrategy.byId); - }, + this.extensionObject.render(); - initDataProvider: function () { - throw 'BaseDataSource.initDataProvider В потомке BaseDataSource не задан провайдер данных.' - }, + this.updateProperties(); + this.trigger('render'); - onPropertyChanged: function (property, handler, owner) { + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, - if (typeof property == 'function') { - owner = handler; - handler = property; - property = '*'; - } + updateGrouping: function(){ - if(property.charAt(0) == '.'){ - property = property.substr(1); - }else{ - if(property == ''){ - property = 'items'; - }else{ - property = 'items.' + property; - } + }, - } + initExtensionObject: function () { + var extensionName = this.model.get('extensionName'), + context = this.model.get('context'), + itemTemplate = this.model.get('itemTemplate'), + parameters = this.model.get('parameters'), + items = this.model.get('items'), + builder = this.model.get('builder'); - this.get('model').onPropertyChanged(property, function(context, args){ - var property = args.property; + this.extensionObject = new window[extensionName](context, {$el: this.$el, parameters: parameters, itemTemplate: itemTemplate, items: items, builder: builder}); + } +}); - if(property.substr(0,6) == 'items.'){ - property = property.substr(6); - }else if(property == 'items'){ - property = ''; - } else{ - property = '.' + property; - } +//####app/controls/fileBox/fileBoxControl.js +/** + * + * @param parent + * @constructor + * @augments Control + * @mixes editorBaseControlMixin + */ +function FileBoxControl(parent) { + _.superClass(FileBoxControl, this, parent); + this.initialize_editorBaseControl(); +} + +_.inherit(FileBoxControl, Control); + +_.extend(FileBoxControl.prototype, { + + createControlModel: function () { + return new FileBoxModel(); + }, + + createControlView: function (model) { + return new FileBoxView({model: model}); + } + +}, editorBaseControlMixin); + - args.property = property; +//####app/controls/fileBox/fileBoxModel.js +/** + * @constructor + * @augments ControlModel + * @mixes editorBaseModelMixin + */ +var FileBoxModel = ControlModel.extend( _.extend({ + + defaults: _.defaults({ + + }, + editorBaseModelMixin.defaults_editorBaseModel, + ControlModel.prototype.defaults + ), + initialize: function () { + ControlModel.prototype.initialize.apply(this, arguments); + this.initialize_editorBaseModel(); + + this.set('acceptTypes', new Collection()); + this.on('change:file', this.onChangeFileHandler); + this.on('change:value', function (model, value) { + if (value instanceof File) { + model.set('fileName', value.name); + } + }); + + this.on("invalid", function(model, error) { + this.set('errorText', error); + }); + }, + + validate: function (attrs, options) { + var file = attrs.file; + var maxSize = this.get('maxSize'); + var acceptTypes = this.get('acceptTypes'); + if (file) { + if (maxSize) { + if (file.size > maxSize) { + return localized.strings.FileBox.fileSizeTooBig + .replace(/\{chosen-size\}/g, (file.size/(1024*1024)).toFixed(1)) + .replace(/\{permitted-size\}/g, (maxSize/(1024*1024)).toFixed(1)); + } + } + + if (acceptTypes.length) { + var acceptType = acceptTypes.contains(file.type); + var fileName = file.name.toLowerCase(); + if (!acceptType) { + var len = fileName.length; + var acceptType = acceptTypes.some(function(name) { + return fileName.lastIndexOf(name.toLowerCase()) === len - name.length; + }); + } + + if (!acceptType) { + return localized.strings.FileBox.incorrectFormat; + } + + } + + + } + }, + + setFile: function (file) { + if (this.set('file', file, {validate: true})) { + this.set('errorText', ''); + } + }, + + removeFile: function () { + this.setFile(null); + }, + + onChangeFileHandler: function (model, file) { + if (file) { + model.set('fileName', file.name); + model.set('fileSize', file.size); + } else { + model.set('fileName', null); + model.set('fileSize', null); + } + model.set('value', file); + //model.set('value', null); + } + + //stopLoadingFile: function () { + // var fileLoader = this.fileLoader; + // if (fileLoader && fileLoader.state() === 'pending') { + // fileLoader.reject(); + // } + //}, + + //loadPreview: function (file) { + // var defer = $.Deferred(); + // var reader = new FileReader(); + // reader.onload = (function (file) { + // return function (event) { + // defer.resolve(file, event.target.result); + // }; + // }(file)); + // reader.onerror = function (event) { + // defer.reject(event); + // }; + // reader.readAsDataURL(file); + // return defer.promise(); + //} + +}, editorBaseModelMixin)); +//####app/controls/fileBox/fileBoxView.js +/** + * @augments ControlView + * @mixes editorBaseViewMixin + * @constructor + */ +var FileBoxView = ControlView.extend(/** @lends FileBoxView.prototype */ _.extend({}, editorBaseViewMixin, { + + template: InfinniUI.Template["controls/fileBox/template/template.tpl.html"], + + className: 'pl-file-box', + + UI: _.extend({}, editorBaseViewMixin.UI, { + label: '.pl-control-label', + btnRemove: '.pl-filebox-btn-remove', + btnPick: '.pl-filebox-btn-pick', + fileEmpty: '.pl-filebox-file-empty', + fileUpload: '.pl-filebox-file-upload', + fileDownload: '.pl-filebox-file-download', + fileDownloadUrl: '.pl-filebox-file-download-url', + edit: '.pl-filebox-edit', + control: '.form-control', + + input: 'input' + }), + + events: { + 'change input': 'onChangeFileHandler', + 'click .pl-filebox-btn-remove': 'onClickRemoveImageHandler' + }, + + initHandlersForProperties: function(){ + ControlView.prototype.initHandlersForProperties.call(this); + this.listenTo(this.model, 'change:labelText', this.updateLabelText); + this.listenTo(this.model, 'change:fileName', this.updateFileName); + this.listenTo(this.model, 'change:fileSize', this.updateFileSize); + this.listenTo(this.model, 'change:fileTime', this.updateFileTime); + this.listenTo(this.model, 'change:fileType', this.updateFileType); + this.listenTo(this.model, 'change:value', this.updateValue); + + this.listenTo(this.model, 'change:hintText', this.updateHintText); + this.listenTo(this.model, 'change:errorText', this.updateErrorText); + this.listenTo(this.model, 'change:warningText', this.updateWarningText); + + this.listenTo(this.model, 'invalid', this.onInvalidHandler); + + var acceptTypes = this.model.get('acceptTypes'); + acceptTypes.onChange(this.updateAcceptTypes.bind(this)); + }, + + updateProperties: function(){ + ControlView.prototype.updateProperties.call(this); + + this.updateLabelText(); + this.updateFileName(); + this.updateFileSize(); + this.updateFileType(); + this.updateFileTime(); + this.updateAcceptTypes(); + this.updateValue(); + + this.updateHintText(); + this.updateErrorText(); + this.updateWarningText(); + }, + + updateLabelText: function () { + var labelText = this.model.get('labelText'); + + if(labelText != '') { + this.ui.label + .css({display: 'inline-block'}) + .text(labelText); + } else { + this.ui.label.css({display: 'none'}); + } + }, + + updateAcceptTypes: function () { + var acceptTypes = this.model.get('acceptTypes'); + if (acceptTypes.length === 0) { + this.ui.input.removeAttr('accept'); + } else { + var accept = acceptTypes.toArray().join(','); + this.ui.input.attr('accept', accept); + } + }, + + updateFocusable: function () { + var focusable = this.model.get('focusable'); + + if (focusable) { + this.ui.control.attr('tabindex', 0); + } else { + this.ui.control.removeAttr('tabindex'); + } + }, + + updateText: function () { + var text = this.model.get('text'); + this.ui.btnPick.attr('title', text); + }, + + updateHintText: function(){ + var hintText = this.model.get('hintText'); + if(hintText){ + this.ui.hintText + .text(hintText) + .removeClass('hidden'); + }else{ + this.ui.hintText + .text('') + .addClass('hidden'); + } + + }, + + updateErrorText: function(){ + var errorText = this.model.get('errorText'); + if(errorText){ + this.ui.errorText + .text(errorText) + .removeClass('hidden'); + }else{ + this.ui.errorText + .text('') + .addClass('hidden'); + } + + }, + + updateWarningText: function(){ + var warningText = this.model.get('warningText'); + if(warningText){ + this.ui.warningText + .text(warningText) + .removeClass('hidden'); + }else{ + this.ui.warningText + .text('') + .addClass('hidden'); + } + + }, + + updateEnabled: function () { + ControlView.prototype.updateEnabled.call(this); + + var isEnabled = this.model.get('enabled'); + + this.ui.input.prop('disabled', !isEnabled); + this.ui.btnRemove.prop('disabled', !isEnabled); + this.ui.btnPick.toggleClass('disabled', !isEnabled); + + }, + + updateFileName: function () { + var fileName = this.model.get('fileName'); + this.ui.fileUpload.text(fileName); + this.ui.fileDownloadUrl.text(fileName); + }, + + updateFileSize: function () { + //var fileSize = this.model.get('fileSize'); + // + //var text = ''; + //if (typeof fileSize !== 'undefined' && fileSize !== null) { + // text = InfinniUI.format.humanFileSize(fileSize); + //} + //this.ui.fileSize.text(text); + }, + + updateFileInfo: function() { + return; + var model = this.model; + var + value = model.get('value'), + fileName = model.get('fileName'); + + if (!value || value.length === 0) { + this.ui.info.toggleClass('hidden', true); + this.ui.empty.toggleClass('hidden', false); + } else { + if (!fileName || fileName.length === 0) { + fileName = 'Скачать файл'; + } + this.ui.download.text(fileName); + this.ui.info.toggleClass('hidden', false); + this.ui.empty.toggleClass('hidden', true); + } + }, + + updateFileTime: function () { + var time = this.model.get('fileTime'); + + //@TODO Update file's datetime on view + }, + + updateFileType: function () { + var fileType = this.model.get('fileType'); + + //@TODO Update file's mime type on view + }, + + updateValue: function () { + var model = this.model; + var value = model.get('value'); + + var fileEmpty = false, + fileUpload = false, + fileDownload = false; + + if (value === null || typeof value === 'undefined') { + //No file + fileEmpty = value === null || typeof value === 'undefined'; + this.ui.input.val(null); + this.updateUrl(null); + } else if (value && typeof value === 'object') { + //File instance + fileUpload = value && typeof value === 'object'; + this.updateUrl(null); + } else { + //Url + fileDownload = true; + this.updateUrl(value); + } + + this.ui.fileEmpty.toggleClass('hidden', !fileEmpty); + this.ui.fileUpload.toggleClass('hidden', !fileUpload); + this.ui.fileDownload.toggleClass('hidden', !fileDownload); + + this.ui.btnRemove.toggleClass('hidden', fileEmpty); + this.ui.btnPick.toggleClass('hidden', !fileEmpty); + }, + + updateUrl: function (url) { + this.ui.fileDownloadUrl.attr('href', url); + var none = url === null || typeof url === 'undefined'; + this.$el.toggleClass('pl-empty', none); + this.updateFileInfo(); + }, + + onClickRemoveImageHandler: function () { + this.model.removeFile(); + this.ui.input.val(''); + }, + + onChangeFileHandler: function () { + var file = null; + var files = this.ui.input[0].files; + + if (files && files[0]) { + file = files[0]; + } + this.model.setFile(file); + }, + + render: function () { + this.prerenderingActions(); + + this.renderTemplate(this.template); + this.updateProperties(); + + this.trigger('render'); + + this.postrenderingActions(); + + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + + return this; + }, + + onInvalidHandler: function () { + this.ui.input.val(null); + } + +})); - handler(context, args); - }, owner); - }, +//####app/controls/form/formControl.js +function FormControl(parent) { + _.superClass(FormControl, this, parent); +} - onSelectedItemChanged: function (handler, owner) { - var that = this; +_.inherit(FormControl, StackPanelControl); - this.get('model').onPropertyChanged('selectedItem', function(context, args){ - var argument = that._getArgumentTemplate(); - argument.value = args.newValue; +_.extend(FormControl.prototype, { - handler(context, argument); - }, owner); - }, + createControlModel: function () { + return new FormModel(); + }, - onErrorValidator: function (handler) { - this.on('onErrorValidator', handler); - }, + createControlView: function (model) { + return new FormView({model: model}); + }, - onItemSaved: function (handler) { - this.on('onItemSaved', handler); - }, + onSubmit: function (callback) { + this.controlView.$el.on('submit', callback); + }, - onItemCreated: function (handler) { - this.on('onItemCreated', handler); - }, + setSubmitFunction: function(func) { + this.controlModel.set('submitFunction', func); + }, - onItemsUpdated: function (handler) { - this.on('onItemsUpdated', handler); - }, + getSubmitFunction: function() { + return this.controlModel.get('submitFunction'); + }, - onItemsUpdatedOnce: function (handler) { - this.once('onItemsUpdated', handler); - }, + setMethod: function(method) { + this.controlModel.set('method', method); + }, - onItemDeleted: function (handler) { - this.on('onItemDeleted', handler); - }, + getMethod: function() { + return this.controlModel.get('method'); + }, - onProviderError: function (handler) { - this.on('onProviderError', handler); - }, + setAction: function(action) { + this.controlModel.set('action', action); + }, - getName: function () { - return this.get('name'); - }, + getAction: function() { + return this.controlModel.get('action'); + } - setName: function (name) { - this.set('name', name); - this.name = name; - }, +}); - getView: function () { - return this.get('view'); - }, +//####app/controls/form/formModel.js +var FormModel = StackPanelModel.extend({ - getProperty: function (property) { - var firstChar = property.charAt(0); - var indexOfSelectedItem; + defaults: _.defaults({ + submitFunction: null, + method: '', + action: '' + }, StackPanelModel.prototype.defaults) - if( this.get('isNumRegEx').test(firstChar) ){ - property = 'items.' + property; +}); - }else if(firstChar == ''){ - property = 'items'; +//####app/controls/form/formView.js +/** + * @class FormView + * @augments StackPanelView + */ +var FormView = StackPanelView.extend({ - }else if(firstChar == '$'){ - indexOfSelectedItem = this._indexOfSelectedItem(); - if(indexOfSelectedItem == -1){ - return undefined; - } - property = 'items.' + indexOfSelectedItem + property.substr(1); + className: 'pl-form', - }else if(firstChar == '.'){ - property = property.substr(1); - }else{ - indexOfSelectedItem = this._indexOfSelectedItem(); - if(indexOfSelectedItem == -1){ - return undefined; - } - property = 'items.' + indexOfSelectedItem + '.' + property; - } + tagName: 'form', - return this.get('model').getProperty(property); - }, + template: { + plain: InfinniUI.Template["controls/form/template/form.tpl.html"] + }, - setProperty: function (property, value) { - var propertyPaths = property.split('.'); - var firstChar; - var indexOfSelectedItem; - var index; - var resultOfSet; + events: { + 'submit': 'onSubmit' + }, - if(propertyPaths[0] == '$'){ - indexOfSelectedItem = this._indexOfSelectedItem(); - if(indexOfSelectedItem == -1){ - return; - } + onSubmit: function (e) { + e.preventDefault(); + }, - property = indexOfSelectedItem + property.substr(1); - propertyPaths[0] = indexOfSelectedItem.toString(); - } + initialize: function (options) { + StackPanelView.prototype.initialize.call(this, options); - firstChar = property.charAt(0); + this.listenTo(this.model, 'change:method', this.updateMethod); + this.listenTo(this.model, 'change:action', this.updateAction); + }, - if(propertyPaths.length == 1){ + updateGrouping: function(){ + this.strategy = new StackPanelViewPlainStrategy(this); + }, - if(propertyPaths[0] == ''){ - this._setItems(value); + render: function () { + this.prerenderingActions(); - }else if( this.get('isNumRegEx').test(propertyPaths[0]) ){ - this._changeItem(propertyPaths[0], value); + this.removeChildElements(); - }else{ - indexOfSelectedItem = this._indexOfSelectedItem(); - if(indexOfSelectedItem == -1){ - return; - } - property = 'items.' + indexOfSelectedItem + '.' + property; - resultOfSet = this.get('model').setProperty(property, value); + var preparedItems = this.strategy.prepareItemsForRendering(); + var template = this.strategy.getTemplate(); - if(resultOfSet){ - this._includeItemToModifiedSetByIndex(indexOfSelectedItem); - } - } + this.$el.html(template(preparedItems)); - }else{ - if(firstChar == '.'){ - property = property.substr(1); - this.get('model').setProperty(property, value); + this.strategy.appendItemsContent(preparedItems, '.pl-form-i'); - }else if(this.get('isNumRegEx').test(firstChar)){ - property = 'items.' + property; - resultOfSet = this.get('model').setProperty(property, value); + this.bindUIElements(); + this.updateProperties(); + this.trigger('render'); - if(resultOfSet){ - this._includeItemToModifiedSetByIndex( parseInt(propertyPaths[0])); - } - }else{ - indexOfSelectedItem = this._indexOfSelectedItem(); - if(indexOfSelectedItem == -1){ - return; - } - property = 'items.' + indexOfSelectedItem + '.' + property; - resultOfSet = this.get('model').setProperty(property, value); + this.postrenderingActions(); - if(resultOfSet){ - this._includeItemToModifiedSetByIndex(indexOfSelectedItem); - } - } - } - }, + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + + return this; + }, - _setItems: function (items) { - this._detectIdentifyingMode(items); + updateProperties: function() { + StackPanelView.prototype.updateProperties.call(this); - var indexOfItemsById; + this.updateMethod(); + this.updateAction(); + }, - this.set('isDataReady', true); - this.get('model').setProperty('items', items); - this._clearModifiedSet(); - if (items && items.length > 0) { - indexOfItemsById = this._indexItemsById(items); - this.set('itemsById', indexOfItemsById); + updateMethod: function() { + var method = this.model.get('method'); - if( !this._restoreSelectedItem() ){ - this.setSelectedItem(items[0]); - } + this.$el.attr('method', method); + }, - } else { - this.setSelectedItem(null); - } - }, + updateAction: function() { + var action = this.model.get('action'); - _restoreSelectedItem: function(){ - // override by strategy - var logger = window.InfinniUI.global.logger; - logger.warn({ - message: 'BaseDataSource._restoreSelectedItem: not overrided by strategy', - source: this - }); - }, + this.$el.attr('action', action); + } - getSelectedItem: function () { - return this.get('model').getProperty('selectedItem'); - }, +}); - setSelectedItem: function (item, success, error) { - // override by strategy - var logger = window.InfinniUI.global.logger; - logger.warn({ - message: 'BaseDataSource.setSelectedItem: not overrided by strategy', - source: this - }); - }, +//####app/controls/frame/frameControl.js +/** + * + * @constructor + * @augments Control + * @mixes editorBaseControlMixin + */ +var FrameControl = function () { + _.superClass(FrameControl, this); + this.initialize_editorBaseControl(); +}; + +_.inherit(FrameControl, Control); + +_.extend(FrameControl.prototype, { + + createControlModel: function () { + return new FrameModel(); + }, + + createControlView: function (model) { + return new FrameView({model: model}); + } + +}, editorBaseControlMixin); +//####app/controls/frame/frameModel.js +var FrameModel = ControlModel.extend(_.extend({ + + defaults: _.defaults({}, + editorBaseModelMixin.defaults_editorBaseModel, + ControlModel.prototype.defaults + ), + + initialize: function(){ + ControlModel.prototype.initialize.apply(this, arguments); + this.initialize_editorBaseModel(); + } +}, editorBaseModelMixin)); +//####app/controls/frame/frameView.js +/** + * @class FrameView + * @augments ControlView + * @mixes editorBaseViewMixin + */ +var FrameView = ControlView.extend(_.extend({}, editorBaseViewMixin, /** @lends FrameView.prototype */{ + + className: 'pl-frame', + + template: InfinniUI.Template["controls/frame/template/frame.tpl.html"], + + UI: _.extend({}, editorBaseViewMixin.UI, { + iframe: 'iframe' + }), + + initialize: function () { + ControlView.prototype.initialize.apply(this); + }, + + initHandlersForProperties: function(){ + ControlView.prototype.initHandlersForProperties.call(this); + editorBaseViewMixin.initHandlersForProperties.call(this); + }, + + updateProperties: function(){ + ControlView.prototype.updateProperties.call(this); + editorBaseViewMixin.updateProperties.call(this); + }, + + updateValue: function(){ + var value = this.model.get('value'); + + this.ui.iframe.attr('src', value); + }, + + getData: function () { + return _.extend( + {}, + ControlView.prototype.getData.call(this), + editorBaseViewMixin.getData.call(this), + { + + } + ); + }, + + render: function () { + var model = this.model; + + this.prerenderingActions(); + this.renderTemplate(this.template); + + this.updateProperties(); + + this.trigger('render'); + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + } + +})); - _notifyAboutSelectedItem: function (item, successHandler) { - var context = this.getContext(), - argument = this._getArgumentTemplate(); +//####app/controls/gridPanel/gridPanelControl.js +/** + * + * @param parent + * @constructor + * @augments ContainerControl + */ +function GridPanelControl(parent) { + _.superClass(GridPanelControl, this, parent); +} - argument.value = item; +_.inherit(GridPanelControl, ContainerControl); - if (successHandler) { - successHandler(context, argument); +_.extend(GridPanelControl.prototype, + /** @lends GridPanelControl.prototype */ + { + createControlModel: function () { + return new GridPanelModel(); + }, + + createControlView: function (model) { + return new GridPanelView({model: model}); } - }, + } +); - _tuneMirroringOfModel: function(index){ - if(index != -1){ - this.get('model').setMirroring('items.$', 'items.'+index); - }else{ - this.get('model').setMirroring(null, null); + +//####app/controls/gridPanel/gridPanelModel.js +/** + * @constructor + * @augments ContainerModel + */ +var GridPanelModel = ContainerModel.extend( + /** @lends GridPanelModel.prototype */ + { + initialize: function () { + ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); } - }, + } +); +//####app/controls/gridPanel/gridPanelView.js +/** + * @class + * @augments ControlView + */ +var GridPanelView = ContainerView.extend( + /** @lends GridPanelView.prototype */ + { + className: 'pl-grid-panel pl-clearfix', - getIdProperty: function () { - return this.get('idProperty'); - }, + columnCount: 12, - setIdProperty: function (value) { - this.set('idProperty', value); - }, + template: { + row: InfinniUI.Template["controls/gridPanel/template/row.tpl.html"] + }, - getFillCreatedItem: function () { - return this.get('fillCreatedItem'); - }, + initialize: function (options) { + ContainerView.prototype.initialize.call(this, options); + }, - setFillCreatedItem: function (fillCreatedItem) { - this.set('fillCreatedItem', fillCreatedItem); - }, + render: function () { + this.prerenderingActions(); - suspendUpdate: function (name) { - var reason = name || 'default'; + this.removeChildElements(); - var suspended = this.get('suspendingList'); - if (suspended.indexOf(reason) === -1) { - suspended = suspended.slice(0); - suspended.push(reason); - this.set('suspendingList', suspended); - } - }, + this.renderItemsContents(); + this.updateProperties(); + this.trigger('render'); - resumeUpdate: function (name) { - var reason = name || 'default'; + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, - var suspended = this.get('suspendingList'); - var index = suspended.indexOf(reason); + renderItemsContents: function(){ + var items = this.model.get('items'), + itemTemplate = this.model.get('itemTemplate'), + view = this, + row = [], + rowSize = 0, + element, item; - if (index !== -1) { - suspended = suspended.slice(0); - suspended.splice(index, 1); - this.set('suspendingList', suspended); + //this.$el.hide(); + items.forEach(function(item, i){ + element = itemTemplate(undefined, {item: item, index: i}); + var span = element.getColumnSpan(); + if (rowSize + span > view.columnCount) { + view.renderRow(row); + row.length = 0; + rowSize = 0; + } - // если источник полностью разморожен, а до этого вызывались updateItems, не выполненные из-за заморозки, нужно вызвать updateItems - if(!this.isUpdateSuspended() && this.get('waitingOnUpdateItemsHandlers').length > 0){ - this.updateItems(); - } - } - }, + row.push(element); + rowSize += span; + }); - isUpdateSuspended: function () { - var suspended = this.get('suspendingList'); - return suspended.length > 0; - }, + if (row.length) { + view.renderRow(row); + } + //this.$el.show(); + }, - isModifiedItems: function () { - return this.isModified(); - }, + renderRow: function (row) { + var view = this; + // var $row = $(this.template.row()); + var $row = $('
'); + $row.append(row.map(function(element) { + view.addChildElement(element); + return element.render(); + })); + this.$el.append($row); + }, - isModified: function (item) { - if (arguments.length == 0) { - return _.size(this.get('modifiedItems')) > 0; - } + updateGrouping: function(){} + } +); - if (item === null || item === undefined) { - return false; - } - else { - var itemId = this.idOfItem(item); - return itemId in this.get('modifiedItems'); - } - }, +//####app/controls/icon/iconControl.js +/** + * + * @param parent + * @constructor + * @augments Control + */ +function IconControl() { + _.superClass(IconControl, this); +} - _includeItemToModifiedSetByIndex: function (index) { - var item; +_.inherit(IconControl, Control); - item = this.getItems()[index]; - this._includeItemToModifiedSet(item); - }, +_.extend(IconControl.prototype, { - _includeItemToModifiedSet: function (item) { - // override by strategy - var logger = window.InfinniUI.global.logger; - logger.warn({ - message: 'BaseDataSource._includeItemToModifiedSet: not overrided by strategy', - source: this - }); + createControlModel: function () { + return new IconModel(); }, - _excludeItemFromModifiedSet: function (item) { - // override by strategy - var logger = window.InfinniUI.global.logger; - logger.warn({ - message: 'BaseDataSource._excludeItemFromModifiedSet: not overrided by strategy', - source: this - }); - }, + createControlView: function (model) { + return new IconView({model: model}); + } - _clearModifiedSet: function () { - this.set('modifiedItems', {}); - }, +}); +//####app/controls/icon/iconModel.js +/** + * @class + * @augments ControlModel + */ +var IconModel = ControlModel.extend({ - /** - * @description Проверяет формат имя свойства атрибута - * @param propertyName - * @private - */ - _checkPropertyName: function (propertyName) { - var result = true; - try { - if (propertyName && propertyName.length > 0) { - result = propertyName.match(/^[\$#@\d]+/); - } - if (!result) { - throw new Error('Wrong property name "' + propertyName + '"'); - } - } catch (e) { - console.debug(e); - } - }, + defaults: _.defaults({ + value: null, + focusable: false - _changeItem: function(index, value){ - var item = this.get('model').getProperty('items.'+index), - isSelectedItem = (item == this.getSelectedItem()), - idProperty = this.get('idProperty'), - indexedItemsById = this.get('itemsById'); + }, ControlModel.prototype.defaults), - if(value == item){ - return; - } + initialize: function () { + ControlModel.prototype.initialize.apply(this, arguments); + } - this._excludeItemFromModifiedSet(item); - delete indexedItemsById[item[idProperty]]; +}); +//####app/controls/icon/iconView.js +/** + * @class IconView + * @arguments ControlView + */ +var IconView = ControlView.extend({ - this.get('model').setProperty('items.'+index, value); + className: 'pl-icon fa', - this._includeItemToModifiedSet(value); - indexedItemsById[value[idProperty]] = value; - this.set('itemsById', indexedItemsById); + tagName: 'i', - if(isSelectedItem) { - this.get('model').setProperty('selectedItem', value); - } + render: function(){ + this.prerenderingActions(); + this.updateProperties(); + this.trigger('render'); + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; }, - tryInitData: function(){ - if (!this.get('isDataReady') && !this.get('isRequestInProcess')){ - this.updateItems(); - } + renderIcon: function () { + var value = this.model.get('value'); + this.switchClass('fa', value); }, - saveItem: function (item, success, error) { - var dataProvider = this.get('dataProvider'), - ds = this, - logger = window.InfinniUI.global.logger, - that = this, - validateResult, - errorInProvider = this._compensateOnErrorOfProviderHandler(error); - - if (!this.isModified(item)) { - this._notifyAboutItemSaved({item: item, result: null}, 'notModified'); - that._executeCallback(success, {item: item, result: {IsValid: true}}); - return; - } - - validateResult = this.validateOnErrors(item); - if (!validateResult.IsValid) { - this._executeCallback(error, {item: item, result: validateResult}); - return; - } - - dataProvider.saveItem(item, function(data){ - if( !('IsValid' in data) || data.IsValid === true ){ - that._excludeItemFromModifiedSet(item); - that._notifyAboutItemSaved({item: item, result: data.data}, 'modified'); - that._executeCallback(success, {item: item, result: that._getValidationResult(data)}); - }else{ - var result = that._getValidationResult(data); - that._notifyAboutValidation(result, 'error'); - that._executeCallback(error, {item: item, result: result}); - } - }, function(data) { - var result = that._getValidationResult(data); - that._notifyAboutValidation(result, 'error'); - that._executeCallback(errorInProvider, {item: item, result: result}); - }); + initHandlersForProperties: function () { + ControlView.prototype.initHandlersForProperties.call(this); + this.listenTo(this.model, 'change:value', this.updateValue); }, - _getValidationResult: function(data){ - if(data.data && data.data.responseJSON && data.data.responseJSON['Result']){ - return data.data.responseJSON['Result']['ValidationResult']; - } - - return data.data && data.data['Result'] && data.data['Result']['ValidationResult']; + updateProperties: function () { + ControlView.prototype.updateProperties.call(this); + this.updateValue(); }, - _executeCallback: function(callback, args){ - if(callback){ - callback(this.getContext(), args); + updateFocusable: function () { + var focusable = this.model.get('focusable'); + + if (focusable) { + this.$el.attr('tabindex', 0); + } else { + this.$el.removeAttr('tabindex'); } }, - _notifyAboutItemSaved: function (data, result) { - var context = this.getContext(), - argument = this._getArgumentTemplate(); - - argument.value = data; - argument.result = result; - - this.trigger('onItemSaved', context, argument); - }, + updateValue: function () { + this.renderIcon(); + } - deleteItem: function (item, success, error) { - var dataProvider = this.get('dataProvider'), - that = this, - itemId = this.idOfItem(item), - isItemInSet = this.get('itemsById')[itemId] !== undefined, - errorInProvider = this._compensateOnErrorOfProviderHandler(error); +}); - if ( item == null || ( itemId !== undefined && !isItemInSet ) ) { - this._notifyAboutMissingDeletedItem(item, error); - return; - } +//####app/controls/imageBox/imageBoxControl.js +/** + * + * @param parent + * @constructor + * @augments Control + * @mixes editorBaseControlMixin + */ +function ImageBoxControl(parent) { + _.superClass(ImageBoxControl, this, parent); + this.initialize_editorBaseControl(); +} + +_.inherit(ImageBoxControl, Control); + +_.extend(ImageBoxControl.prototype, { + + createControlModel: function () { + return new ImageBoxModel(); + }, + + createControlView: function (model) { + return new ImageBoxView({model: model}); + } + +}, editorBaseControlMixin); + - this.beforeDeleteItem(item); +//####app/controls/imageBox/imageBoxModel.js +/** + * @constructor + * @augments ControlModel + * @mixes editorBaseModelMixin + */ +var ImageBoxModel = ControlModel.extend( _.extend({ + + defaults: _.defaults({ + text: localized.strings.ImageBox.chooseImage + }, + editorBaseModelMixin.defaults_editorBaseModel, + ControlModel.prototype.defaults + ), + + initialize: function () { + ControlModel.prototype.initialize.apply(this, arguments); + this.initialize_editorBaseModel(); + + this.set('acceptTypes', new Collection()); + this.on('change:file', this.onChangeFileHandler); + + this.on("invalid", function(model, error) { + this.set('errorText', error); + }); + }, + + validate: function (attrs, options) { + var file = attrs.file; + var maxSize = this.get('maxSize'); + var acceptTypes = this.get('acceptTypes'); + if (file) { + if (maxSize) { + if (file.size > maxSize) { + return localized.strings.ImageBox.imageSizeTooBig + .replace(/\{chosen-size\}/g, (file.size/(1024*1024)).toFixed(1)) + .replace(/\{permitted-size\}/g, (maxSize/(1024*1024)).toFixed(1)); + } + } + + if (acceptTypes.length && !acceptTypes.contains(file.type)) { + return localized.strings.ImageBox.incorrectFormat; + } + } + }, + + setFile: function (file) { + if (this.set('file', file, {validate: true})) { + this.set('errorText', ''); + } + }, + + removeFile: function () { + this.setFile(null); + }, + + onChangeFileHandler: function (model, file) { + //this.stopLoadingFile(); + //if (file) { + // var fileLoader = this.loadPreview(file); + // + // this.fileLoader = fileLoader; + // + // fileLoader.then(function (file, content) { + // model.set('value', content); + // }, function (err) { + // console.log(err); + // }); + //} else { + // model.set('value', null); + //} + }, + + //stopLoadingFile: function () { + // var fileLoader = this.fileLoader; + // if (fileLoader && fileLoader.state() === 'pending') { + // fileLoader.reject(); + // } + //}, + // + //loadPreview: function (file) { + // var defer = $.Deferred(); + // var reader = new FileReader(); + // reader.onload = (function (file) { + // return function (event) { + // defer.resolve(file, event.target.result); + // }; + // }(file)); + // reader.onerror = function (event) { + // defer.reject(event); + // }; + // reader.readAsDataURL(file); + // return defer.promise(); + //} + +}, editorBaseModelMixin)); +//####app/controls/imageBox/imageBoxView.js +/** + * @augments ControlView + * @mixes editorBaseViewMixin + * @constructor + */ +var ImageBoxView = ControlView.extend(/** @lends ImageBoxView.prototype */ _.extend({}, editorBaseViewMixin, { + + className: 'pl-imagebox', + + template: InfinniUI.Template["controls/imageBox/template/imageBox.tpl.html"], + + UI: _.extend({}, editorBaseViewMixin.UI, { + input: 'input', + img: 'img', + file: '.pl-image-file', + remove: '.pl-image-remove', + uploadButton: '.pl-image-file-upload-button' + }), + + events: { + 'change input': 'onChangeFileHandler', + 'click .pl-image-remove': 'onClickRemoveImageHandler' + }, + + + initHandlersForProperties: function(){ + ControlView.prototype.initHandlersForProperties.call(this); + + this.listenTo(this.model, 'change:value', this.updateValue); + this.listenTo(this.model, 'change:hintText', this.updateHintText); + this.listenTo(this.model, 'change:errorText', this.updateErrorText); + this.listenTo(this.model, 'change:warningText', this.updateWarningText); + }, + + updateProperties: function(){ + ControlView.prototype.updateProperties.call(this); + + this.updateValue(); + this.updateHintText(); + this.updateErrorText(); + this.updateWarningText(); + }, + + updateFocusable: function () { + var focusable = this.model.get('focusable'); + + if (focusable) { + this.ui.file.attr('tabindex', 0); + } else { + this.ui.file.removeAttr('tabindex'); + } + }, + + updateText: function () { + var text = this.model.get('text'); + this.ui.uploadButton.text(text); + }, + + updateEnabled: function () { + ControlView.prototype.updateEnabled.call(this); + var isEnabled = this.model.get('enabled'); + this.ui.input.prop('disabled', !isEnabled); + }, + + updateValue: function () { + var model = this.model; + var value = model.get('value'); + + if (value && typeof value === 'object') { + //Native FileAPI File instance, start loading preview + this.stopLoadingFile(); + var fileLoader = this.loadPreview(value); + + this.fileLoader = fileLoader; + + fileLoader.then(function (file, content) { + this.updateUrl(content); + }.bind(this), function (err) { + console.log(err); + }); + } else { + this.updateUrl(value); + } + }, + + updateUrl: function (url) { + this.ui.img.attr('src', url); + var none = url === null || typeof url === 'undefined'; + this.$el.toggleClass('pl-empty', none); + }, + + stopLoadingFile: function () { + var fileLoader = this.fileLoader; + if (fileLoader && fileLoader.state() === 'pending') { + fileLoader.reject(); + } + }, + + loadPreview: function (file) { + var defer = $.Deferred(); + var reader = new FileReader(); + reader.onload = (function (file) { + return function (event) { + defer.resolve(file, event.target.result); + }; + }(file)); + reader.onerror = function (event) { + defer.reject(event); + }; + reader.readAsDataURL(file); + return defer.promise(); + }, + + onClickRemoveImageHandler: function () { + this.model.removeFile(); + this.ui.input.val(''); + }, + + onChangeFileHandler: function () { + var file = null; + var files = this.ui.input[0].files; + + if (files && files[0]) { + file = files[0]; + } + this.model.setFile(file); + }, + + render: function () { + this.prerenderingActions(); + + this.renderTemplate(this.template); + this.updateProperties(); + + this.trigger('render'); + + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + } + +})); - dataProvider.deleteItem(item, function (data) { - if (!('IsValid' in data) || data['IsValid'] === true) { - that._handleDeletedItem(item, success); - } else { - var result = that._getValidationResult(data); - that._notifyAboutValidation(result, 'error'); - that._executeCallback(error, {item: item, result: result}); - } - }, function(data) { - var result = that._getValidationResult(data); - that._notifyAboutValidation(result, 'error'); - that._executeCallback(errorInProvider, {item: item, result: result}); - }); - }, +//####app/controls/indeterminateCheckBox/indeterminateCheckBoxControl.js +function IndeterminateCheckBoxControl(parent) { + _.superClass(IndeterminateCheckBoxControl, this, parent); + this.initialize_editorBaseControl(); +} - beforeDeleteItem: function(item){}, +_.inherit(IndeterminateCheckBoxControl, CheckBoxControl); - _handleDeletedItem: function (item, successHandler) { - // override by strategy - var logger = window.InfinniUI.global.logger; - logger.warn({ - message: 'BaseDataSource._handleDeletedItem: not overrided by strategy', - source: this - }); - }, +_.extend(IndeterminateCheckBoxControl.prototype, { - _notifyAboutItemDeleted: function (item, successHandler) { - var context = this.getContext(), - argument = this._getArgumentTemplate(); + createControlModel: function () { + return new IndeterminateCheckBoxModel(); + }, - argument.value = item; + createControlView: function (model) { + return new IndeterminateCheckBoxView({model: model}); + } - if (successHandler) { - successHandler(context, argument); - } - this.trigger('onItemDeleted', context, argument); - }, +}, editorBaseControlMixin); - _notifyAboutMissingDeletedItem: function (item, errorHandler) { - var context = this.getContext(), - argument = this._getArgumentTemplate(); - argument.value = item; - argument.error = { - message: 'Нельзя удалить элемент, которого нет текущем наборе источника данных' - }; +//####app/controls/indeterminateCheckBox/indeterminateCheckBoxModel.js +var IndeterminateCheckBoxModel = CheckBoxModel.extend({ - if (errorHandler) { - errorHandler(context, argument); - } - }, + defaults: _.defaults({ + value: 'unchecked' + }, CheckBoxModel.prototype.defaults) - isDataReady: function () { - return this.get('isDataReady'); - }, +}); - getItems: function () { - var logger = window.InfinniUI.global.logger; +//####app/controls/indeterminateCheckBox/indeterminateCheckBoxView.js +/** + * @class IndeterminateCheckBoxView + * @augments ControlView + * @mixes editorBaseViewMixin + */ +var IndeterminateCheckBoxView = CheckBoxView.extend({ - if (!this.isDataReady()) { - logger.warn({ - message: 'BaseDataSource: Попытка получить данные источника данных (' + this.get('name') + '), до того как он был проинициализирован данными', - source: this - }); - } + className: 'pl-indeterminate-checkbox', - return this.get('model').getProperty('items'); - }, + onClickHandler: function () { + var model = this.model; - updateItems: function (onSuccess, onError) { - if (!this.isUpdateSuspended()) { - var dataProvider = this.get('dataProvider'), - that = this; + var enabled = model.get('enabled'); + if (enabled) { + var newValue = model.get('value'); + newValue = newValue === 'indeterminate' ? 'unchecked' : newValue === 'unchecked' ? 'checked' : 'unchecked'; + model.set('value', newValue); + } + }, + updateValue: function () { + var value = this.model.get('value'); + if( value === 'checked' ) { + this.ui.input.prop('indeterminate', false); + this.ui.input.prop('checked', true); + } else if( value === 'unchecked' ) { + this.ui.input.prop('indeterminate', false); + this.ui.input.prop('checked', false); + } else if( value === 'indeterminate' ) { + this.ui.input.prop('checked', false); + this.ui.input.prop('indeterminate', true); + } - onError = this._compensateOnErrorOfProviderHandler(onError); + } +}); +//####app/controls/link/linkElementControl.js +/** + * + * @param parent + * @constructor + * @augments Control + */ +function LinkElementControl() { + _.superClass(LinkElementControl, this); +} - this.set('isRequestInProcess', true); - dataProvider.getItems( - function (data) { - that._handleSuccessUpdateItemsInProvider(data, onSuccess, onError); - }, - onError - ); +_.inherit(LinkElementControl, ButtonControl); - }else{ - var handlers = this.get('waitingOnUpdateItemsHandlers'); - handlers.push({ - onSuccess: onSuccess, - onError: onError - }); +_.extend( + LinkElementControl.prototype, { + + createControlModel: function () { + return new LinkElementModel(); + }, + + createControlView: function (model) { + return new LinkElementView({model: model}); } - //devblockstart - window.InfinniUI.global.messageBus.send('updateItems', {dataSource: this}); - //devblockstop - }, + }); - _compensateOnErrorOfProviderHandler: function(onError){ - var that = this; +//####app/controls/link/linkElementModel.js +/** + * @class + * @augments ButtonModel + */ +var LinkElementModel = ButtonModel.extend({ - return function(){ - if(typeof onError == 'function'){ - onError.apply(undefined, arguments); - }else{ - that.trigger('onProviderError', arguments); - } - }; + defaults: _.defaults({ + href: "javascript:;", + target: "self" + }, ButtonModel.prototype.defaults), - }, + initialize: function () { + ButtonModel.prototype.initialize.apply(this, arguments); + } - _handleSuccessUpdateItemsInProvider: function(data, onSuccess, onError){ - var that = this, - isWaiting = that.get('isWaiting'), - finishUpdating = function(){ - that.set('isRequestInProcess', false); - that._handleUpdatedItemsData(data.data, onSuccess, onError); - }; +}); - if(isWaiting){ - that.once('change:isWaiting', function () { - finishUpdating(); - }); - } else { - finishUpdating(); - } - }, +//####app/controls/link/linkElementView.js +/** + * @class LinkElementView + * @augments CommonButtonView + */ +var LinkElementView = CommonButtonView.extend({ - _onErrorProviderUpdateItemsHandle: function(){ + tagName: 'a', - }, + className: 'pl-link', - setIsWaiting: function(value){ - this.set('isWaiting', value); + events: { + 'click': 'onClickHandler' }, - _handleUpdatedItemsData: function (itemsData, successHandler, errorHandler) { - if(this.get('newItemsHandler')){ - itemsData = this.get('newItemsHandler')(itemsData); - } + template: function(){return '';}, - this.setProperty('', itemsData); - this._notifyAboutItemsUpdated(itemsData, successHandler, errorHandler); + updateProperties: function(){ + CommonButtonView.prototype.updateProperties.call(this); + + this.updateHref(); + this.updateTarget(); }, - _notifyAboutItemsUpdated: function (itemsData, successHandler, errorHandler) { - var context = this.getContext(); - var argument = { - value: itemsData, - source: this - }; + getButtonElement: function(){ + return this.$el; + }, - // вызываем обработчики которые были переданы на отложенных updateItems (из за замороженного источника) - var handlers = this.get('waitingOnUpdateItemsHandlers'); - for(var i = 0, ii = handlers.length; i < ii; i++){ - if(handlers[i].onSuccess){ - handlers[i].onSuccess(context, argument); - } - } + initHandlersForProperties: function(){ + CommonButtonView.prototype.initHandlersForProperties.call(this); - this.set('waitingOnUpdateItemsHandlers', []); + this.listenTo(this.model, 'change:href', this.updateHref); + this.listenTo(this.model, 'change:target', this.updateTarget); + }, - if (successHandler) { - successHandler(context, argument); - } + updateHref: function() { + var newHref = this.model.get('href'), + $link = this.getButtonElement(); - this.trigger('onItemsUpdated', context, argument); + $link.attr('href', newHref); }, - _notifyAboutItemsUpdatedAsPropertyChanged: function (itemsData) { - var context = this.getContext(), - argument = this._getArgumentTemplate(); - - argument.property = ''; - argument.newValue = itemsData; - argument.oldValue = null; + updateTarget: function() { + var newTarget = this.model.get('target'), + $link = this.getButtonElement(); - this.trigger('onPropertyChanged', context, argument); - this.trigger('onPropertyChanged:', context, argument); + $link.attr('target', '_' + newTarget); }, - createItem: function (success, error) { - var dataProvider = this.get('dataProvider'), - idProperty = this.get('idProperty'), - that = this, - localItem; - - if (this.get('fillCreatedItem')) { - dataProvider.createItem( - function (item) { - that._handleDataForCreatingItem(item, success); - }, - idProperty - ); - } else { - localItem = dataProvider.createLocalItem(idProperty); - this._handleDataForCreatingItem(localItem, success); + onClickHandler: function(e) { + var href = this.model.get('href'); + if( href.indexOf('http://') === -1 ) { + InfinniUI.AppRouter.navigate(href, {trigger: true}); + if( e.which !== 2 ) { + e.preventDefault(); + } } - }, + } - _handleDataForCreatingItem: function (itemData, successHandler) { - var items = this.getItems(); +}); - if(items) { - items = items.slice(); - items.push(itemData); - }else{ - items = [itemData]; - } +//####app/controls/loaderIndicator/loaderIndicator.js +(function () { + var template = InfinniUI.Template["controls/loaderIndicator/template.tpl.html"]; + + InfinniUI.loaderIndicator = { + show: function(){ + $.blockUI({ + message: $(template()), + ignoreIfBlocked: true, + baseZ: 99999 + }); + }, + hide: function(){ + $.unblockUI(); + } + }; + + if (!InfinniUI.config.useLoaderIndicator) { + return; + } + + jQuery(function () { + var $indicator = $(template()); + $('body').append($indicator); + $.blockUI.defaults.css = {}; + $(document).ajaxStart(function () { + $.blockUI({ + message: $indicator, + ignoreIfBlocked: true, + baseZ: 99999 + }); + }) + .ajaxStop(function () { + $.unblockUI(); + }) + .ajaxError(function () { + $.unblockUI(); + }); + }); + +})(); +//####app/controls/menuBar/menuBarControl.js +/** + * + * @param parent + * @constructor + * @augments ContainerControl + */ +function MenuBarControl(parent) { + _.superClass(MenuBarControl, this, parent); +} - this.setProperty('', items); - this._includeItemToModifiedSet(itemData); - this.setSelectedItem(itemData); - this._notifyAboutItemCreated(itemData, successHandler); - }, +_.inherit(MenuBarControl, ContainerControl); - _notifyAboutItemCreated: function (createdItem, successHandler) { - var context = this.getContext(), - argument = { - value: createdItem - }; +_.extend(MenuBarControl.prototype, + /** @lends MenuBarControl.prototype */ + { + createControlModel: function () { + return new MenuBarModel(); + }, - if (successHandler) { - successHandler(context, argument); + createControlView: function (model) { + return new MenuBarView({model: model}); } - this.trigger('onItemCreated', context, argument); - }, - - getFilter: function () { - }, + } +); - setFilter: function (value, onSuccess, onError) { - }, - _setCriteriaList: function(criteriaList, onSuccess, onError){ - this.set('criteriaList', criteriaList); - this.updateItems(onSuccess, onError); - }, +//####app/controls/menuBar/menuBarModel.js +/** + * @constructor + * @augments ContainerModel + */ +var MenuBarModel = ContainerModel.extend( + /** @lends MenuBarModel.prototype */ + { + initialize: function () { + ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + } + } +); +//####app/controls/menuBar/menuBarView.js +/** + * @class + * @augments ControlView + */ +var MenuBarView = ContainerView.extend( + /** @lends MenuBarView.prototype */ + { + tagName: 'nav', + className: 'pl-menu-bar navbar navbar-default', - setIdFilter: function (itemId) { - var dataProvider = this.get('dataProvider'), - idFilter = dataProvider.createIdFilter(itemId); + template: InfinniUI.Template["controls/menuBar/template/menuBar.tpl.html"], - this.setFilter(idFilter); - }, + UI: { - setNewItemsHandler: function(handler){ - this.set('newItemsHandler', handler); - }, + }, - getErrorValidator: function () { - return this.get('errorValidator'); - }, + render: function () { + this.prerenderingActions(); - setErrorValidator: function (validatingFunction) { - this.set('errorValidator', validatingFunction); - }, + this.removeChildElements(); - validateOnErrors: function (item, callback) { - var validatingFunction = this.get('errorValidator'), - result = { - IsValid: true, - Items: [] - }, - isCheckingOneItem = !!item, - context = this.getContext(), - items, subResult, itemIndex; + this.$el.html(this.template({ + items: this.model.get('items') + })); + this.renderItemsContents(); - if (validatingFunction) { - if (isCheckingOneItem) { + this.bindUIElements(); - result = validatingFunction(context, item); + this.updateProperties(); + this.trigger('render'); - } else { + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, - items = this.getItems(); - for (var i = 0, ii = items.length; i < ii; i++) { + renderItemsContents: function(){ + var $items = this.$el.find('.pl-menu-bar-item'), + items = this.model.get('items'), + itemTemplate = this.model.get('itemTemplate'), + that = this, + element, item; - subResult = validatingFunction(context, items[i]); - if (!subResult.IsValid) { - this._addIndexToPropertiesOfValidationMessage(subResult.Items, i); - result.IsValid = false; - result.Items = _.union(result.Items, subResult.Items); - } + $items.each(function(i, el){ + item = items.getByIndex(i); + element = itemTemplate(undefined, {item: item, index: i}); + that.addChildElement(element); + $(el) + .append(element.render()); + }); + }, - } + updateGrouping: function(){} + } +); - } - } +//####app/controls/numericBox/numericBoxControl.js +/** + * + * @param parent + * @constructor + * @augments TextEditorBaseControl + */ +function NumericBoxControl(parent) { + _.superClass(NumericBoxControl, this, parent); +} + +_.inherit(NumericBoxControl, TextEditorBaseControl); + +_.extend(NumericBoxControl.prototype, { + + createControlModel: function () { + return new NumericBoxModel(); + }, + + createControlView: function (model) { + return new NumericBoxView({model: model}); + } +}); + - this._notifyAboutValidation(result, 'error'); - this._executeCallback(callback, {item: item, result: result}); +//####app/controls/numericBox/numericBoxModel.js +/** + * @class + * @augments TextEditorBaseModel + */ +var NumericBoxModel = TextEditorBaseModel.extend(/** @lends TextBoxModel.prototype */{ + defaults: _.defaults( + { + increment: 1, + inputType: 'number' + }, + TextEditorBaseModel.prototype.defaults + ), + + incValue: function () { + var delta = this.get('increment'); + this.addToValue(delta); + }, + + decValue: function () { + var delta = this.get('increment'); + this.addToValue(-delta); + }, + + addToValue: function (delta) { + + var value = this.get('value'); + var startValue = this.get('startValue'); + var minValue = this.get('minValue'); + var maxValue = this.get('maxValue'); + + var newValue = _.isNumber(value) ? value : +value; + + if (this.isSetValue(value) && _.isNumber(value)) { + newValue += delta; + } else { + newValue = (_.isNumber(startValue)) ? startValue : 0; + } + + if (_.isNumber(minValue) && newValue < minValue) { + newValue = minValue; + } else if (_.isNumber(maxValue) && newValue > maxValue) { + newValue = maxValue; + } + + this.set('value', newValue); + }, + + initialize: function () { + TextEditorBaseModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + }, + + validateValue: function (value, callback) { + + var + isValid = true, + min = this.get('minValue'), + max = this.get('maxValue'); + + if (!this.isSetValue(value)) { + return true; + } + + if (_.isNumber(min) && _.isNumber(max)) { + if (value < min || value > max) { + isValid = false + } + } else if (_.isNumber(min) && value < min) { + isValid = false; + } else if (_.isNumber(max) && value > max) { + isValid = false; + } + + return isValid; + } + + +}); +//####app/controls/numericBox/numericBoxView.js +/** + * @class + * @augments TextEditorBaseView + */ +var NumericBoxView = TextEditorBaseView.extend(/** @lends TextBoxView.prototype */{ + + className: "pl-numericbox form-group", + + template: InfinniUI.Template["controls/numericBox/template/numericBox.tpl.html"], + + UI: _.extend({}, TextEditorBaseView.prototype.UI, { + min: '.pl-numeric-box-min', + max: '.pl-numeric-box-max' + }), + + events: _.extend({}, TextEditorBaseView.prototype.events, { + 'click .pl-numeric-box-min': 'onClickMinControlHandler', + 'click .pl-numeric-box-max': 'onClickMaxControlHandler', + 'mousedown .pl-numeric-box-min': 'onMousedownMinControlHandler', + 'mousedown .pl-numeric-box-max': 'onMousedownMaxControlHandler' + }), + + render: function () { + this.prerenderingActions(); + this.renderTemplate(this.template); + this.renderNumericBoxEditor(); + this.updateProperties(); + this.trigger('render'); + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, + + getData: function () { + var + model = this.model; + + return _.extend({}, + TextEditorBaseView.prototype.getData.call(this), { + minValue: model.get('minValue'), + maxValue: model.get('maxValue'), + increment: model.get('increment') + }); + }, + + renderNumericBoxEditor: function () { + this.renderControlEditor(); + }, + + onChangeEnabledHandler: function (model, value) { + this.ui.control.prop('disabled', !value); + this.ui.min.prop('disabled', !value); + this.ui.max.prop('disabled', !value); + }, + + onClickMinControlHandler: function () { + if (this.canChangeValue()) { + this.model.decValue(); + } + }, + + onClickMaxControlHandler: function () { + if (this.canChangeValue()) { + this.model.incValue(); + } + }, + + onMousedownMinControlHandler: function (event) { + if (this.canChangeValue()) { + this.repeatUpdateValue(this.model.decValue.bind(this.model)); + } + }, + + onMousedownMaxControlHandler: function (event) { + if (this.canChangeValue()) { + this.repeatUpdateValue(this.model.incValue.bind(this.model)); + } + }, + + repeatUpdateValue: function (cb) { + var intervalId; + + window.document.addEventListener('mouseup', stopRepeat); + + intervalId = setInterval(cb, 200); + + function stopRepeat() { + if (intervalId) { + clearInterval(intervalId); + intervalId = null; + } + window.document.removeEventListener('mouseup', stopRepeat); + } + + }, + + canChangeValue: function () { + var model = this.model, + enabled = model.get('enabled'); + + return enabled === true; + } + +}); - return result; - }, +//####app/controls/panel/panelControl.js +/** + * + * @param parent + * @constructor + * @augments ContainerControl + */ +function PanelControl(parent) { + _.superClass(PanelControl, this, parent); +} - setFileProvider: function (fileProvider) { - this.set('fileProvider', fileProvider); - }, +_.inherit(PanelControl, ContainerControl); - getFileProvider: function () { - return this.get('fileProvider'); +_.extend(PanelControl.prototype, /** @lends PanelControl.prototype */ { + createControlModel: function () { + return new PanelModel(); }, - _addIndexToPropertiesOfValidationMessage: function (validationMessages, index) { - for (var i = 0, ii = validationMessages.length; i < ii; i++) { - validationMessages[i].property = index + '.' + validationMessages[i].property; - } - }, + createControlView: function (model) { + return new PanelView({model: model}); + } - _notifyAboutValidation: function (validationResult, validationType) { - if(!validationResult) { - return; - } +}); - var context = this.getContext(), - argument = { - value: validationResult - }; - this.trigger('onErrorValidator', context, argument); +//####app/controls/panel/panelModel.js +/** + * @constructor + * @augments ContainerModel + */ +var PanelModel = ContainerModel.extend(/** @lends PanelModel.prototype */ { + initialize: function () { + ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + this.on('change:collapsed', function (model, value) { + model.trigger(value ? 'collapsed' : 'expanded', null, {}); + }); }, - getContext: function () { - return this.getView().getContext(); - }, + defaults: _.defaults({ + collapsible: false, + collapsed: false, + collapsibleArea: '' + }, ContainerModel.prototype.defaults), - _indexItemsById: function (items) { - var idProperty = this.get('idProperty'), - result = {}, - idValue; - for (var i = 0, ii = items.length; i < ii; i++) { - idValue = items[i][idProperty]; - result[idValue] = items[i]; + set: function (key, val, options) { + if (key == null) return this; + + var attrs; + if (typeof key === 'object') { + attrs = key; + options = val; + } else { + (attrs = {})[key] = val; } - return result; - }, + var oldValue, newValue; + if ('collapsed' in attrs) { + //Вызов обработчиков перед collapsing/expanding + oldValue = this.get('collapsed'); + newValue = attrs.collapsed; + var allow; - _indexOfItem: function(item){ - var items = this.getItems(); - if(!items){ - return -1; + if (newValue && !oldValue) { + allow = this + .set('_collapsing', true, {validate: false}) + .trigger('collapsing', null, {}) + .get('_collapsing'); + } else if (!newValue && oldValue) { + allow = this + .set('_expanding', true, {validate: false}) + .trigger('expanding', null, {}) + .get('_expanding'); + } + if (allow === false) { + //Если collapsing/expanding отменен в обработчиках collapsing/expanding - не меняем collapsed + delete attrs.collapsed; + } } - return items.indexOf(item); + return ContainerModel.prototype.set.call(this, attrs, options); }, - _indexOfSelectedItem: function(){ - var selectedItem = this.getSelectedItem(); + //@TODO Add support an event map syntax + on: function (name, callback, context) { + var handler; + var model = this; + switch (name) { + case 'collapsing': + handler = function () { + var allow = callback(null, {}); + if (allow === false) { + model.set('_collapsing', false); + } + }; + break; + case 'expanding': + handler = function () { + var allow = callback(null, {}); + if (allow === false) { + model.set('_expanding', false); + } + }; + break; + default: + handler = callback; + break; + } + ContainerModel.prototype.on.call(this, name, handler, context); + } + +}); + +//####app/controls/panel/panelView.js +/** + * @class + * @augments ControlView + */ +var PanelView = ContainerView.extend(/** @lends PanelView.prototype */ { + + className: 'pl-panel panel panel-default', - return this._indexOfItem(selectedItem); + template: InfinniUI.Template["controls/panel/template/panel.tpl.html"], + + UI: { + header: '.pl-panel-header', + items: '.panel-items' }, - idOfItem: function (item) { - var idProperty = this.get('idProperty'); - if (!item) { - return undefined; - } - return item[idProperty]; + events: { + 'click >.pl-panel-header': 'onClickHeaderHandler' }, - getCurrentRequestPromise: function(){ - var promise = $.Deferred(); - var logger = window.InfinniUI.global.logger; + initialize: function (options) { + ContainerView.prototype.initialize.call(this, options); + }, - if(this.get('isRequestInProcess')){ - this.onItemsUpdatedOnce(function(){ - if(this.isDataReady()){ - promise.resolve(); - }else{ - logger.warn({ - message: 'BaseDataSource: strange, expected other dataReady status', - source: this - }); - } - }); - }else{ - promise.resolve(); - } + render: function () { + this.prerenderingActions(); - return promise; - }, + this.removeChildElements(); - getNearestRequestPromise: function(){ - var promise = $.Deferred(); + this.$el.html(this.template({ + items: this.model.get('items') + })); - this.onItemsUpdatedOnce( function(){ - if(this.isDataReady()){ - promise.resolve(); - }else{ - logger.warn({ - message: 'BaseDataSource: strange, expected other dataReady status', - source: this - }); - } - }); + this.bindUIElements(); - return promise; - }, + this.renderItemsContents(); - //setBindingBuilder: function(bindingBuilder){ - // this.set('bindingBuilder', bindingBuilder); - //}, + this.trigger('render'); + this.updateProperties(); - setIsLazy: function(isLazy){ - this.set('isLazy', isLazy); + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; }, - isLazy: function(){ - return this.get('isLazy'); + initHandlersForProperties: function () { + ContainerView.prototype.initHandlersForProperties.call(this); + this.listenTo(this.model, 'change:collapsed', this.updateCollapsed); + this.listenTo(this.model, 'change:collapsible', this.updateCollapsible); + this.listenTo(this.model, 'change:header', this.updateHeader); }, - setResolvePriority: function(priority){ - this.set('resolvePriority', priority); + updateProperties: function () { + ContainerView.prototype.updateProperties.call(this); + this.updateCollapsed(); + this.updateCollapsible(); + this.updateHeader(); }, - getResolvePriority: function(){ - return this.get('resolvePriority'); + updateCollapsed: function () { + this.ui.header.toggleClass('pl-collapsed', this.model.get('collapsed')); }, - _copyObject: function (currentObject) { - return JSON.parse(JSON.stringify(currentObject)); + updateCollapsible: function (model, value) { + this.ui.header.toggleClass('pl-collapsible', this.model.get('collapsible')); }, - _getArgumentTemplate: function () { - return { - source: this - }; - }, + updateHeader: function () { + var model = this.model; - _detectIdentifyingMode: function(items){ - if( $.isArray(items) && items.length > 0){ - if( !$.isPlainObject(items[0]) || this.getIdProperty() in items[0] ){ - this.set('identifyingMode', 'byId'); - _.extend( this, BaseDataSource.identifyingStrategy.byId); - }else{ - this.set('identifyingMode', 'byLink'); - _.extend( this, BaseDataSource.identifyingStrategy.byLink); - } - }else{ - this.set('identifyingMode', 'byId'); - _.extend( this, BaseDataSource.identifyingStrategy.byId); + this.ui.header.empty(); + var headerTemplate = model.get('headerTemplate'); + if (typeof headerTemplate === 'function') { + var header = model.get('header'); + this.ui.header.append(headerTemplate(null, {value: header}).render()); } }, - _getIdentifyingMode: function(){ - return this.get('identifyingMode'); - } - -}); - - -BaseDataSource.identifyingStrategy = { - - byId: { - _restoreSelectedItem: function(){ - - var selectedItem = this.getSelectedItem(), - selectedItemId = this.idOfItem(selectedItem); - if( selectedItemId != null ){ - var items = this.get('itemsById'); - var newSelectedItem = items[selectedItemId]; - if( newSelectedItem != null ){ - this.setSelectedItem(newSelectedItem); - return true; - } - } + renderItemsContents: function () { + var $items = this.$el.find('.pl-panel-i'), + items = this.model.get('items'), + itemTemplate = this.model.get('itemTemplate'), + that = this, + element, item; - return false; - }, + $items.each(function (i, el) { + item = items.getByIndex(i); + element = itemTemplate(undefined, {item: item, index: i}); + that.addChildElement(element); + $(el) + .append(element.render()); + }); + }, + // + //initOrientation: function () { + // this.listenTo(this.model, 'change:orientation', this.updateOrientation); + // this.updateOrientation(); + //}, - setSelectedItem: function (item, success, error) { - var currentSelectedItem = this.getSelectedItem(), - items = this.get('itemsById'), - itemId = this.idOfItem(item), - index; + //updateOrientation: function () { + // var orientation = this.model.get('orientation'); + // this.$el.toggleClass('horizontal-orientation', orientation == 'Horizontal'); + //}, + updateGrouping: function () { - if (typeof item == 'undefined') { - item = null; - } + }, - if (item == currentSelectedItem) { - return; - } + onEventCallback: function () { + var collapsible = this.model.get('collapsible'); + if (collapsible) { + var collapsed = this.model.get('collapsed'); + this.model.set('collapsed', !collapsed); + this.updateLayout(); + } + }, - if (item !== null) { - if (!items[itemId]) { - if (!error) { - throw 'BaseDataSource.setSelectedItem() Попытка выбрать элемент в источнике, которого нет среди элементов этого источника.'; - } else { - error(this.getContext(), {error: 'BaseDataSource.setSelectedItem() Попытка выбрать элемент в источнике, которого нет среди элементов этого источника.'}); - return; - } - } + onClickHeaderHandler: function (event) { + var collapsibleArea = this.model.get('collapsibleArea'); + if( collapsibleArea !== '' ) { + if( $(event.target).closest('[data-pl-name=' + collapsibleArea + ']').length ) { + this.onEventCallback(); } + } else { + this.onEventCallback(); + } + } - this.get('model').setProperty('selectedItem', item); +}); - index = this._indexOfItem(items[itemId]); - this._tuneMirroringOfModel(index); +//####app/controls/passwordBox/passwordBoxControl.js +/** + * + * @constructor + * @augments Control + * @mixes editorBaseControlMixin + */ +var PasswordBoxControl = function () { + _.superClass(PasswordBoxControl, this); + this.initialize_editorBaseControl(); +}; + +_.inherit(PasswordBoxControl, Control); + +_.extend(PasswordBoxControl.prototype, /** @lends PasswordBoxControl.prototype */ { + + createControlModel: function () { + return new PasswordBoxModel(); + }, + + createControlView: function (model) { + return new PasswordBoxView({model: model}); + } + +}, editorBaseControlMixin); +//####app/controls/passwordBox/passwordBoxModel.js +/** + * @constructor + * @augments ControlModel + * @mixes editorBaseModelMixin + */ +var PasswordBoxModel = ControlModel.extend(_.extend({ + + defaults: _.defaults( + { + autocomplete: true + }, + editorBaseModelMixin.defaults_editorBaseModel, + ControlModel.prototype.defaults + ), + + initialize: function () { + ControlModel.prototype.initialize.apply(this, arguments); + this.initialize_editorBaseModel(); + } + +}, editorBaseModelMixin)); +//####app/controls/passwordBox/passwordBoxView.js +/** + * @class PasswordBoxView + * @augments ControlView + * @mixes editorBaseViewMixin + */ +var PasswordBoxView = ControlView.extend(_.extend({}, editorBaseViewMixin, { + + className: 'pl-password-box form-group', + + template: { + "autocomplete": InfinniUI.Template["controls/passwordBox/template/passwordBox.on.tpl.html"], + "noautocomplete": InfinniUI.Template["controls/passwordBox/template/passwordBox.off.tpl.html"] + }, + + UI: _.extend({}, editorBaseViewMixin.UI, { + label: '.pl-control-label', + input: '.pl-control' + }), + + events: { + 'blur .pl-control': 'onBlurHandler', + 'input .pl-control': 'onInputHandler', + 'change .pl-control': 'onChangeHandler' + }, + + initialize: function () { + ControlView.prototype.initialize.apply(this); + }, + + initHandlersForProperties: function(){ + ControlView.prototype.initHandlersForProperties.call(this); + editorBaseViewMixin.initHandlersForProperties.call(this); + + this.listenTo(this.model, 'change:labelText', this.updateLabelText); + this.listenTo(this.model, 'change:labelFloating', this.updateLabelFloating); + this.listenTo(this.model, 'change:autocomplete', this.updateAutocomplete); + + }, + + updateProperties: function(){ + ControlView.prototype.updateProperties.call(this); + editorBaseViewMixin.updateProperties.call(this); + this.updateLabelText(); + }, + + updateLabelText: function () { + var labelText = this.model.get('labelText'); + this.ui.label.text(labelText); + }, + + updateAutocomplete: function () { + this.rerender(); + }, + + updateValue: function(){ + editorBaseViewMixin.updateValueState.call(this); + + var value = this.model.get('value'); + this.ui.input.val(value); + }, + + updateEnabled: function () { + ControlView.prototype.updateEnabled.call(this); + + var enabled = this.model.get('enabled'); + this.ui.input.prop('disabled', !enabled); + }, + + getData: function () { + return _.extend( + {}, + ControlView.prototype.getData.call(this), + editorBaseViewMixin.getData.call(this) + ); + }, + + render: function () { + var model = this.model; + + this.prerenderingActions(); + this.renderTemplate(this.getTemplate()); + + this.updateProperties(); + + this.trigger('render'); + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, + + remove: function () { + ControlView.prototype.remove.call(this); + }, + + getTemplate: function () { + var model = this.model; + + return model.get('autocomplete') ? this.template.autocomplete : this.template.noautocomplete; + }, + + updateModelValue: function () { + var value = this.ui.input.val(); + var model = this.model; + model.set('value', value); + model.set('rawValue', value); + }, + + onBlurHandler: function () { + this.updateModelValue(); + }, + + onChangeHandler: function () { + this.updateModelValue(); + }, + + onInputHandler: function () { + this.updateModelValue(); + } + +})); - this._notifyAboutSelectedItem(item, success); - }, +//####app/controls/scrollPanel/scrollPanelControl.js +/** + * + * @param parent + * @constructor + * @augments ContainerControl + */ +function ScrollPanelControl(parent) { + _.superClass(ScrollPanelControl, this, parent); +} - _includeItemToModifiedSet: function (item) { - var itemId = this.idOfItem(item); - this.get('modifiedItems')[itemId] = item; - }, +_.inherit(ScrollPanelControl, ContainerControl); - _excludeItemFromModifiedSet: function (item) { - var itemId = this.idOfItem(item); - delete this.get('modifiedItems')[itemId]; - }, +_.extend(ScrollPanelControl.prototype, /** @lends ScrollPanelControl.prototype */ { - _handleDeletedItem: function (item, successHandler) { - var items = this.getItems(), - idProperty = this.get('idProperty'), - itemId = this.idOfItem(item), - selectedItem = this.getSelectedItem(); + createControlModel: function () { + return new ScrollPanelModel(); + }, - for (var i = 0, ii = items.length, needExit = false; i < ii && !needExit; i++) { - if (items[i][idProperty] == itemId) { - items.splice(i, 1); - needExit = true; - } - } - delete this.get('itemsById')[itemId]; - this._excludeItemFromModifiedSet(item); + createControlView: function (model) { + return new ScrollPanelView({model: model}); + } - if (selectedItem && selectedItem[idProperty] == itemId) { - this.setSelectedItem(null); - } +}); - this._notifyAboutItemDeleted(item, successHandler); - } - }, - byLink: { - _restoreSelectedItem: function(){ +//####app/controls/scrollPanel/scrollPanelModel.js +/** + * @constructor + * @augments ContainerModel + */ +var ScrollPanelModel = ContainerModel.extend(/** @lends ScrollPanelModel.prototype */ { - var selectedItem = this.getSelectedItem(); - var items = this.getItems(); + initialize: function () { + ContainerModel.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + }, - if( items.indexOf(selectedItem) == -1 ){ - return false; - }else{ - return true; - } + defaults: _.defaults( + { + verticalAlignment: 'Stretch', + horizontalScroll: InfinniUI.ScrollVisibility.auto, + verticalScroll: InfinniUI.ScrollVisibility.auto }, + ContainerModel.prototype.defaults + ) - setSelectedItem: function (item, success, error) { - var currentSelectedItem = this.getSelectedItem(), - items = this.getItems(), - index = this._indexOfItem(item); +}); +//####app/controls/scrollPanel/scrollPanelView.js +/** + * @class + * @augments ControlView + */ +var ScrollPanelView = ContainerView.extend(/** @lends ScrollPanelView.prototype */ { + className: 'pl-scrollpanel panel panel-default', - if (typeof item == 'undefined') { - item = null; - } + template: InfinniUI.Template["controls/scrollPanel/template/scrollPanel.tpl.html"], - if (item == currentSelectedItem) { - return; - } + UI: { - if (item !== null) { - if (index == -1) { - if (!error) { - throw 'BaseDataSource.setSelectedItem() Попытка выбрать элемент в источнике, которого нет среди элементов этого источника.'; - } else { - error(this.getContext(), {error: 'BaseDataSource.setSelectedItem() Попытка выбрать элемент в источнике, которого нет среди элементов этого источника.'}); - return; - } - } - } + }, - this.get('model').setProperty('selectedItem', item); + initialize: function (options) { + ContainerView.prototype.initialize.call(this, options); + }, - this._tuneMirroringOfModel(index); + render: function () { + this.prerenderingActions(); - this._notifyAboutSelectedItem(item, success); - }, + this.removeChildElements(); + this.$el.html(this.template({ + items: this.model.get('items') + })); + this.renderItemsContents(); - _includeItemToModifiedSet: function (item) { - this.get('modifiedItems')['-'] = item; - }, + this.bindUIElements(); - _excludeItemFromModifiedSet: function (item) { - delete this.get('modifiedItems')['-']; - }, + this.postrenderingActions(); - _handleDeletedItem: function (item, successHandler) { - var items = this.getItems(), - selectedItem = this.getSelectedItem(), - index = items.indexOf(item); + this.trigger('render'); + this.updateProperties(); - if(index >= 0){ - items.splice(index, 1); - this._excludeItemFromModifiedSet(item); + (function ($el) { + //Firefox сохраняет позицию прокрутки. Принудительно крутим в начало. + setTimeout(function () { + $el.scrollTop(0); + }, 0); + })(this.$el); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, - if (selectedItem && selectedItem == item) { - this.setSelectedItem(null); - } - } + initHandlersForProperties: function () { + ContainerView.prototype.initHandlersForProperties.call(this); + this.listenTo(this.model, 'change:horizontalScroll', this.updateHorizontalScroll); + this.listenTo(this.model, 'change:verticalScroll', this.updateVerticalScroll); + }, - this._notifyAboutItemDeleted(item, successHandler); + updateProperties: function () { + ContainerView.prototype.updateProperties.call(this); + this.updateHorizontalScroll(); + this.updateVerticalScroll(); + }, + + /** + * @protected + * @description Set one of CSS class: "pl-horizontal-scroll-(visible|hidden|auto)", + */ + updateHorizontalScroll: function () { + var name = ''; + switch (this.model.get('horizontalScroll')) { + case InfinniUI.ScrollVisibility.visible: + name = 'visible'; + break; + case InfinniUI.ScrollVisibility.hidden: + name = 'hidden'; + break; + case InfinniUI.ScrollVisibility.auto: + default: + name = 'auto'; + break; } - } -}; + this.switchClass('pl-horizontal-scroll', name, this.$el); + }, -window.InfinniUI.BaseDataSource = BaseDataSource; + /** + * @protected + * @description Set one of CSS class: "pl-vertical-scroll-(visible|hidden|auto)", + */ + updateVerticalScroll: function (model, value) { + var name = ''; + switch (this.model.get('verticalScroll')) { + case InfinniUI.ScrollVisibility.visible: + name = 'visible'; + break; + case InfinniUI.ScrollVisibility.hidden: + name = 'hidden'; + break; + case InfinniUI.ScrollVisibility.auto: + default: + name = 'auto'; + break; + } + this.switchClass('pl-vertical-scroll', name, this.$el); + }, -//####app/data/dataSource/restDataSource.js -var RestDataSource = BaseDataSource.extend({ + renderItemsContents: function () { + var $items = this.$el.find('.pl-scrollpanel-i'), + items = this.model.get('items'), + itemTemplate = this.model.get('itemTemplate'), + that = this, + element, item; - defaults: _.defaults({ - updatingItemsConverter: null + $items.each(function (i, el) { + item = items.getByIndex(i); + element = itemTemplate(undefined, {item: item, index: i}); + that.addChildElement(element); + $(el) + .append(element.render()); + }); + }, - }, BaseDataSource.prototype.defaults), + updateGrouping: function () { - initialize: function(){ - BaseDataSource.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); + } - var model = this.get('model'); - model.urlParams = { - get: { - method: 'get', - origin: null, - path: '', - data: {}, - params: {} - }, +}); - set: { - method: 'post', - origin: null, - path: '', - data: {}, - params: {} - }, +//####app/controls/toggleButton/toggleButtonControl.js +function ToggleButtonControl(parent) { + _.superClass(ToggleButtonControl, this, parent); + this.initialize_editorBaseControl(); +} + +_.inherit(ToggleButtonControl, Control); + +_.extend(ToggleButtonControl.prototype, { + + createControlModel: function () { + return new ToggleButtonModel(); + }, + + createControlView: function (model) { + return new ToggleButtonView({model: model}); + } +}, editorBaseControlMixin); + - delete: { - method: 'delete', - origin: null, - path: '', - data: {}, - params: {} - } - }; +//####app/controls/toggleButton/toggleButtonModel.js +var ToggleButtonModel = ControlModel.extend( _.extend({ + + defaults: _.defaults({ + value: false, + textOn: 'ON', + textOff: 'OFF', + horizontalAlignment: 'Left' + }, ControlModel.prototype.defaults), + + initialize: function () { + ControlModel.prototype.initialize.apply(this, arguments); + this.initialize_editorBaseModel(); + } + +}, editorBaseModelMixin)); +//####app/controls/toggleButton/toggleButtonView.js +/** + * @class ToggleButtonView + * @augments ControlView + * @mixes editorBaseViewMixin + */ +var ToggleButtonView = ControlView.extend(/** @lends ToggleButtonView.prototype */ _.extend({}, editorBaseViewMixin, { + + template: InfinniUI.Template["controls/toggleButton/template/toggleButton.tpl.html"], + + UI: _.extend({}, editorBaseViewMixin.UI, { + textOn: '.togglebutton-handle-on', + textOff: '.togglebutton-handle-off', + container: '.togglebutton-container' + }), + + events: { + 'click .togglebutton-box': 'onClickHandler' + }, + + initHandlersForProperties: function(){ + ControlView.prototype.initHandlersForProperties.call(this); + editorBaseViewMixin.initHandlersForProperties.call(this); + + this.listenTo(this.model, 'change:textOn', this.updateTextOn); + this.listenTo(this.model, 'change:textOff', this.updateTextOff); + }, + + updateProperties: function(){ + ControlView.prototype.updateProperties.call(this); + editorBaseViewMixin.updateProperties.call(this); + + this.updateTextOn(); + this.updateTextOff(); + }, + + updateFocusable: function () { + var focusable = this.model.get('focusable'); + + if (focusable) { + this.ui.container.attr('tabindex', 0); + } else { + this.ui.container.removeAttr('tabindex'); + } + }, + + updateTextOn: function () { + var textOn = this.model.get('textOn'); + this.ui.textOn.html(textOn || ' '); + }, + + updateTextOff: function () { + var textOff = this.model.get('textOff'); + this.ui.textOff.html(textOff || ' '); + }, + + render: function () { + this.prerenderingActions(); + this.renderTemplate(this.template); + this.updateProperties(); + + this.trigger('render'); + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, + + getData: function () { + var model = this.model; + + return _.extend({}, + ControlView.prototype.getData.call(this), + editorBaseViewMixin.getData.call(this), + { + textOn: model.get('textOn'), + textOff: model.get('textOff') + } + ); + }, + + + onClickHandler: function (event) { + var model = this.model; + model.set('value', !model.get('value')); + }, + + updateValue: function () { + var value = this.model.get('value'); + this.switchClass('toggle', value ? 'on' : 'off', this.$el); + } +})); - this.initUrlParamsHandlers(); - }, +//####app/controls/toolBar/toolBarControl.js +/** + * + * @param parent + * @constructor + * @augments ContainerControl + */ +function ToolBarControl(parent) { + _.superClass(ToolBarControl, this, parent); +} + +_.inherit(ToolBarControl, ContainerControl); + +_.extend(ToolBarControl.prototype, /** @lends ToolBarControl.prototype */ { + + createControlModel: function () { + return new ToolBarModel(); + }, + + createControlView: function (model) { + return new ToolBarView({model: model}); + } +}); + - initDataProvider: function(){ - var dataProvider = window.InfinniUI.providerRegister.build('RestDataSource'); - this.set('dataProvider', dataProvider); - }, +//####app/controls/toolBar/toolBarModel.js +/** + * @constructor + * @aurments ContainerModel + */ +var ToolBarModel = ContainerModel.extend({ + +}); - initUrlParamsHandlers: function(){ - var that = this; +//####app/controls/toolBar/toolBarView.js +/** + * @constructor + * @augments ContainerView + */ +var ToolBarView = ContainerView.extend({ + + className: 'pl-tool-bar', + + template: InfinniUI.Template["controls/toolBar/template/toolBar.tpl.html"], + + itemTemplate: InfinniUI.Template["controls/toolBar/template/toolBarItem.tpl.html"], + + UI: { + container: '.pl-tool-bar__container' + }, + + render: function () { + this.prerenderingActions(); + + this.renderTemplate(this.template); + this.ui.container.append(this.renderItems()); + this.updateProperties(); + this.trigger('render'); + + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, + + renderItems: function () { + var model = this.model; + var items = model.get('items'); + var itemTemplate = model.get('itemTemplate'); + + this.removeChildElements(); + + var $elements = []; + + items.forEach(function (item, index) { + var template = this.itemTemplate(); + var $template = $(template); + + var element = itemTemplate(null, { + index: index, + item: item + }); + this.addChildElement(element); + $template.append(element.render()); + $elements.push($template); + }, this); + + return $elements; + }, + + updateGrouping: function(){} +}); + +//####app/controls/tooltip/tooltipControl.js +var TooltipControl = function () { + _.superClass(TooltipControl, this); +}; + +_.inherit(TooltipControl, Control); + +_.extend(TooltipControl.prototype, { + + createControlModel: function( ) { + return new InfinniUI.TooltipModel(); + }, + + createControlView: function( model ) { + return new InfinniUI.TooltipView({model: model}); + } - this.get('model').onPropertyChanged('urlParams.get.*', function(context, args){ - var dataProvider = that.get('dataProvider'); - var urlParams = that.getGettingUrlParams(); - var templated; +}); - dataProvider.setOrigin('get', urlParams.origin); - templated = that._templateParamsInStr(urlParams.path, urlParams.params); - dataProvider.setPath('get', templated); - templated = that._templateParamsInObject(urlParams.data, urlParams.params); - dataProvider.setData('get', templated); +InfinniUI.TooltipControl = TooltipControl; +//####app/controls/tooltip/tooltipModel.js +/** + * @class + * @augments ControlModel + */ +InfinniUI.TooltipModel = ControlModel.extend( { - if( that.get('isDataReady') || that.get('isRequestInProcess') || that.get('waitingOnUpdateItemsHandlers').length > 0 ){ // ds was resolved or waiting resolving - that.updateItems(); - } - }); +} ); - this.get('model').onPropertyChanged('urlParams.set.*', function(context, args){ - var dataProvider = that.get('dataProvider'); - var urlParams = that.getSettingUrlParams(); - var templated; +//####app/controls/tooltip/tooltipView.js +InfinniUI.TooltipView = ControlView.extend({ + + render: function(){ + this.prerenderingActions(); + this.renderContent(); + this.trigger('render'); + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, - dataProvider.setOrigin('set', urlParams.origin); - templated = that._templateParamsInStr(urlParams.path, urlParams.params); - dataProvider.setPath('set', templated); - templated = that._templateParamsInObject(urlParams.data, urlParams.params); - dataProvider.setData('set', templated); - }); + initHandlersForProperties: function( ) { + ControlView.prototype.initHandlersForProperties.apply(this, Array.prototype.slice.call(arguments)); - this.get('model').onPropertyChanged('urlParams.delete.*', function(context, args){ - var dataProvider = that.get('dataProvider'); - var urlParams = that.getDeletingUrlParams(); - var templated; + this.listenTo(this.model, 'change:content', this.updateContent); + }, - dataProvider.setOrigin('delete', urlParams.origin); - templated = that._templateParamsInStr(urlParams.path, urlParams.params); - dataProvider.setPath('delete', templated); - templated = that._templateParamsInObject(urlParams.data, urlParams.params); - dataProvider.setData('delete', templated); - }); + updateContent: function( ) { + this.renderContent(); }, - updateItems: function(){ + /** + * @protected + */ + renderContent: function() { + var model = this.model; + var content = model.get('content'); + this.$el.html(content.render()); + } - if(this._checkGettingUrlParamsReady()){ - BaseDataSource.prototype.updateItems.apply(this, Array.prototype.slice.call(arguments)); - this.resumeUpdate('urlGettingParamsNotReady'); +}); - }else{ - this.suspendUpdate('urlGettingParamsNotReady'); - BaseDataSource.prototype.updateItems.apply(this, Array.prototype.slice.call(arguments)); - } +//####app/controls/view/viewControl.js +/** + * + * @param parent + * @constructor + * @augments ContainerControl + */ +function ViewControl(parent) { + _.superClass(ViewControl, this, parent); +} - }, +_.inherit(ViewControl, ContainerControl); - getGettingUrlParams: function(propertyName){ - if(arguments.length == 0){ - propertyName = 'urlParams.get'; +_.extend(ViewControl.prototype, + /** @lends ViewControl.prototype */ + { + createControlModel: function () { + return new ViewModel(); + }, - }else{ - if(propertyName == ''){ - propertyName = 'urlParams.get'; - }else{ - propertyName = 'urlParams.get.' + propertyName; - } + createControlView: function (model) { + return new ViewView({model: model}); } - return this.get('model').getProperty(propertyName); - }, + } +); - setGettingUrlParams: function(propertyName, value){ - if(arguments.length == 1){ - value = propertyName; - propertyName = 'urlParams.get'; - }else{ - if(propertyName == ''){ - propertyName = 'urlParams.get'; - }else{ - propertyName = 'urlParams.get.' + propertyName; - } - } +//####app/controls/view/viewModel.js +var DialogResult = { + none: 0, + accepted: 1, + canceled: 2 +}; - this.get('model').setProperty(propertyName, value); - }, +window.InfinniUI.DialogResult = DialogResult; - getSettingUrlParams: function(propertyName){ - if(arguments.length == 0){ - propertyName = 'urlParams.set'; +var ViewModel = ContainerModel.extend({ - }else{ - if(propertyName == ''){ - propertyName = 'urlParams.set'; - }else{ - propertyName = 'urlParams.set.' + propertyName; - } - } - return this.get('model').getProperty(propertyName); - }, + defaults: _.defaults({ + dialogResult: DialogResult.none, + isApplication: false, + closeButtonVisibility: true + }, ContainerModel.prototype.defaults), - setSettingUrlParams: function(propertyName, value){ - if(arguments.length == 1){ - value = propertyName; - propertyName = 'urlParams.set'; + initialize: function () { + ContainerModel.prototype.initialize.apply(this); - }else{ - if(propertyName == ''){ - propertyName = 'urlParams.set'; - }else{ - propertyName = 'urlParams.set.' + propertyName; - } - } + this.set('scripts', new Collection([], 'name')); + this.set('parameters', new Collection([], 'name')); + this.set('dataSources', new Collection([], 'name')); + } +}); - this.get('model').setProperty(propertyName, value); - }, +//####app/controls/view/viewView.js +/** + * @class + * @augments ContainerView + */ +var ViewView = ContainerView.extend( + /** @lends ViewView.prototype */ + { + className: 'pl-view', - getDeletingUrlParams: function(propertyName){ - if(arguments.length == 0){ - propertyName = 'urlParams.delete'; + initialize: function (options) { + ContainerView.prototype.initialize.call(this, options); + }, - }else{ - if(propertyName == ''){ - propertyName = 'urlParams.delete'; - }else{ - propertyName = 'urlParams.delete.' + propertyName; - } - } - return this.get('model').getProperty(propertyName); - }, + render: function () { + this.prerenderingActions(); - setDeletingUrlParams: function(propertyName, value){ - if(arguments.length == 1){ - value = propertyName; - propertyName = 'urlParams.delete'; + this.$el.empty(); - }else{ - if(propertyName == ''){ - propertyName = 'urlParams.delete'; - }else{ - propertyName = 'urlParams.delete.' + propertyName; - } - } + this.renderItemsContents(); - this.get('model').setProperty(propertyName, value); - }, + this.updateProperties(); + this.trigger('render'); - _checkGettingUrlParamsReady: function(){ - var allParams = []; - var strWithParams; - var params; - var data; - var definedParams; - var param; + this.postrenderingActions(); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + }, - if(!this._checkUrlParamsReady(this.getGettingUrlParams())){ - return false; - } + renderItemsContents: function(){ + var that = this, + items = this.model.get('items'), + itemTemplate = this.model.get('itemTemplate'), + element; - strWithParams = this.getGettingUrlParams('path'); - params = this._findSubstitutionParams(strWithParams); - allParams = allParams.concat(params); + items.forEach(function(item, i){ + element = itemTemplate(undefined, {item: item, index: i}); + if (element) { + that.$el + .append(element.render()); + } + }); + }, - data = this.getGettingUrlParams('data'); - strWithParams = JSON.stringify(data); - params = this._findSubstitutionParams(strWithParams); - allParams = allParams.concat(params); + updateGrouping: function(){} + } +); - definedParams = this.getGettingUrlParams('params'); - for(var i = 0, ii = allParams.length; i 0 - && typeof params.path == 'string' - && typeof params.data == 'object' - && typeof params.params == 'object'; - }, +ViewPanelControl.prototype.createControlModel = function () { + return new ViewPanelModel(); +}; - _findSubstitutionParams: function(str){ - if(!str){ - return []; - } +ViewPanelControl.prototype.createControlView = function (model) { + return new ViewPanelView({model: model}); +}; - var result = []; - str.replace(/<%([\s\S]+?)%>/g, function(p1, p2){ - result.push(p2); - return p1; - }); +var ViewPanelModel = ControlModel.extend({ + defaults: _.defaults({ + layout: null + }, ControlModel.prototype.defaults), - return result; + initialize: function(){ + var that = this; + + ControlModel.prototype.initialize.apply(this); + + this.once('change:layout', function (model, layout) { + if(layout && layout.onLoaded){ + that.subscribeOnLoaded(); + } + }); }, - _templateParamsInStr: function(str, params){ - if(!str || !params){ - return str; - } + subscribeOnLoaded: function(){ + var that = this; + var layout = this.get('layout'); - return str.replace(/<%([\s\S]+?)%>/g, function(p1, p2){ - return params[p2]; + layout.onLoaded(function(){ + that.set('isLoaded', true); }); - }, + } +}); - _templateParamsInObject: function(obj, params){ - if(!obj || !params){ - return obj; - } +var ViewPanelView = ControlView.extend({ + className: 'pl-view-panel', - var str = JSON.stringify(obj); - var tmpTemplated = this._templateParamsInStr(str, params); - return JSON.parse(tmpTemplated); + initialize: function () { + ControlView.prototype.initialize.apply(this); + this.listenTo(this.model, 'change:layout', this.onChangeLayoutHandler); }, - getUpdatingItemsConverter: function(){ - return this.get('updatingItemsConverter'); + onChangeLayoutHandler: function (model, layout) { + this.$el.empty(); + if(layout){ + this.$el.append(layout.render()); + } }, - setUpdatingItemsConverter: function(converter){ - this.set('updatingItemsConverter', converter); - }, + render: function () { + this.prerenderingActions(); - _handleUpdatedItemsData: function (itemsData, successHandler, errorHandler) { - var converter = this.getUpdatingItemsConverter(); - var items; + var layout = this.model.get('layout'); - if(converter){ - items = converter(itemsData); - }else{ - items = itemsData; + if(layout){ + this.$el.append(layout.render()); } - BaseDataSource.prototype._handleUpdatedItemsData.call(this, items, successHandler, errorHandler); - } + this.updateProperties(); + this.trigger('render'); + this.postrenderingActions(false); + //devblockstart + window.InfinniUI.global.messageBus.send('render', {element: this}); + //devblockstop + return this; + } }); -window.InfinniUI.RestDataSource = RestDataSource; - -//####app/data/dataSource/documentDataSource.js -var DocumentDataSource = RestDataSource.extend({ - defaults: _.defaults({ - documentId: null - - }, RestDataSource.prototype.defaults), - - initialize: function () { - RestDataSource.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - - var model = this.get('model'); - model.setProperty('pageNumber', 0); - model.setProperty('pageSize', 15); - model.setProperty('filterParams', {}); - this.setUpdatingItemsConverter(function(data){ - model.setProperty('totalCount', data['Result']['Count']); - return data['Result']['Items']; - }); +//####app/data/dataSource/_mixins/dataSourceValidationNotifierMixin.js +/** + * + * @mixin + */ +var DataSourceValidationNotifierMixin = { + /** + * @param dataSource + */ + initNotifyValidation: function (dataSource) { + dataSource.onErrorValidator(this.notifyOnValidationError.bind(this)); + }, + + /** + * @param context + * @param args + */ + notifyOnValidationError: function (context, args) { + var result = args.value; + + if (typeof result === 'undefined' || result === null || result['IsValid'] || !Array.isArray(result['Items'])) { + return; + } + + result['Items'].forEach(function (item) { + var exchange = window.InfinniUI.global.messageBus; + exchange.send(messageTypes.onNotifyUser, {item: item, messageText: item.Message, messageType: 'error'}); + }); + } +}; +//####app/data/dataSource/baseDataSource.js +/** + * @constructor + * @augments Backbone.Model + * @mixes dataSourceFindItemMixin + */ +var BaseDataSource = Backbone.Model.extend({ + defaults: { + name: null, + idProperty: '_id', + identifyingMode: 'byId', // byId, byLink. detect automatically - this.initHandlers(); - }, + view: null, - initHandlers: function(){ - var model = this.get('model'); - var that = this; - var updateGettingUrlParams = _.bind(this.updateGettingUrlParams, this); + isDataReady: false, - model.onPropertyChanged('documentId', function(){ - that.updateGettingUrlParams(); - that.updateSettingUrlParams(); - that.updateDeletingUrlParams(); - }); - model.onPropertyChanged('filter', updateGettingUrlParams); - model.onPropertyChanged('filterParams.*', updateGettingUrlParams); - model.onPropertyChanged('pageNumber', updateGettingUrlParams); - model.onPropertyChanged('pageSize', updateGettingUrlParams); - model.onPropertyChanged('search', updateGettingUrlParams); - model.onPropertyChanged('select', updateGettingUrlParams); - model.onPropertyChanged('order', updateGettingUrlParams); - model.onPropertyChanged('needTotalCount', updateGettingUrlParams); + dataProvider: null, - this.updateGettingUrlParams(); - this.updateSettingUrlParams(); - this.updateDeletingUrlParams(); - }, + /* + * TreeModel for handling + * model.items + * model.selectedItem + * */ + model: null, - updateGettingUrlParams: function(){ - var model = this.get('model'), - params = { - type: 'get', - origin: InfinniUI.config.serverUrl, - path: '/documents/' + this.get('model').getProperty('documentId'), - data: {}, - params: {} - }, - filter = model.getProperty('filter'), - filterParams = model.getProperty('filterParams'), - pageNumber = model.getProperty('pageNumber'), - pageSize = model.getProperty('pageSize'), - searchStr = model.getProperty('search'), - select = model.getProperty('select'), - order = model.getProperty('order'), - needTotalCount = model.getProperty('needTotalCount'); + modifiedItems: {}, + itemsById: {}, - if(filter){ - params.data.filter = filter; - if(filterParams){ - _.extend(params.params, filterParams); - } - } + fillCreatedItem: true, - if(pageSize){ - pageNumber = pageNumber || 0; - params.data.skip = pageNumber*pageSize; - params.data.take = pageSize; - } + suspendingList: null, // [] - if(searchStr){ - params.data.search = searchStr; - } + waitingOnUpdateItemsHandlers: null, //[] - if(select){ - params.data.select = select; - } + errorValidator: null, - if(order){ - params.data.order = order; - } + isRequestInProcess: false, - if(needTotalCount){ - params.data.count = needTotalCount; - } + isLazy: true, - this.setGettingUrlParams(params); - }, + isWaiting: false, - updateSettingUrlParams: function(){ - var model = this.get('model'), - params = { - type: 'post', - origin: InfinniUI.config.serverUrl, - path: '/documents/' + this.get('model').getProperty('documentId'), - data: {}, - params: {} - }; + resolvePriority: 0, - this.setSettingUrlParams(params); - }, + newItemsHandler: null, - updateDeletingUrlParams: function(){ - var model = this.get('model'), - params = { - type: 'delete', - origin: InfinniUI.config.serverUrl, - path: '/documents/' + this.get('model').getProperty('documentId') + '/<%id%>', - data: {}, - params: {} - }; + isNumRegEx: /^\d/ - this.setDeletingUrlParams(params); }, - initDataProvider: function(){ - var dataProvider = window.InfinniUI.providerRegister.build('DocumentDataSource'); - - this.set('dataProvider', dataProvider); - }, + initialize: function () { + var view = this.get('view'); + var modelStartTree = { + items: null, + selectedItem: null + }; - getDocumentId: function(){ - return this.get('model').getProperty('documentId'); - }, + this.initDataProvider(); + if (!view) { + throw 'BaseDataSource.initialize: При создании объекта не была задана view.' + } + this.set('suspendingList', []); + this.set('waitingOnUpdateItemsHandlers', []); + this.set('model', new TreeModel(view.getContext(), this, modelStartTree)); - setDocumentId: function(documentId){ - this.get('model').setProperty('documentId', documentId); + _.extend( this, BaseDataSource.identifyingStrategy.byId); }, - getFilter: function(){ - return this.get('model').getProperty('filter'); + initDataProvider: function () { + throw 'BaseDataSource.initDataProvider В потомке BaseDataSource не задан провайдер данных.' }, - setFilter: function(filter){ - this.get('model').setProperty('filter', filter); - }, + onPropertyChanged: function (property, handler, owner) { - getFilterParams: function(propertyName){ - if(arguments.length == 0){ - propertyName = 'filterParams'; + if (typeof property == 'function') { + owner = handler; + handler = property; + property = '*'; + } + if(property.charAt(0) == '.'){ + property = property.substr(1); }else{ - if(propertyName == ''){ - propertyName = 'filterParams'; + if(property == ''){ + property = 'items'; }else{ - propertyName = 'filterParams.' + propertyName; + property = 'items.' + property; } + } - return this.get('model').getProperty(propertyName); + this.get('model').onPropertyChanged(property, function(context, args){ + var property = args.property; + + if(property.substr(0,6) == 'items.'){ + property = property.substr(6); + }else if(property == 'items'){ + property = ''; + } else{ + property = '.' + property; + } + + args.property = property; + + handler(context, args); + }, owner); }, - setFilterParams: function(propertyName, value){ - if(arguments.length == 1){ - value = propertyName; - propertyName = 'filterParams'; + onSelectedItemChanged: function (handler, owner) { + var that = this; - }else{ - if(propertyName == ''){ - propertyName = 'filterParams'; - }else{ - propertyName = 'filterParams.' + propertyName; - } - } + this.get('model').onPropertyChanged('selectedItem', function(context, args){ + var argument = that._getArgumentTemplate(); + argument.value = args.newValue; - this.get('model').setProperty(propertyName, value); + handler(context, argument); + }, owner); }, - setIdFilter: function (itemId) { - this.setFilter('eq(' + this.getIdProperty() + ','+ this.quoteValue(itemId) + ')'); + onErrorValidator: function (handler) { + this.on('onErrorValidator', handler); }, - getPageNumber: function(){ - return this.get('model').getProperty('pageNumber'); + onItemSaved: function (handler) { + this.on('onItemSaved', handler); }, - setPageNumber: function(pageNumber){ - this.get('model').setProperty('pageNumber', pageNumber); + onItemCreated: function (handler) { + this.on('onItemCreated', handler); }, - getPageSize: function(){ - return this.get('model').getProperty('pageSize'); + onItemsUpdated: function (handler) { + this.on('onItemsUpdated', handler); }, - setPageSize: function(pageSize){ - this.get('model').setProperty('pageSize', pageSize); + onItemsUpdatedOnce: function (handler) { + this.once('onItemsUpdated', handler); }, - getSearch: function(){ - return this.get('model').getProperty('search'); + onItemDeleted: function (handler) { + this.on('onItemDeleted', handler); }, - setSearch: function(searchStr){ - this.get('model').setProperty('search', searchStr); + onProviderError: function (handler) { + this.on('onProviderError', handler); }, - getSelect: function(){ - return this.get('model').getProperty('select'); + getName: function () { + return this.get('name'); }, - setSelect: function(selectStr){ - this.get('model').setProperty('select', selectStr); + setName: function (name) { + this.set('name', name); + this.name = name; }, - getOrder: function(){ - return this.get('model').getProperty('order'); + getView: function () { + return this.get('view'); }, - setOrder: function(orderConditionStr){ - this.get('model').setProperty('order', orderConditionStr); - }, + getProperty: function (property) { + var firstChar = property.charAt(0); + var indexOfSelectedItem; - getTotalCount: function(){ - return this.get('model').getProperty('totalCount'); - }, + if( this.get('isNumRegEx').test(firstChar) ){ + property = 'items.' + property; - getNeedTotalCount: function(){ - return this.get('model').getProperty('needTotalCount'); - }, + }else if(firstChar == ''){ + property = 'items'; - setNeedTotalCount: function(needTotalCount){ - this.get('model').setProperty('needTotalCount', needTotalCount); - }, + }else if(firstChar == '$'){ + indexOfSelectedItem = this._indexOfSelectedItem(); + if(indexOfSelectedItem == -1){ + return undefined; + } + property = 'items.' + indexOfSelectedItem + property.substr(1); - beforeDeleteItem: function(item){ - var itemId = this.idOfItem(item); - if(itemId !== undefined){ - this.setDeletingUrlParams('params.id', itemId); + }else if(firstChar == '.'){ + property = property.substr(1); + }else{ + indexOfSelectedItem = this._indexOfSelectedItem(); + if(indexOfSelectedItem == -1){ + return undefined; + } + property = 'items.' + indexOfSelectedItem + '.' + property; } + + return this.get('model').getProperty(property); }, - quoteValue: function (value) { - var VALUE_QUOTE_CHAR = '\''; + setProperty: function (property, value) { + var propertyPaths = property.split('.'); + var firstChar; + var indexOfSelectedItem; + var index; + var resultOfSet; - if (_.isString(value)) { - return VALUE_QUOTE_CHAR + value + VALUE_QUOTE_CHAR; - } else { - return value + if(propertyPaths[0] == '$'){ + indexOfSelectedItem = this._indexOfSelectedItem(); + if(indexOfSelectedItem == -1){ + return; + } + + property = indexOfSelectedItem + property.substr(1); + propertyPaths[0] = indexOfSelectedItem.toString(); } - } -}); + firstChar = property.charAt(0); -window.InfinniUI.DocumentDataSource = DocumentDataSource; + if(propertyPaths.length == 1){ -//####app/data/dataSource/baseDataSourceBuilder.js -/** - * @constructor - * @mixes DataSourceValidationNotifierMixin - */ -var BaseDataSourceBuilder = function() { -} + if(propertyPaths[0] == ''){ + this._setItems(value); -_.extend(BaseDataSourceBuilder.prototype, /** @lends BaseDataSourceBuilder.prototype */ { - build: function (context, args) { - var dataSource = this.createDataSource(args.parentView); - dataSource.suspendUpdate('tuningInSourceBuilder'); + }else if( this.get('isNumRegEx').test(propertyPaths[0]) ){ + this._changeItem(propertyPaths[0], value); - this.applyMetadata(args.builder, args.parentView, args.metadata, dataSource); + }else{ + indexOfSelectedItem = this._indexOfSelectedItem(); + if(indexOfSelectedItem == -1){ + return; + } + property = 'items.' + indexOfSelectedItem + '.' + property; + resultOfSet = this.get('model').setProperty(property, value); - this.applySuspended(dataSource, args.suspended); + if(resultOfSet){ + this._includeItemToModifiedSetByIndex(indexOfSelectedItem); + } + } - dataSource.resumeUpdate('tuningInSourceBuilder'); + }else{ + if(firstChar == '.'){ + property = property.substr(1); + this.get('model').setProperty(property, value); - return dataSource; - }, + }else if(this.get('isNumRegEx').test(firstChar)){ + property = 'items.' + property; + resultOfSet = this.get('model').setProperty(property, value); - applySuspended: function (dataSource, suspended) { - if (!suspended) { - return; - } + if(resultOfSet){ + this._includeItemToModifiedSetByIndex( parseInt(propertyPaths[0])); + } + }else{ + indexOfSelectedItem = this._indexOfSelectedItem(); + if(indexOfSelectedItem == -1){ + return; + } + property = 'items.' + indexOfSelectedItem + '.' + property; + resultOfSet = this.get('model').setProperty(property, value); - for (var name in suspended) { - if (!suspended.hasOwnProperty(name) || dataSource.getName() !== name) { - continue; + if(resultOfSet){ + this._includeItemToModifiedSetByIndex(indexOfSelectedItem); + } } - - dataSource.suspendUpdate(suspended[name]); } - }, - applyMetadata: function (builder, parentView, metadata, dataSource) { - var idProperty = metadata.IdProperty; - if (idProperty) { - dataSource.setIdProperty(idProperty); - } + _setItems: function (items) { + this._detectIdentifyingMode(items); - dataSource.setName(metadata.Name); - dataSource.setFillCreatedItem(metadata.FillCreatedItem); - //dataSource.setPageSize(metadata.PageSize || 15); - //dataSource.setPageNumber(metadata.PageNumber || 0); - // - //if('Sorting' in metadata){ - // dataSource.setSorting(metadata['Sorting']); - //} - // - //var queryMetadata; - //if('Query' in metadata){ - // dataSource.setFilter(metadata['Query']); - //} + var indexOfItemsById; - if('IsLazy' in metadata){ - dataSource.setIsLazy(metadata['IsLazy']); - } + this.set('isDataReady', true); + this.get('model').setProperty('items', items); + this._clearModifiedSet(); + if (items && items.length > 0) { + indexOfItemsById = this._indexItemsById(items); + this.set('itemsById', indexOfItemsById); - if('ResolvePriority' in metadata){ - dataSource.setResolvePriority(metadata['ResolvePriority']); - } + if( !this._restoreSelectedItem() ){ + this.setSelectedItem(items[0]); + } - if( _.isObject(metadata.CustomProperties) ) { - this.initCustomProperties(dataSource, metadata.CustomProperties); + } else { + this.setSelectedItem(null); } - - this.initValidation(parentView, dataSource, metadata); - this.initNotifyValidation(dataSource); - this.initScriptsHandlers(parentView, metadata, dataSource); - - this.initFileProvider(dataSource); - }, - - createDataSource: function (parent) { - throw 'BaseDataSourceBuilder.createDataSource В потомке BaseDataSourceBuilder не переопределен метод createDataSource.'; }, - initCustomProperties: function(dataSource, customProperties){ - _.each(customProperties, function(value, key){ - dataSource.setProperty('.' + key, value); + _restoreSelectedItem: function(){ + // override by strategy + var logger = window.InfinniUI.global.logger; + logger.warn({ + message: 'BaseDataSource._restoreSelectedItem: not overrided by strategy', + source: this }); }, - - /** - * @protected - * @description Инициализация обработчиков для валидации данных - * @param parentView - * @param dataSource - * @param metadata - */ - initValidation: function (parentView, dataSource, metadata) { - if (metadata.ValidationErrors) { - dataSource.setErrorValidator(function (context, args) { - return new ScriptExecutor(parentView).executeScript(metadata.ValidationErrors.Name || metadata.ValidationErrors, args); - }); - } + + getSelectedItem: function () { + return this.get('model').getProperty('selectedItem'); }, - //Скриптовые обработчики на события - initScriptsHandlers: function (parentView, metadata, dataSource) { + setSelectedItem: function (item, success, error) { + // override by strategy + var logger = window.InfinniUI.global.logger; + logger.warn({ + message: 'BaseDataSource.setSelectedItem: not overrided by strategy', + source: this + }); + }, - if( !parentView ){ - return; - } + _notifyAboutSelectedItem: function (item, successHandler) { + var context = this.getContext(), + argument = this._getArgumentTemplate(); - if (metadata.OnSelectedItemChanged) { - dataSource.onSelectedItemChanged(function (context, args) { - new ScriptExecutor(parentView).executeScript(metadata.OnSelectedItemChanged.Name || metadata.OnSelectedItemChanged, args); - }); - } + argument.value = item; - if (metadata.OnItemsUpdated) { - dataSource.onItemsUpdated(function (context, args) { - new ScriptExecutor(parentView).executeScript(metadata.OnItemsUpdated.Name || metadata.OnItemsUpdated, args); - }); + if (successHandler) { + successHandler(context, argument); } + }, - if (metadata.OnPropertyChanged) { - dataSource.onPropertyChanged(function (context, args) { - new ScriptExecutor(parentView).executeScript(metadata.OnPropertyChanged.Name || metadata.OnPropertyChanged, args); - }); + _tuneMirroringOfModel: function(index){ + if(index != -1){ + this.get('model').setMirroring('items.$', 'items.'+index); + }else{ + this.get('model').setMirroring(null, null); } + }, - if (metadata.OnItemDeleted) { - dataSource.onItemDeleted(function () { - new ScriptExecutor(parentView).executeScript(metadata.OnItemDeleted.Name || metadata.OnItemDeleted); - }); - } + getIdProperty: function () { + return this.get('idProperty'); + }, - if (metadata.OnErrorValidator) { - dataSource.onErrorValidator(function () { - new ScriptExecutor(parentView).executeScript(metadata.OnErrorValidator.Name || metadata.OnErrorValidator); - }); - } + setIdProperty: function (value) { + this.set('idProperty', value); }, - buildBindingBuilder: function(params){ + getFillCreatedItem: function () { + return this.get('fillCreatedItem'); + }, - return function(bindingMetadata){ - return params.builder.buildBinding(bindingMetadata, { - parentView: params.parentView, - basePathOfProperty: params.basePathOfProperty - }); - }; + setFillCreatedItem: function (fillCreatedItem) { + this.set('fillCreatedItem', fillCreatedItem); }, - initFileProvider: function (dataSource) { + suspendUpdate: function (name) { + var reason = name || 'default'; - var host = InfinniUI.config.serverUrl; + var suspended = this.get('suspendingList'); + if (suspended.indexOf(reason) === -1) { + suspended = suspended.slice(0); + suspended.push(reason); + this.set('suspendingList', suspended); + } + }, - var fileUrlConstructor = new DocumentUploadQueryConstructor(host); + resumeUpdate: function (name) { + var reason = name || 'default'; - var fileProvider = new DocumentFileProvider(fileUrlConstructor); + var suspended = this.get('suspendingList'); + var index = suspended.indexOf(reason); - dataSource.setFileProvider(fileProvider); - } + if (index !== -1) { + suspended = suspended.slice(0); + suspended.splice(index, 1); + this.set('suspendingList', suspended); + // если источник полностью разморожен, а до этого вызывались updateItems, не выполненные из-за заморозки, нужно вызвать updateItems + if(!this.isUpdateSuspended() && this.get('waitingOnUpdateItemsHandlers').length > 0){ + this.updateItems(); + } + } + }, -}); + isUpdateSuspended: function () { + var suspended = this.get('suspendingList'); + return suspended.length > 0; + }, + isModifiedItems: function () { + return this.isModified(); + }, -_.extend(BaseDataSourceBuilder.prototype, DataSourceValidationNotifierMixin); + isModified: function (item) { + if (arguments.length == 0) { + return _.size(this.get('modifiedItems')) > 0; + } -window.InfinniUI.BaseDataSourceBuilder = BaseDataSourceBuilder; + if (item === null || item === undefined) { + return false; + } + else { + var itemId = this.idOfItem(item); + return itemId in this.get('modifiedItems'); + } + }, -//####app/data/dataSource/restDataSourceBuilder.js -var RestDataSourceBuilder = function() { - _.superClass(RestDataSourceBuilder, this); -} + _includeItemToModifiedSetByIndex: function (index) { + var item; -_.inherit(RestDataSourceBuilder, BaseDataSourceBuilder); + item = this.getItems()[index]; + this._includeItemToModifiedSet(item); + }, -_.extend(RestDataSourceBuilder.prototype, { - createDataSource: function(parent){ - return new RestDataSource({ - view: parent + _includeItemToModifiedSet: function (item) { + // override by strategy + var logger = window.InfinniUI.global.logger; + logger.warn({ + message: 'BaseDataSource._includeItemToModifiedSet: not overrided by strategy', + source: this }); }, - applyMetadata: function(builder, parent, metadata, dataSource){ - BaseDataSourceBuilder.prototype.applyMetadata.call(this, builder, parent, metadata, dataSource); - - var tmpParams; + _excludeItemFromModifiedSet: function (item) { + // override by strategy + var logger = window.InfinniUI.global.logger; + logger.warn({ + message: 'BaseDataSource._excludeItemFromModifiedSet: not overrided by strategy', + source: this + }); + }, - this.initProviderErrorHandling(dataSource); + _clearModifiedSet: function () { + this.set('modifiedItems', {}); + }, - if('GettingParams' in metadata){ - tmpParams = this.extractUrlParams(metadata['GettingParams'], '.urlParams.get.params'); - dataSource.setGettingUrlParams(tmpParams); - this.bindParams(metadata['GettingParams'], dataSource, parent, '.urlParams.get.params', builder); + /** + * @description Проверяет формат имя свойства атрибута + * @param propertyName + * @private + */ + _checkPropertyName: function (propertyName) { + var result = true; + try { + if (propertyName && propertyName.length > 0) { + result = propertyName.match(/^[\$#@\d]+/); + } + if (!result) { + throw new Error('Wrong property name "' + propertyName + '"'); + } + } catch (e) { + console.debug(e); } + }, - if('SettingParams' in metadata){ - tmpParams = this.extractUrlParams(metadata['SettingParams'], '.urlParams.set.params'); - dataSource.setSettingUrlParams(tmpParams); - this.bindParams(metadata['SettingParams'], dataSource, parent, '.urlParams.set.params', builder); - } + _changeItem: function(index, value){ + var item = this.get('model').getProperty('items.'+index), + isSelectedItem = (item == this.getSelectedItem()), + idProperty = this.get('idProperty'), + indexedItemsById = this.get('itemsById'); - if('DeletingParams' in metadata){ - tmpParams = this.extractUrlParams(metadata['DeletingParams'], '.urlParams.delet.params'); - dataSource.setDeletingUrlParams(tmpParams); - this.bindParams(metadata['DeletingParams'], dataSource, parent, '.urlParams.delet.params', builder); + if(value == item){ + return; } - if('UpdatingItemsConverter' in metadata){ - dataSource.setUpdatingItemsConverter(function (items) { - return new ScriptExecutor(parent).executeScript(metadata['UpdatingItemsConverter'].Name || metadata['UpdatingItemsConverter'], { value: items, source: dataSource }); - }); - } + this._excludeItemFromModifiedSet(item); + delete indexedItemsById[item[idProperty]]; - }, + this.get('model').setProperty('items.'+index, value); - extractUrlParams: function(urlParamsMetadata, pathForBinding){ - var result = {}; + this._includeItemToModifiedSet(value); + indexedItemsById[value[idProperty]] = value; + this.set('itemsById', indexedItemsById); - if('Origin' in urlParamsMetadata){ - result.origin = urlParamsMetadata['Origin']; - }else{ - result.origin = InfinniUI.config.serverUrl; + if(isSelectedItem) { + this.get('model').setProperty('selectedItem', value); } + }, - if('Path' in urlParamsMetadata){ - result.path = urlParamsMetadata['Path']; + tryInitData: function(){ + if (!this.get('isDataReady') && !this.get('isRequestInProcess')){ + this.updateItems(); } + }, - if('Data' in urlParamsMetadata){ - result.data = urlParamsMetadata['Data']; + saveItem: function (item, success, error) { + var dataProvider = this.get('dataProvider'), + ds = this, + logger = window.InfinniUI.global.logger, + that = this, + validateResult, + errorInProvider = this._compensateOnErrorOfProviderHandler(error); + + if (!this.isModified(item)) { + this._notifyAboutItemSaved({item: item, result: null}, 'notModified'); + that._executeCallback(success, {item: item, result: {IsValid: true}}); + return; } - if('Method' in urlParamsMetadata){ - result.method = urlParamsMetadata['Method']; + validateResult = this.getValidationResult(item); + if (!validateResult.IsValid) { + this._notifyAboutValidation(validateResult, 'error'); + this._executeCallback(error, {item: item, result: validateResult}); + return; } - result.params = {}; + dataProvider.saveItem(item, function(data){ + if( !('IsValid' in data) || data.IsValid === true ){ + that._excludeItemFromModifiedSet(item); + that._notifyAboutItemSaved({item: item, result: data.data}, 'modified'); + that._executeCallback(success, {item: item, result: that._getValidationResult(data), originalResponse: data}); + }else{ + var result = that._getValidationResult(data); + that._notifyAboutValidation(result, 'error'); + that._executeCallback(error, {item: item, result: result, originalResponse: data}); + } + }, function(data) { + var result = that._getValidationResult(data); + that._notifyAboutValidation(result, 'error'); + that._executeCallback(errorInProvider, {item: item, result: result, originalResponse: data}); + }); + }, - return result; + _getValidationResult: function(data){ + if(data.data && data.data.responseJSON && data.data.responseJSON['Result']){ + return data.data.responseJSON['Result']['ValidationResult']; + } + + return data.data && data.data['Result'] && data.data['Result']['ValidationResult']; }, - bindParams: function(methodMetadata, dataSource, parentView, pathForBinding, builder){ - if('Params' in methodMetadata){ - var params = methodMetadata['Params']; - for(var k in params){ - this.initBindingToProperty(params[k], dataSource, parentView, pathForBinding + '.' + k, builder); - } + _executeCallback: function(callback, args){ + if(callback){ + callback(this.getContext(), args); } }, - initBindingToProperty: function (valueMetadata, dataSource, parentView, pathForBinding, builder) { - if (typeof valueMetadata != 'object') { - if (valueMetadata !== undefined) { - dataSource.setProperty(pathForBinding, valueMetadata); - } + _notifyAboutItemSaved: function (data, result) { + var context = this.getContext(), + argument = this._getArgumentTemplate(); - } else { - var args = { - parent: parentView, - parentView: parentView - }; + argument.value = data; + argument.result = result; - var dataBinding = builder.buildBinding(valueMetadata, args); + this.trigger('onItemSaved', context, argument); + }, - dataBinding.setMode(InfinniUI.BindingModes.toElement); + deleteItem: function (item, success, error) { + var dataProvider = this.get('dataProvider'), + that = this, + itemId = this.idOfItem(item), + isItemInSet = this.get('itemsById')[itemId] !== undefined, + errorInProvider = this._compensateOnErrorOfProviderHandler(error); - dataBinding.bindElement(dataSource, pathForBinding); + if ( item == null || ( itemId !== undefined && !isItemInSet ) ) { + this._notifyAboutMissingDeletedItem(item, error); + return; } - }, - initProviderErrorHandling: function(dataSource){ - dataSource.onProviderError(function(){ - var exchange = window.InfinniUI.global.messageBus; - exchange.send(messageTypes.onNotifyUser, {messageText: 'Ошибка на сервере', messageType: "error"}); + this.beforeDeleteItem(item); + dataProvider.deleteItem(item, function (data) { + if (!('IsValid' in data) || data['IsValid'] === true) { + that._handleDeletedItem(item, success); + } else { + var result = that._getValidationResult(data); + that._notifyAboutValidation(result, 'error'); + that._executeCallback(error, {item: item, result: result}); + } + }, function(data) { + var result = that._getValidationResult(data); + that._notifyAboutValidation(result, 'error'); + that._executeCallback(errorInProvider, {item: item, result: result}); }); - } -}); - -window.InfinniUI.RestDataSourceBuilder = RestDataSourceBuilder; - -//####app/data/dataSource/documentDataSourceBuilder.js -var DocumentDataSourceBuilder = function() { - _.superClass(DocumentDataSourceBuilder, this); -} + }, -_.inherit(DocumentDataSourceBuilder, BaseDataSourceBuilder); + beforeDeleteItem: function(item){}, -_.extend(DocumentDataSourceBuilder.prototype, { - applyMetadata: function(builder, parent, metadata, dataSource){ - BaseDataSourceBuilder.prototype.applyMetadata.call(this, builder, parent, metadata, dataSource); + _handleDeletedItem: function (item, successHandler) { + // override by strategy + var logger = window.InfinniUI.global.logger; + logger.warn({ + message: 'BaseDataSource._handleDeletedItem: not overrided by strategy', + source: this + }); + }, - dataSource.setDocumentId(metadata['DocumentId']); + _notifyAboutItemDeleted: function (item, successHandler) { + var context = this.getContext(), + argument = this._getArgumentTemplate(); - if('PageNumber' in metadata){ dataSource.setPageNumber(metadata['PageNumber']); } - if('PageSize' in metadata){ dataSource.setPageSize(metadata['PageSize']); } + argument.value = item; - if('Filter' in metadata){ dataSource.setFilter(metadata['Filter']); } - if('FilterParams' in metadata){ - var params = metadata['FilterParams']; - for(var k in params){ - this.initBindingToProperty(params[k], dataSource, parent, '.filterParams.' + k, builder); - } + if (successHandler) { + successHandler(context, argument); } + this.trigger('onItemDeleted', context, argument); + }, - if('Search' in metadata){ dataSource.setSearch(metadata['Search']); } - if('Select' in metadata){ dataSource.setSelect(metadata['Select']); } - if('Order' in metadata){ dataSource.setOrder(metadata['Order']); } - if('NeedTotalCount' in metadata){ dataSource.setNeedTotalCount(metadata['NeedTotalCount']); } + _notifyAboutMissingDeletedItem: function (item, errorHandler) { + var context = this.getContext(), + argument = this._getArgumentTemplate(); + + argument.value = item; + argument.error = { + message: 'Нельзя удалить элемент, которого нет текущем наборе источника данных' + }; - if (Array.isArray(metadata.DefaultItems)) { - dataSource.setProperty('', metadata.DefaultItems); + if (errorHandler) { + errorHandler(context, argument); } }, - createDataSource: function(parent){ - return new DocumentDataSource({ - view: parent - }); + isDataReady: function () { + return this.get('isDataReady'); }, - initBindingToProperty: RestDataSourceBuilder.prototype.initBindingToProperty -}); + getItems: function () { + var logger = window.InfinniUI.global.logger; -window.InfinniUI.DocumentDataSourceBuilder = DocumentDataSourceBuilder; + if (!this.isDataReady()) { + logger.warn({ + message: 'BaseDataSource: Попытка получить данные источника данных (' + this.get('name') + '), до того как он был проинициализирован данными', + source: this + }); + } -//####app/elements/_base/element/element.js -var Element = function (parent, viewMode) { - this.parent = parent; - this.control = this.createControl(viewMode); - this.state = { - Enabled: true - }; + return this.get('model').getProperty('items'); + }, - this.childElements = []; -}; + updateItems: function (onSuccess, onError) { + if (!this.isUpdateSuspended()) { + var dataProvider = this.get('dataProvider'), + that = this; -Object.defineProperties(Element.prototype, { - name: { - get: function () { - return this.getName() - } - } -}); -_.extend(Element.prototype, { + onError = this._compensateOnErrorOfProviderHandler(onError); - createControl: function (viewMode) { - throw ('Не перегружен абстрактный метод Element.createControl'); - }, - setParent: function (parentElement) { - this.parent = parentElement; - }, + this.set('isRequestInProcess', true); + dataProvider.getItems( + function (data) { + that._handleSuccessUpdateItemsInProvider(data, onSuccess, onError); + }, + onError + ); - getParent: function () { - return this.parent; + }else{ + var handlers = this.get('waitingOnUpdateItemsHandlers'); + handlers.push({ + onSuccess: onSuccess, + onError: onError + }); + } + //devblockstart + window.InfinniUI.global.messageBus.send('updateItems', {dataSource: this}); + //devblockstop }, - getChildElements: function () { - return this.childElements; - }, - findAllChildrenByType: function (type) { - return this._findAllChildren(predicate, getChildElements); + _compensateOnErrorOfProviderHandler: function(onError){ + var that = this; - function predicate() { - return this.constructor.name === type; - } + return function(){ + if(typeof onError == 'function'){ + onError.apply(undefined, arguments); + }else{ + that.trigger('onProviderError', arguments); + } + }; - function getChildElements(element) { - return element.findAllChildrenByType(type); - } }, - findAllChildrenByName: function (name) { - return this._findAllChildren(predicate, getChildElements); + _handleSuccessUpdateItemsInProvider: function(data, onSuccess, onError){ + var that = this, + isWaiting = that.get('isWaiting'), + finishUpdating = function(){ + that.set('isRequestInProcess', false); + that._handleUpdatedItemsData(data.data, onSuccess, onError); + }; - function predicate () { - return this.getName() === name; + if(isWaiting){ + that.once('change:isWaiting', function () { + finishUpdating(); + }); + } else { + finishUpdating(); } + }, - function getChildElements (element) { - return element.findAllChildrenByName(name); - } + _onErrorProviderUpdateItemsHandle: function(){ }, - _findAllChildren: function (predicate, getChildElements) { - var elements = this.getChildElements(); - var items = []; - if (Array.isArray(elements)) { - elements.forEach(function (element) { - if (predicate.call(element)) { - items.push(element); - } - Array.prototype.push.apply(items, getChildElements(element)); - }); + setIsWaiting: function(value){ + this.set('isWaiting', value); + }, + + _handleUpdatedItemsData: function (itemsData, successHandler, errorHandler) { + if(this.get('newItemsHandler')){ + itemsData = this.get('newItemsHandler')(itemsData); } - return items; + this._setItems(itemsData); + this._notifyAboutItemsUpdated(itemsData, successHandler, errorHandler); }, - getView: function () { - if (!this.parentView) { - if (this.parent && this.parent.isView) { - this.parentView = this.parent; + _notifyAboutItemsUpdated: function (itemsData, successHandler, errorHandler) { + var context = this.getContext(); + var argument = { + value: itemsData, + source: this + }; + + // вызываем обработчики которые были переданы на отложенных updateItems (из за замороженного источника) + var handlers = this.get('waitingOnUpdateItemsHandlers'); + for(var i = 0, ii = handlers.length; i < ii; i++){ + if(handlers[i].onSuccess){ + handlers[i].onSuccess(context, argument); + } + } + + this.set('waitingOnUpdateItemsHandlers', []); - } else { - if (this.parent && this.parent.getView) { - this.parentView = this.parent.getView(); - } else { - this.parentView = null; - } - } + if (successHandler) { + successHandler(context, argument); } - return this.parentView; + this.trigger('onItemsUpdated', context, argument); }, - getName: function () { - return this.control.get('name'); - }, + _notifyAboutItemsUpdatedAsPropertyChanged: function (itemsData) { + var context = this.getContext(), + argument = this._getArgumentTemplate(); - setName: function (name) { - if(this.getName()){ - throw 'name already exists'; - } + argument.property = ''; + argument.newValue = itemsData; + argument.oldValue = null; - if (typeof name == 'string') { - this.control.set('name', name); - } + this.trigger('onPropertyChanged', context, argument); + this.trigger('onPropertyChanged:', context, argument); }, - getProperty: function (name) { - var getterMethodName = 'get' + this._upperFirstSymbol(name); - if (typeof this[getterMethodName] == 'function') { - return this[getterMethodName](); + createItem: function (success, error) { + var dataProvider = this.get('dataProvider'), + idProperty = this.get('idProperty'), + that = this, + localItem; + + if (this.get('fillCreatedItem')) { + dataProvider.createItem( + function (item) { + that._handleDataForCreatingItem(item, success); + }, + idProperty + ); } else { - throw 'expect that ' + getterMethodName + ' is getter function'; + localItem = dataProvider.createLocalItem(idProperty); + this._handleDataForCreatingItem(localItem, success); } }, - setProperty: function (name, value) { - var setterMethodName = 'set' + this._upperFirstSymbol(name), - getterMethodName; + _handleDataForCreatingItem: function (itemData, successHandler) { + var items = this.getItems(); - if (typeof this[setterMethodName] == 'function') { - this[setterMethodName](value); - } else { - if (this._isCollectionProperty(name)) { - getterMethodName = 'get' + this._upperFirstSymbol(name); - this[getterMethodName]().set(value); - } else { - throw 'expect that ' + setterMethodName + ' is setter function'; - } + if(items) { + items = items.slice(); + items.push(itemData); + }else{ + items = [itemData]; } - }, - _isCollectionProperty: function (propertyName) { - var getterMethodName = 'get' + this._upperFirstSymbol(propertyName); - return (typeof this[getterMethodName] == 'function') && this[getterMethodName]() instanceof Collection; + this._setItems(items); + this._includeItemToModifiedSet(itemData); + this.setSelectedItem(itemData); + this._notifyAboutItemCreated(itemData, successHandler); }, - onPropertyChanged: function (propertyName, handler) { - var subscribingMethodName = 'on' + this._upperFirstSymbol(propertyName) + 'Changed'; - if (typeof this[subscribingMethodName] == 'function') { - this[subscribingMethodName](handler); - } else { - this.control.on('change:' + propertyName, function (model, value) { - var parentView = this.getView(), - context = parentView ? parentView.getContext() : undefined, - args = { - property: propertyName, - oldValue: model.previous(propertyName), - newValue: value - }; - handler(context, args); - }.bind(this)); + _notifyAboutItemCreated: function (createdItem, successHandler) { + var context = this.getContext(), + argument = { + value: createdItem + }; + + if (successHandler) { + successHandler(context, argument); } + this.trigger('onItemCreated', context, argument); }, - getText: function () { - return this.control.get('text'); + getFilter: function () { }, - setText: function (text) { - if (typeof text !== 'undefined') { - this.control.set('text', text); - } + setFilter: function (value, onSuccess, onError) { }, - getEnabled: function () { - return this.control.get('enabled'); + _setCriteriaList: function(criteriaList, onSuccess, onError){ + this.set('criteriaList', criteriaList); + this.updateItems(onSuccess, onError); }, - setEnabled: function (isEnabled) { - if (typeof isEnabled !== 'boolean') { - return; - } - - this.setState('Enabled', isEnabled); - - var parentEnabled = this.control.get('parentEnabled'); - var old = this.control.get('enabled'); + setIdFilter: function (itemId) { + var dataProvider = this.get('dataProvider'), + idFilter = dataProvider.createIdFilter(itemId); - isEnabled = parentEnabled && isEnabled; + this.setFilter(idFilter); + }, - if (isEnabled === old) { - return; - } + setNewItemsHandler: function(handler){ + this.set('newItemsHandler', handler); + }, - this.control.set('enabled', isEnabled); - this.setParentEnabledOnChild(isEnabled); + getErrorValidator: function () { + return this.get('errorValidator'); }, - setParentEnabledOnChild: function (value) { - var elements = this.getChildElements(); - if (_.isEmpty(elements) === false) { - for (var i = 0, ln = elements.length; i < ln; i = i + 1) { - if (typeof elements[i].setParentEnabled === 'undefined') { - continue; - } - elements[i].setParentEnabled(value); - } - } + setErrorValidator: function (validatingFunction) { + this.set('errorValidator', validatingFunction); }, - setParentEnabled: function (value) { + getValidationResult: function (item) { + var validatingFunction = this.get('errorValidator'), + result = { + IsValid: true, + Items: [] + }, + isCheckingOneItem = !!item, + context = this.getContext(), + items, subResult; - if (typeof value !== 'boolean') { - return; - } + if (validatingFunction) { + if (isCheckingOneItem) { - var old = this.control.get('parentEnabled'); - this.control.set('parentEnabled', value); + result = validatingFunction(context, item); - if (old !== value) { - var enabled = value && this.getState('Enabled'); - this.control.set('enabled', enabled); - this.setParentEnabled(enabled); - this.setParentEnabledOnChild(enabled); - } - }, + } else { - getVisible: function () { - return this.control.get('visible'); - }, + items = this.getItems(); + for (var i = 0, ii = items.length; i < ii; i++) { - setVisible: function (isVisible) { - if (typeof isVisible == 'boolean') { - this.control.set('visible', isVisible); - } - }, + subResult = validatingFunction(context, items[i]); + if (!subResult.IsValid) { + this._addIndexToPropertiesOfValidationMessage(subResult.Items, i); + result.IsValid = false; + result.Items = _.union(result.Items, subResult.Items); + } - getStyle: function () { - return this.control.get('style'); - }, + } - setStyle: function (style) { - if (typeof style == 'string') { - this.control.set('style', style); + } } + + return result; }, - getTextHorizontalAlignment: function () { - return this.control.get('textHorizontalAlignment'); + setFileProvider: function (fileProvider) { + this.set('fileProvider', fileProvider); }, - setTextHorizontalAlignment: function (value) { - if (InfinniUI.Metadata.isValidValue(value, InfinniUI.TextHorizontalAlignment)) { - this.control.set('textHorizontalAlignment', value); - } + getFileProvider: function () { + return this.get('fileProvider'); }, - getHorizontalAlignment: function () { - return this.control.get('horizontalAlignment'); + _addIndexToPropertiesOfValidationMessage: function (validationMessages, index) { + for (var i = 0, ii = validationMessages.length; i < ii; i++) { + validationMessages[i].property = index + '.' + validationMessages[i].property; + } }, - setHorizontalAlignment: function (horizontalAlignment) { - if (typeof horizontalAlignment == 'string') { - this.control.set('horizontalAlignment', horizontalAlignment); + _notifyAboutValidation: function (validationResult, validationType) { + if(!validationResult) { + return; } + + var context = this.getContext(), + argument = { + value: validationResult + }; + + this.trigger('onErrorValidator', context, argument); }, - getVerticalAlignment: function () { - return this.control.get('verticalAlignment'); + getContext: function () { + return this.getView().getContext(); }, - setVerticalAlignment: function (verticalAlignment) { - if (typeof verticalAlignment == 'string') { - this.control.set('verticalAlignment', verticalAlignment); + _indexItemsById: function (items) { + var idProperty = this.get('idProperty'), + result = {}, + idValue; + for (var i = 0, ii = items.length; i < ii; i++) { + idValue = items[i][idProperty]; + result[idValue] = items[i]; } - }, - getTextStyle: function () { - return this.control.get('textStyle'); + return result; }, - setTextStyle: function (textStyle) { - if (typeof textStyle == 'string') { - this.control.set('textStyle', textStyle); + _indexOfItem: function(item){ + var items = this.getItems(); + if(!items){ + return -1; } + return items.indexOf(item); }, - getBackground: function () { - return this.control.get('background'); + _indexOfSelectedItem: function(){ + var selectedItem = this.getSelectedItem(); + + return this._indexOfItem(selectedItem); }, - setBackground: function (background) { - if (typeof background == 'string') { - this.control.set('background', background); + idOfItem: function (item) { + var idProperty = this.get('idProperty'); + if (!item) { + return undefined; } + return item[idProperty]; }, - getForeground: function () { - return this.control.get('foreground'); - }, + getCurrentRequestPromise: function(){ + var promise = $.Deferred(); + var logger = window.InfinniUI.global.logger; - setForeground: function (foreground) { - if (typeof foreground == 'string') { - this.control.set('foreground', foreground); + if(this.get('isRequestInProcess')){ + this.onItemsUpdatedOnce(function(){ + if(this.isDataReady()){ + promise.resolve(); + }else{ + logger.warn({ + message: 'BaseDataSource: strange, expected other dataReady status', + source: this + }); + } + }); + }else{ + promise.resolve(); } - }, - onLoaded: function (handler) { - this.control.onLoaded(handler); + return promise; }, - isLoaded: function () { - return this.control.isLoaded(); - }, + getNearestRequestPromise: function(){ + var promise = $.Deferred(); - getFocusable: function () { - return this.control.get('focusable') - }, + this.onItemsUpdatedOnce( function(){ + if(this.isDataReady()){ + promise.resolve(); + }else{ + logger.warn({ + message: 'BaseDataSource: strange, expected other dataReady status', + source: this + }); + } + }); - setFocusable: function (value) { - if (_.isBoolean(value)) { - this.control.set('focusable', value); - } + return promise; }, - getFocused: function () { - return this.control.get('focused'); - }, + //setBindingBuilder: function(bindingBuilder){ + // this.set('bindingBuilder', bindingBuilder); + //}, - setFocused: function (value) { - return this.control.set('focused', !!value); - }, - onLostFocus: function (handler) { - this.control.on('OnLostFocus', handler); + setIsLazy: function(isLazy){ + this.set('isLazy', isLazy); }, - onGotFocus: function (handler) { - this.control.on('OnGotFocus', handler); + isLazy: function(){ + return this.get('isLazy'); }, - setToolTip: function (value) { - this.control.set('toolTip', value); + setResolvePriority: function(priority){ + this.set('resolvePriority', priority); }, - getToolTip: function () { - return this.control.get('toolTip'); + getResolvePriority: function(){ + return this.get('resolvePriority'); }, - setContextMenu: function(items) { - this.control.set('contextMenu', items); + _copyObject: function (currentObject) { + return JSON.parse(JSON.stringify(currentObject)); }, - getContextMenu: function(items) { - return this.control.get('contextMenu'); + _getArgumentTemplate: function () { + return { + source: this + }; }, - getIsLoaded: function () { - return this.control.get('isLoaded'); + _detectIdentifyingMode: function(items){ + if( $.isArray(items) && items.length > 0){ + if( !$.isPlainObject(items[0]) || this.getIdProperty() in items[0] ){ + this.set('identifyingMode', 'byId'); + _.extend( this, BaseDataSource.identifyingStrategy.byId); + }else{ + this.set('identifyingMode', 'byLink'); + _.extend( this, BaseDataSource.identifyingStrategy.byLink); + } + }else{ + this.set('identifyingMode', 'byId'); + _.extend( this, BaseDataSource.identifyingStrategy.byId); + } }, - setIsLoaded: function () { - this.control.set('isLoaded', true); - }, + _getIdentifyingMode: function(){ + return this.get('identifyingMode'); + } - setTag: function (value) { - this.control.set('tag', value); - }, +}); - getTag: function () { - return this.control.get('tag'); - }, - render: function () { - return this.control.render(); - }, +BaseDataSource.identifyingStrategy = { - getWidth: function () { - }, + byId: { + _restoreSelectedItem: function(){ - getHeight: function () { - }, + var selectedItem = this.getSelectedItem(), + selectedItemId = this.idOfItem(selectedItem); - getScriptsStorage: function () { - return this.getView(); - }, + if( selectedItemId != null ){ + var items = this.get('itemsById'); + var newSelectedItem = items[selectedItemId]; - /** - * Установка состояния валидации элеменат - * @param {String} [state="success"] - * @param {String} [message] - */ - setValidationState: function (state, message) { - this.control.set('validationMessage', message); - this.control.set('validationState', state); - }, + if( newSelectedItem != null ){ + this.setSelectedItem(newSelectedItem); + return true; + } + } - /** - * Получение состояния валидации элеменат - * @return {String} [state="success"] - */ - getValidationState: function () { - return this.control.get('validationState'); - }, + return false; + }, - getState: function (name) { - return this.state[name]; - }, + setSelectedItem: function (item, success, error) { + var currentSelectedItem = this.getSelectedItem(), + items = this.get('itemsById'), + itemId = this.idOfItem(item), + index; - setState: function (name, value) { - this.state[name] = value; - }, - onBeforeClick: function (handler) { - return this.control.onBeforeClick(handler); - }, + if (typeof item == 'undefined') { + item = null; + } - onKeyDown: function (handler) { - var that = this, - callback = function (nativeEventData) { - var eventData = that._getHandlingKeyEventData(nativeEventData); - handler(eventData); - }; - return this.control.onKeyDown(callback); - }, + if (item == currentSelectedItem) { + return; + } - onKeyUp: function (handler) { - var that = this, - callback = function (nativeEventData) { - var eventData = that._getHandlingKeyEventData(nativeEventData); - handler(eventData); - }; - return this.control.onKeyUp(callback); - }, + if (item !== null) { + if (!items[itemId]) { + if (!error) { + throw 'BaseDataSource.setSelectedItem() Попытка выбрать элемент в источнике, которого нет среди элементов этого источника.'; + } else { + error(this.getContext(), {error: 'BaseDataSource.setSelectedItem() Попытка выбрать элемент в источнике, которого нет среди элементов этого источника.'}); + return; + } + } + } - onClick: function (handler) { - var that = this, - callback = function (nativeEventData) { - var eventData = that._getHandlingMouseEventData(nativeEventData); - handler(eventData); - }; - return this.control.onClick(callback); - }, + this.get('model').setProperty('selectedItem', item); - onDoubleClick: function (handler) { - var that = this, - callback = function (nativeEventData) { - var eventData = that._getHandlingMouseEventData(nativeEventData); - handler(eventData); - }; - return this.control.onDoubleClick(callback); - }, + index = this._indexOfItem(items[itemId]); + this._tuneMirroringOfModel(index); - onMouseDown: function (handler) { - var that = this, - callback = function (nativeEventData) { - var eventData = that._getHandlingMouseEventData(nativeEventData); - handler(eventData); - }; - return this.control.onMouseDown(callback); - }, + this._notifyAboutSelectedItem(item, success); + }, + + _includeItemToModifiedSet: function (item) { + var itemId = this.idOfItem(item); + this.get('modifiedItems')[itemId] = item; + }, + + _excludeItemFromModifiedSet: function (item) { + var itemId = this.idOfItem(item); + delete this.get('modifiedItems')[itemId]; + }, + + _handleDeletedItem: function (item, successHandler) { + var items = this.getItems(), + idProperty = this.get('idProperty'), + itemId = this.idOfItem(item), + selectedItem = this.getSelectedItem(); - onMouseUp: function (handler) { - var that = this, - callback = function (nativeEventData) { - var eventData = that._getHandlingMouseEventData(nativeEventData); - handler(eventData); - }; - return this.control.onMouseUp(callback); - }, + for (var i = 0, ii = items.length, needExit = false; i < ii && !needExit; i++) { + if (items[i][idProperty] == itemId) { + items.splice(i, 1); + needExit = true; + } + } + delete this.get('itemsById')[itemId]; + this._excludeItemFromModifiedSet(item); - onMouseEnter: function (handler) { - var that = this, - callback = function (nativeEventData) { - var eventData = that._getHandlingMouseEventData(nativeEventData); - handler(eventData); - }; - return this.control.onMouseEnter(callback); - }, + if (selectedItem && selectedItem[idProperty] == itemId) { + this.setSelectedItem(null); + } - onMouseLeave: function (handler) { - var that = this, - callback = function (nativeEventData) { - var eventData = that._getHandlingMouseEventData(nativeEventData); - handler(eventData); - }; - return this.control.onMouseLeave(callback); + this._notifyAboutItemDeleted(item, successHandler); + } }, - onMouseMove: function (handler) { - var that = this, - callback = function (nativeEventData) { - var eventData = that._getHandlingMouseEventData(nativeEventData); - handler(eventData); - }; - return this.control.onMouseMove(callback); - }, + byLink: { + _restoreSelectedItem: function(){ - onMouseWheel: function (handler) { - var that = this, - callback = function (nativeEventData) { - var eventData = that._getHandlingMouseEventData(nativeEventData); - handler(eventData); - }; - return this.control.onMouseWheel(callback); - }, + var selectedItem = this.getSelectedItem(); + var items = this.getItems(); - remove: function (isInitiatedByParent) { - var logger = window.InfinniUI.global.logger; - if(this.isRemoved){ - logger.warn('Element.remove: Попытка удалить элемент, который уже был удален'); - return; - } + if( items.indexOf(selectedItem) == -1 ){ + return false; + }else{ + return true; + } + }, - var children = this.childElements; + setSelectedItem: function (item, success, error) { + var currentSelectedItem = this.getSelectedItem(), + items = this.getItems(), + index = this._indexOfItem(item); - for (var i = 0, ii = children.length; i < ii; i++) { - children[i].remove(true); - } - this.control.remove(); + if (typeof item == 'undefined') { + item = null; + } - if (this.parent && this.parent.removeChild && !isInitiatedByParent) { - if(this.parent.isRemoved){ - logger.warn('Element.remove: Попытка удалить элемент из родителя, который помечан как удаленный'); - }else{ - this.parent.removeChild(this); + if (item == currentSelectedItem) { + return; } - } + if (item !== null) { + if (index == -1) { + if (!error) { + throw 'BaseDataSource.setSelectedItem() Попытка выбрать элемент в источнике, которого нет среди элементов этого источника.'; + } else { + error(this.getContext(), {error: 'BaseDataSource.setSelectedItem() Попытка выбрать элемент в источнике, которого нет среди элементов этого источника.'}); + return; + } + } + } - this.isRemoved = true; + this.get('model').setProperty('selectedItem', item); - this.childElements = undefined; - }, + this._tuneMirroringOfModel(index); - removeChild: function (child) { - var index = this.childElements.indexOf(child); - if (index != -1) { - this.childElements.splice(index, 1); - } - }, + this._notifyAboutSelectedItem(item, success); + }, - addChild: function (child) { - if(!this.isRemoved){ - this.childElements.push(child); + _includeItemToModifiedSet: function (item) { + this.get('modifiedItems')['-'] = item; + }, - }else{ - var logger = window.InfinniUI.global.logger; - logger.warn('Element.addChild: Попытка добавить потомка в удаленный элемент'); - } + _excludeItemFromModifiedSet: function (item) { + delete this.get('modifiedItems')['-']; + }, - }, + _handleDeletedItem: function (item, successHandler) { + var items = this.getItems(), + selectedItem = this.getSelectedItem(), + index = items.indexOf(item); - createControlEventHandler: function(element, handler, additionParams) { - var context; - var parentView = element.getView(); - additionParams = additionParams || {}; + if(index >= 0){ + items.splice(index, 1); + this._excludeItemFromModifiedSet(item); - if (parentView) { - context = parentView.context; + if (selectedItem && selectedItem == item) { + this.setSelectedItem(null); + } + } + + this._notifyAboutItemDeleted(item, successHandler); } + } +}; - return function (message) { - _.extend( - message, - additionParams - ); - message.source = element; +window.InfinniUI.BaseDataSource = BaseDataSource; - return handler.call(undefined, context, message); - }; - }, +//####app/data/dataSource/restDataSource.js +var RestDataSource = BaseDataSource.extend({ - _getHandlingKeyEventData: function (nativeData) { - var result = {}; + defaults: _.defaults({ + updatingItemsConverter: null - result = { - source: this, - key: nativeData.which, - altKey: nativeData.altKey, - ctrlKey: nativeData.ctrlKey, - shiftKey: nativeData.shiftKey, - nativeEventData: nativeData - }; - return result; - }, + }, BaseDataSource.prototype.defaults), - _getHandlingMouseEventData: function (nativeData) { - var result = {}; + initialize: function(){ + BaseDataSource.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - result = { - source: this, - button: nativeData.which, - altKey: nativeData.altKey, - ctrlKey: nativeData.ctrlKey, - shiftKey: nativeData.shiftKey, - nativeEventData: nativeData + var model = this.get('model'); + model.urlParams = { + get: { + method: 'get', + origin: null, + path: '', + data: {}, + params: {} + }, + + set: { + method: 'post', + origin: null, + path: '', + data: {}, + params: {} + }, + + delete: { + method: 'delete', + origin: null, + path: '', + data: {}, + params: {} + } }; - return result; - }, - _upperFirstSymbol: function (s) { - return s[0].toUpperCase() + s.substr(1); + this.initUrlParamsHandlers(); }, - setFocus: function () { - this.control.setFocus(); + initDataProvider: function(){ + var dataProvider = window.InfinniUI.providerRegister.build('RestDataSource'); + this.set('dataProvider', dataProvider); }, - renderTree: function(textIndent) { - var textIndent = textIndent || ''; - console.log( textIndent + 'Name: ' + this.getName(), this ); - if( this.childElements !== undefined ) { - if( textIndent !== '' ) { - textIndent += '_____'; - } else { - textIndent += '_____'; - } - for( var i = 0, ii = this.childElements.length; i < ii; i += 1 ) { - this.renderTree.call(this.childElements[i], textIndent); - } - } + initUrlParamsHandlers: function(){ + var that = this; + + this.get('model').onPropertyChanged('urlParams.get.*', function(context, args){ + var dataProvider = that.get('dataProvider'); + var urlParams = that.getGettingUrlParams(); + var templated; + + dataProvider.setOrigin('get', urlParams.origin); + templated = that._templateParamsInStr(urlParams.path, urlParams.params); + dataProvider.setPath('get', templated); + templated = that._templateParamsInObject(urlParams.data, urlParams.params); + dataProvider.setData('get', templated); + dataProvider.setMethod('get', urlParams.method); + + if( that.get('isDataReady') || that.get('isRequestInProcess') || that.get('waitingOnUpdateItemsHandlers').length > 0 ){ // ds was resolved or waiting resolving + that.updateItems(); + } + }); + + this.get('model').onPropertyChanged('urlParams.set.*', function(context, args){ + var dataProvider = that.get('dataProvider'); + var urlParams = that.getSettingUrlParams(); + var templated; + + dataProvider.setOrigin('set', urlParams.origin); + templated = that._templateParamsInStr(urlParams.path, urlParams.params); + dataProvider.setPath('set', templated); + templated = that._templateParamsInObject(urlParams.data, urlParams.params); + dataProvider.setData('set', templated); + dataProvider.setMethod('set', urlParams.method); + }); + + this.get('model').onPropertyChanged('urlParams.delete.*', function(context, args){ + var dataProvider = that.get('dataProvider'); + var urlParams = that.getDeletingUrlParams(); + var templated; + + dataProvider.setOrigin('delete', urlParams.origin); + templated = that._templateParamsInStr(urlParams.path, urlParams.params); + dataProvider.setPath('delete', templated); + templated = that._templateParamsInObject(urlParams.data, urlParams.params); + dataProvider.setData('delete', templated); + dataProvider.setMethod('delete', urlParams.method); + }); }, - renderFullTree: function() { - var parent = this.parent; - while( parent.parent && parent.parent.parent !== undefined ) { - parent = parent.parent; - } - this.renderTree.call(parent); - } -}); + updateItems: function(){ -window.InfinniUI.Element = Element; + if(this._checkGettingUrlParamsReady()){ + BaseDataSource.prototype.updateItems.apply(this, Array.prototype.slice.call(arguments)); + this.resumeUpdate('urlGettingParamsNotReady'); -//####app/elements/_base/element/elementBuilder.js -/** - * - * @constructor - */ -var ElementBuilder = function () { -}; + }else{ + this.suspendUpdate('urlGettingParamsNotReady'); + BaseDataSource.prototype.updateItems.apply(this, Array.prototype.slice.call(arguments)); + } -_.extend(ElementBuilder.prototype, /** @lends ElementBuilder.prototype */ { + }, - build: function (context, args) { - args = args || {}; - var element = this.createElement(args), - params = _.extend(args, { element: element }); + getGettingUrlParams: function(propertyName){ + if(arguments.length == 0){ + propertyName = 'urlParams.get'; - this.applyMetadata(params); + }else{ + if(propertyName == ''){ + propertyName = 'urlParams.get'; + }else{ + propertyName = 'urlParams.get.' + propertyName; + } + } + return this.get('model').getProperty(propertyName); + }, - if (args.parentView && args.parentView.registerElement) { - args.parentView.registerElement(element); - } + setGettingUrlParams: function(propertyName, value){ + if(arguments.length == 1){ + value = propertyName; + propertyName = 'urlParams.get'; - if (args.parent && args.parent.addChild) { - args.parent.addChild(element); - } + }else{ + if(propertyName == ''){ + propertyName = 'urlParams.get'; + }else{ + propertyName = 'urlParams.get.' + propertyName; + } + } -//devblockstart - element.onMouseDown( function(eventData) { - if( eventData.ctrlKey ){ - args.metadata.isSelectedElement = true; - args.parentView.showSelectedElementMetadata(); - eventData.nativeEventData.stopPropagation(); - } - }); -//devblockstop + this.get('model').setProperty(propertyName, value); + }, - return element; - }, + getSettingUrlParams: function(propertyName){ + if(arguments.length == 0){ + propertyName = 'urlParams.set'; - /** - * - * @param {Object} params - * @param {Builder} params.builder - * @param {View} params.parent - * @param {Object} params.metadata - * @param {ListBoxItemCollectionProperty} params.collectionProperty - */ - createElement: function (params) { - throw ('Не перегружен абстрактный метод ElementBuilder.createElement()'); - }, + }else{ + if(propertyName == ''){ + propertyName = 'urlParams.set'; + }else{ + propertyName = 'urlParams.set.' + propertyName; + } + } + return this.get('model').getProperty(propertyName); + }, - /** - * - * @param {Object} params - * @param {Builder} params.builder - * @param {View} params.parent - * @param {Object} params.metadata - * @param {ListBoxItemCollectionProperty} params.collectionProperty - * @param {Element} params.element - */ - applyMetadata: function (params) { - var metadata = params.metadata, - element = params.element; + setSettingUrlParams: function(propertyName, value){ + if(arguments.length == 1){ + value = propertyName; + propertyName = 'urlParams.set'; - this.initBindingToProperty(params, 'Text'); - this.initBindingToProperty(params, 'Visible', true); - this.initBindingToProperty(params, 'Enabled', true); - this.initBindingToProperty(params, 'HorizontalAlignment'); - this.initBindingToProperty(params, 'TextHorizontalAlignment'); - this.initBindingToProperty(params, 'VerticalAlignment'); - this.initBindingToProperty(params, 'TextStyle'); - this.initBindingToProperty(params, 'Foreground'); - this.initBindingToProperty(params, 'Background'); - this.initBindingToProperty(params, 'Style'); - this.initBindingToProperty(params, 'Tag'); - this.initBindingToProperty(params, 'Focusable', true); + }else{ + if(propertyName == ''){ + propertyName = 'urlParams.set'; + }else{ + propertyName = 'urlParams.set.' + propertyName; + } + } - if( metadata.ToolTip ) { - this.initToolTip(params); - } - if( metadata.ContextMenu ) { - this.initContextMenu(params); - } + this.get('model').setProperty(propertyName, value); + }, - if ('Name' in metadata) { - element.setName(metadata.Name); - } + getDeletingUrlParams: function(propertyName){ + if(arguments.length == 0){ + propertyName = 'urlParams.delete'; + }else{ + if(propertyName == ''){ + propertyName = 'urlParams.delete'; + }else{ + propertyName = 'urlParams.delete.' + propertyName; + } + } + return this.get('model').getProperty(propertyName); + }, - if (metadata.OnLoaded) { - element.onLoaded(function () { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnLoaded.Name || metadata.OnLoaded, { source: element }); - }); - } + setDeletingUrlParams: function(propertyName, value){ + if(arguments.length == 1){ + value = propertyName; + propertyName = 'urlParams.delete'; - if (metadata.OnGotFocus) { - element.onGotFocus(function () { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnGotFocus.Name || metadata.OnGotFocus, { source: element }); - }); - } + }else{ + if(propertyName == ''){ + propertyName = 'urlParams.delete'; + }else{ + propertyName = 'urlParams.delete.' + propertyName; + } + } - if (metadata.OnLostFocus) { - element.onLostFocus(function () { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnLostFocus.Name || metadata.OnLostFocus, { source: element }); - }); - } + this.get('model').setProperty(propertyName, value); + }, - if (metadata.OnDoubleClick) { - element.onDoubleClick(function (args) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnDoubleClick.Name || metadata.OnDoubleClick, args); - }); - } + _checkGettingUrlParamsReady: function(){ + var allParams = []; + var strWithParams; + var params; + var data; + var definedParams; + var param; - if (metadata.OnClick) { - element.onClick(function (args) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnClick.Name || metadata.OnClick, args); - }); - } + if(!this._checkUrlParamsReady(this.getGettingUrlParams())){ + return false; + } - if (metadata.OnMouseEnter) { - element.onMouseEnter(function (args) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnMouseEnter.Name || metadata.OnMouseEnter, args); - }); - } + strWithParams = this.getGettingUrlParams('path'); + params = this._findSubstitutionParams(strWithParams); + allParams = allParams.concat(params); - if (metadata.OnMouseLeave) { - element.onMouseLeave(function (args) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnMouseLeave.Name || metadata.OnMouseLeave, args); - }); - } + data = this.getGettingUrlParams('data'); + strWithParams = JSON.stringify(data); + params = this._findSubstitutionParams(strWithParams); + allParams = allParams.concat(params); - if (metadata.OnMouseMove) { - element.onMouseMove(function (args) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnMouseMove.Name || metadata.OnMouseMove, args); - }); - } + definedParams = this.getGettingUrlParams('params'); + for(var i = 0, ii = allParams.length; i 0 + && typeof params.path == 'string' + && typeof params.data == 'object' + && typeof params.params == 'object'; + }, - if (metadata.OnMouseDown) { - element.onMouseDown(function (args) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnMouseDown.Name || metadata.OnMouseDown, args); - }); - } + _findSubstitutionParams: function(str){ + if(!str){ + return []; + } - if (metadata.OnMouseUp) { - element.onMouseUp(function (args) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnMouseUp.Name || metadata.OnMouseUp, args); - }); - } + var result = []; + str.replace(/<%([\s\S]+?)%>/g, function(p1, p2){ + result.push(p2); + return p1; + }); - if (metadata.OnMouseWheel) { - element.onMouseWheel(function (args) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnMouseWheel.Name || metadata.OnMouseWheel, args); - }); - } - }, + return result; + }, - initBindingToProperty: function (params, propertyName, isBooleanBinding) { - var metadata = params.metadata, - propertyMetadata = metadata[propertyName], - element = params.element, - lowerCasePropertyName = this.lowerFirstSymbol(propertyName), - converter; + _templateParamsInStr: function(str, params){ + if(!str || !params){ + return str; + } - if (!propertyMetadata || typeof propertyMetadata != 'object') { - if (propertyMetadata !== undefined) { - params.element['set' + propertyName](propertyMetadata); - } - return null; + return str.replace(/<%([\s\S]+?)%>/g, function(p1, p2){ + return params[p2]; + }); + }, - } else { - var args = { - parent: params.parent, - parentView: params.parentView, - basePathOfProperty: params.basePathOfProperty - }; + _templateParamsInObject: function(obj, params){ + if(!obj || !params){ + return obj; + } - var dataBinding = params.builder.buildBinding(metadata[propertyName], args); - var oldConverter; + var str = JSON.stringify(obj); + var tmpTemplated = this._templateParamsInStr(str, params); + return JSON.parse(tmpTemplated); + }, - if (isBooleanBinding) { - dataBinding.setMode(InfinniUI.BindingModes.toElement); + getUpdatingItemsConverter: function(){ + return this.get('updatingItemsConverter'); + }, - converter = dataBinding.getConverter(); - if (!converter) { - converter = {}; - } + setUpdatingItemsConverter: function(converter){ + this.set('updatingItemsConverter', converter); + }, - if(!converter.toElement){ - converter.toElement = function (context, args) { - return !!args.value; - }; - }else{ - oldConverter = converter.toElement; + _handleUpdatedItemsData: function (itemsData, successHandler, errorHandler) { + var converter = this.getUpdatingItemsConverter(); + var items; - converter.toElement = function (context, args) { - var tmp = oldConverter(context, args); - return !!tmp; - }; - } + if(converter){ + items = converter(itemsData); + }else{ + items = itemsData; + } + BaseDataSource.prototype._handleUpdatedItemsData.call(this, items, successHandler, errorHandler); + } - dataBinding.setConverter(converter); - } +}); - dataBinding.bindElement(element, lowerCasePropertyName); +window.InfinniUI.RestDataSource = RestDataSource; - return dataBinding; - } - }, +//####app/data/dataSource/documentDataSource.js +var DocumentDataSource = RestDataSource.extend({ + defaults: _.defaults({ + documentId: null - initToolTip: function (params) { - var exchange = window.InfinniUI.global.messageBus, - builder = params.builder, - element = params.element, - metadata = params.metadata, - tooltip; + }, RestDataSource.prototype.defaults), - var argumentForBuilder = { - parent: element, - parentView: params.parentView, - basePathOfProperty: params.basePathOfProperty - }; + initialize: function () { + RestDataSource.prototype.initialize.apply(this, Array.prototype.slice.call(arguments)); - if (typeof metadata.ToolTip === 'string') { - tooltip = builder.buildType("Label", { - "Text": metadata.ToolTip - }, argumentForBuilder); - } else { - tooltip = builder.build(metadata.ToolTip, argumentForBuilder); - } + var model = this.get('model'); + model.setProperty('pageNumber', 0); + model.setProperty('pageSize', 15); + model.setProperty('filterParams', {}); + this.setUpdatingItemsConverter(function(data){ + model.setProperty('totalCount', data['Result']['Count']); + model.setProperty('additionalResult', data['Result']['AdditionalResult']); + return data['Result']['Items']; + }); - element.setToolTip(tooltip); - exchange.send(messageTypes.onToolTip.name, { source: element, content: tooltip.render() }); - }, + this.initHandlers(); + }, - initContextMenu: function(params) { - var exchange = window.InfinniUI.global.messageBus, - builder = params.builder, - element = params.element, - metadata = params.metadata, - contextMenu; + initHandlers: function(){ + var model = this.get('model'); + var that = this; + var updateGettingUrlParams = _.bind(this.updateGettingUrlParams, this); - var argumentForBuilder = { - parent: element, - parentView: params.parentView, - basePathOfProperty: params.basePathOfProperty - }; + model.onPropertyChanged('documentId', function(){ + that.updateGettingUrlParams(); + that.updateSettingUrlParams(); + that.updateDeletingUrlParams(); + }); + model.onPropertyChanged('filter', updateGettingUrlParams); + model.onPropertyChanged('filterParams.*', updateGettingUrlParams); + model.onPropertyChanged('pageNumber', updateGettingUrlParams); + model.onPropertyChanged('pageSize', updateGettingUrlParams); + model.onPropertyChanged('search', updateGettingUrlParams); + model.onPropertyChanged('select', updateGettingUrlParams); + model.onPropertyChanged('order', updateGettingUrlParams); + model.onPropertyChanged('needTotalCount', updateGettingUrlParams); - contextMenu = builder.buildType('ContextMenu', { - "Items": metadata.ContextMenu.Items - }, argumentForBuilder); + this.updateGettingUrlParams(); + this.updateSettingUrlParams(); + this.updateDeletingUrlParams(); + }, - element.setContextMenu(contextMenu); - exchange.send(messageTypes.onContextMenu.name, { source: element, content: contextMenu.render() }); - }, + updateGettingUrlParams: function(){ + var model = this.get('model'), + params = { + method: 'get', + origin: InfinniUI.config.serverUrl, + path: '/documents/' + this.get('model').getProperty('documentId'), + data: {}, + params: {} + }, + filter = model.getProperty('filter'), + filterParams = model.getProperty('filterParams'), + pageNumber = model.getProperty('pageNumber'), + pageSize = model.getProperty('pageSize'), + searchStr = model.getProperty('search'), + select = model.getProperty('select'), + order = model.getProperty('order'), + needTotalCount = model.getProperty('needTotalCount'); - lowerFirstSymbol: function(s){ - return s[0].toLowerCase() + s.substr(1); - } + if(filter){ + params.data.filter = filter; + if(filterParams){ + _.extend(params.params, filterParams); + } + } -}); + if(pageSize){ + pageNumber = pageNumber || 0; + params.data.skip = pageNumber*pageSize; + params.data.take = pageSize; + } -window.InfinniUI.ElementBuilder = ElementBuilder; + if(searchStr){ + params.data.search = searchStr; + } -//####app/elements/_base/_mixins/builderValuePropertyMixin.js -var builderValuePropertyMixin = { + if(select){ + params.data.select = select; + } - /** - * @param {Object} params - * @param {Boolean|false} useValidation Использовать валидацию - * @returns {*} - */ - initValueProperty: function (params, useValidation) { - var metadata = params.metadata; + if(order){ + params.data.order = order; + } - if (typeof useValidation === 'undefined') { - useValidation = false; + if(needTotalCount){ + params.data.count = needTotalCount; } - if (metadata.Value !== undefined) { - var dataBinding = params.builder.build(params.view, metadata.Value, params.collectionProperty); + this.setGettingUrlParams(params); + }, - dataBinding.setElement(params.element); + updateSettingUrlParams: function(){ + var model = this.get('model'), + params = { + method: 'post', + origin: InfinniUI.config.serverUrl, + path: '/documents/' + this.get('model').getProperty('documentId'), + data: {}, + params: {} + }; + + this.setSettingUrlParams(params); + }, + + updateDeletingUrlParams: function(){ + var model = this.get('model'), + params = { + method: 'delete', + origin: InfinniUI.config.serverUrl, + path: '/documents/' + this.get('model').getProperty('documentId') + '/<%id%>', + data: {}, + params: {} + }; - if (dataBinding != null) { - dataBinding.onPropertyValueChanged(function (dataSourceName, value) { - params.element.setValue(dataBinding.getPropertyValue()); - }); + this.setDeletingUrlParams(params); + }, - var data = dataBinding.getPropertyValue(); - if (data !== null && typeof data !== 'undefined') { - params.element.setValue(data); - } + initDataProvider: function(){ + var dataProvider = window.InfinniUI.providerRegister.build('DocumentDataSource'); - params.element.onValueChanged(function (dataSourceName, value) { - dataBinding.setPropertyValue(value); - }); - } + this.set('dataProvider', dataProvider); + }, + getDocumentId: function(){ + return this.get('model').getProperty('documentId'); + }, - if (useValidation && dataBinding) { - params.element.onLostFocus(function () { - dataBinding.validate(); - }); - } + setDocumentId: function(documentId){ + this.get('model').setProperty('documentId', documentId); + }, - return dataBinding; - } - } + getFilter: function(){ + return this.get('model').getProperty('filter'); + }, -}; -//####app/elements/_base/_mixins/buttonBuilderMixin.js -var buttonBuilderMixin = { - applyButtonMetadata: function(params){ - var element = params.element; - var metadata = params.metadata; - var builder = params.builder; + setFilter: function(filter){ + this.get('model').setProperty('filter', filter); + }, - this.initTemplatingContent(params); + getFilterParams: function(propertyName){ + if(arguments.length == 0){ + propertyName = 'filterParams'; - if (metadata.Action) { - var args = { - parentView: params.parentView, - parent: element, - basePathOfProperty: params.basePathOfProperty - }; - var action = builder.build(metadata.Action, args); - element.onClick(function(){ - action.execute(); - }); + }else{ + if(propertyName == ''){ + propertyName = 'filterParams'; + }else{ + propertyName = 'filterParams.' + propertyName; + } } + + return this.get('model').getProperty(propertyName); }, - initTemplatingContent: function(params){ - var element = params.element; - var metadata = params.metadata; - var builder = params.builder; - var contentTemplate, contentBinding; + setFilterParams: function(propertyName, value){ + if(arguments.length == 1){ + value = propertyName; + propertyName = 'filterParams'; - if('ContentTemplate' in metadata){ - contentTemplate = this.buildContentTemplate(metadata['ContentTemplate'], params); - element.setContentTemplate(contentTemplate); + }else{ + if(propertyName == ''){ + propertyName = 'filterParams'; + }else{ + propertyName = 'filterParams.' + propertyName; + } } - if('Content' in metadata){ - contentBinding = builder.buildBinding(metadata['Content'], { - parentView: params.parentView, - basePathOfProperty: params.basePathOfProperty - }); - - contentBinding.bindElement(element, 'content'); - } + this.get('model').setProperty(propertyName, value); }, - buildContentTemplate: function (templateMetadata, params) { - var element = params.element; - var builder = params.builder; - var basePathOfProperty = params.basePathOfProperty; - - return function(context, args) { - var argumentForBuilder = { - parent: params.element, - parentView: params.parentView, - basePathOfProperty: basePathOfProperty - }; - - return builder.build(templateMetadata, argumentForBuilder); - }; - } -}; -//####app/elements/_base/_mixins/buttonMixin.js -var buttonMixin = { + setIdFilter: function (itemId) { + this.setFilter('eq(' + this.getIdProperty() + ','+ this.quoteValue(itemId) + ')'); + }, - buttonInit: function () { - this.isFirstAction = true; + getPageNumber: function(){ + return this.get('model').getProperty('pageNumber'); }, - getContent: function () { - return this.control.get('content'); + setPageNumber: function(pageNumber){ + this.get('model').setProperty('pageNumber', pageNumber); }, - setContent: function (value) { - this.control.set('content', value); + getPageSize: function(){ + return this.get('model').getProperty('pageSize'); }, - getContentTemplate: function () { - return this.control.get('contentTemplate'); + setPageSize: function(pageSize){ + this.get('model').setProperty('pageSize', pageSize); }, - setContentTemplate: function (value) { - this.control.set('contentTemplate', value); + getSearch: function(){ + return this.get('model').getProperty('search'); }, - setAction: function (value) { - var control = this.control; + setSearch: function(searchStr){ + this.get('model').setProperty('search', searchStr); + }, - control.set('action', value); + getSelect: function(){ + return this.get('model').getProperty('select'); + }, - if (this.isFirstAction) { - this.isFirstAction = false; + setSelect: function(selectStr){ + this.get('model').setProperty('select', selectStr); + }, - this.onClick(function () { - var action = control.get('action'); + getOrder: function(){ + return this.get('model').getProperty('order'); + }, - if (action ) { - action.execute(); - } - }); - } + setOrder: function(orderConditionStr){ + this.get('model').setProperty('order', orderConditionStr); }, - getAction: function () { - return this.control.get('action'); + getTotalCount: function(){ + return this.get('model').getProperty('totalCount'); }, - click: function () { - this.control.click(); + getNeedTotalCount: function(){ + return this.get('model').getProperty('needTotalCount'); }, - onClick: function(handler){ - var that = this; + setNeedTotalCount: function(needTotalCount){ + this.get('model').setProperty('needTotalCount', needTotalCount); + }, - Element.prototype.onClick.call(this, onClickHandlerWrap); + beforeDeleteItem: function(item){ + var itemId = this.idOfItem(item); + if(itemId !== undefined){ + this.setDeletingUrlParams('params.id', itemId); + } + }, - function onClickHandlerWrap(args){ - var enabled = that.getEnabled(); + quoteValue: function (value) { + var VALUE_QUOTE_CHAR = '\''; - if(enabled){ - handler(args); - } + if (_.isString(value)) { + return VALUE_QUOTE_CHAR + value + VALUE_QUOTE_CHAR; + } else { + return value } } -}; -//####app/elements/_base/_mixins/displayFormatBuilderMixin.js +}); + +window.InfinniUI.DocumentDataSource = DocumentDataSource; + +//####app/data/dataSource/baseDataSourceBuilder.js /** - * @mixin + * @constructor + * @mixes DataSourceValidationNotifierMixin */ -var displayFormatBuilderMixin = { - - /** - * Возвращает функцию форматирования значения - * @see {@link http://docs.infinnity.ru/docs/Specifications/UserInterface/Components/TextEditorBase/TextEditorBase.setDisplayFormat/} - * @param {String} displayFormat - * @param {Object} params - * @param {ApplicationBuilder} params.builder - * @returns {Function} - */ - buildDisplayFormat: function (displayFormat, params) { - var formatOptions = params.formatOptions; - var builder = params.builder; - var formatter, format = defaultFormat; - if (typeof displayFormat === 'string') { - formatter = builder.buildType('ObjectFormat', {Format: displayFormat}); - format = function (context, args){ - args = args || {}; - return formatter.format(args.value); - } - } else if (displayFormat && typeof displayFormat === 'object') { - formatter = builder.build(displayFormat); +var BaseDataSourceBuilder = function() { +}; - format = function (context, args){ - args = args || {}; - return formatter.format(args.value); - } - } +_.extend(BaseDataSourceBuilder.prototype, /** @lends BaseDataSourceBuilder.prototype */ { + build: function (context, args) { + var dataSource = this.createDataSource(args.parentView); + dataSource.suspendUpdate('tuningInSourceBuilder'); - if (formatter) { - formatter.setOptions(formatOptions); - } + this.applyMetadata(args.builder, args.parentView, args.metadata, dataSource); - return format; + this.applySuspended(dataSource, args.suspended); - function defaultFormat(context, args) { - args = args || {}; - return args.value; - } - } -}; + dataSource.resumeUpdate('tuningInSourceBuilder'); -//####app/elements/_base/_mixins/labelTextElementMixin.js -var labelTextElementMixin = { - getLabelText: function () { - return this.control.get('labelText'); + return dataSource; }, - setLabelText: function (value) { - this.control.set('labelText', value); - } -}; -//####app/elements/_base/_mixins/routerServiceMixin.js -var routerServiceMixin = { - - replaceParamsInHref: function(oldHref, param, newValue, hrefPattern) { - if( hrefPattern ) { - var newHref = hrefPattern.split('?')[0], - query = hrefPattern.split('?')[1], - tmpArr = newHref.split('/'), - index = tmpArr.indexOf(':' + param); - - if( index === -1 ) { - throw new Error('Different param names in metadata and InfinniUI.config.Routes'); - } - tmpArr = oldHref.split('/'); - tmpArr[index] = newValue; - tmpArr = tmpArr.join('/'); - if( query ) { - tmpArr += '?' + query; - } - return tmpArr; - } else { - return oldHref.replace(':' + param, newValue); - } - }, - replaceParamsInQuery: function(oldHref, queryParam, newValue, queryPattern) { - if( queryPattern ) { - var newHref = oldHref.split('?')[0], - query = oldHref.split('?')[1], - queryTmp = queryPattern.split('?')[1], - tmpArr = queryTmp.split('&'), - index = -1; + applySuspended: function (dataSource, suspended) { + if (!suspended) { + return; + } - for(var i = 0, ii = tmpArr.length; i < ii; i += 1) { - if( tmpArr[i].indexOf(':' + queryParam) !== -1 ) { - index = i; - } - } + for (var name in suspended) { + if (!suspended.hasOwnProperty(name) || dataSource.getName() !== name) { + continue; + } - if( index === -1 ) { - throw new Error('Different query names in metadata and InfinniUI.config.Routes'); - } - tmpArr = query.split('&'); - var tmpValue = tmpArr[index].split('='); - tmpValue[1] = newValue; - tmpArr[index] = tmpValue.join('='); - var finalString = newHref + '?' + tmpArr.join('&'); - return finalString; - } else { - return oldHref.replace(':' + queryParam, newValue); - } - }, + dataSource.suspendUpdate(suspended[name]); + } - bindParams: function(params, paramName, paramValue, hrefPattern) { - var element = params.element, - builder = params.builder, - that = this, - args = { - parent: params.parent, - parentView: params.parentView, - basePathOfProperty: params.basePathOfProperty - }; + }, - var dataBinding = params.builder.buildBinding(paramValue, args); + applyMetadata: function (builder, parentView, metadata, dataSource) { + var idProperty = metadata.IdProperty; + if (idProperty) { + dataSource.setIdProperty(idProperty); + } - dataBinding.bindElement({ - onPropertyChanged: function() {}, - setProperty: function(elementProperty, newValue) { - var oldHref = element.getHref(), - newHref = that.replaceParamsInHref(oldHref, paramName, newValue, hrefPattern); - element.setHref(newHref); - }, - getProperty: function() {} - }, ''); - }, + if( 'SuspendUpdate' in metadata ) { + dataSource.suspendUpdate( metadata['SuspendUpdate'] ); + } - bindQuery: function(params, queryName, queryValue, queryPattern) { - var element = params.element, - builder = params.builder, - that = this, - args = { - parent: params.parent, - parentView: params.parentView, - basePathOfProperty: params.basePathOfProperty - }; + dataSource.setName(metadata.Name); + dataSource.setFillCreatedItem(metadata.FillCreatedItem); - var dataBinding = params.builder.buildBinding(queryValue, args); + if('IsLazy' in metadata){ + dataSource.setIsLazy(metadata['IsLazy']); + } - dataBinding.bindElement({ - onPropertyChanged: function() {}, - setProperty: function(elementProperty, newValue) { - var oldHref = element.getHref(), - newHref = that.replaceParamsInQuery(oldHref, queryName, newValue, queryPattern); - element.setHref(newHref); - }, - getProperty: function() {} - }, ''); - } -}; + if('ResolvePriority' in metadata){ + dataSource.setResolvePriority(metadata['ResolvePriority']); + } -//####app/elements/_base/_mixins/valuePropertyMixin.js -var valuePropertyMixin = { + if( _.isObject(metadata.CustomProperties) ) { + this.initCustomProperties(dataSource, metadata.CustomProperties); + } - getValue: function(){ - return this.control.get('value'); - }, + this.initValidation(parentView, dataSource, metadata); + this.initNotifyValidation(dataSource); + this.initScriptsHandlers(parentView, metadata, dataSource); - setValue: function(value){ - return this.control.set('value', value); + this.initFileProvider(dataSource); }, - onValueChanged: function(handler){ - this.control.onValueChanged(handler); - } + createDataSource: function (parent) { + throw 'BaseDataSourceBuilder.createDataSource В потомке BaseDataSourceBuilder не переопределен метод createDataSource.'; + }, -}; -//####app/elements/_base/_mixins/veiwBuilderHeaderTemplateMixin.js -var viewBuilderHeaderTemplateMixin = { + initCustomProperties: function(dataSource, customProperties){ + _.each(customProperties, function(value, key){ + dataSource.setProperty('.' + key, value); + }); + }, /** * @protected - * @param params + * @description Инициализация обработчиков для валидации данных + * @param parentView + * @param dataSource + * @param metadata */ - buildHeaderTemplate: function (view, params) { - var - builder = params.builder, - metadata = params.metadata, - headerTemplate; - - if (metadata.HeaderTemplate) { - //@TODO Build header template by metadata - headerTemplate = function (context, args) { - var - paramsForBuilder = { - parent: view, - parentView: view, - basePathOfProperty: params.basePathOfProperty - }; - - return builder.build(metadata.HeaderTemplate, paramsForBuilder); - } - } else { - //@TODO Build header template by default - headerTemplate = function (context, args) { - var - label = new Label(); - - label.setValue(view.getText()); - view.onPropertyChanged("text", function (context, args) { - label.setValue(args.newValue); - }); - - return label; - } + initValidation: function (parentView, dataSource, metadata) { + if (metadata.ValidationErrors) { + dataSource.setErrorValidator(function (context, args) { + return new ScriptExecutor(parentView).executeScript(metadata.ValidationErrors.Name || metadata.ValidationErrors, args); + }); } - return headerTemplate; - } + }, -}; + //Скриптовые обработчики на события + initScriptsHandlers: function (parentView, metadata, dataSource) { -//####app/elements/_base/container/container.js -/** - * @param parent - * @constructor - * @augments Element - */ -function Container(parent, viewMode) { - _.superClass(Container, this, parent, viewMode); -} + if( !parentView ){ + return; + } -window.InfinniUI.Container = Container; + if (metadata.OnSelectedItemChanged) { + dataSource.onSelectedItemChanged(function (context, args) { + new ScriptExecutor(parentView).executeScript(metadata.OnSelectedItemChanged.Name || metadata.OnSelectedItemChanged, args); + }); + } -_.inherit(Container, Element); + if (metadata.OnItemsUpdated) { + dataSource.onItemsUpdated(function (context, args) { + new ScriptExecutor(parentView).executeScript(metadata.OnItemsUpdated.Name || metadata.OnItemsUpdated, args); + }); + } -Container.prototype.getItemTemplate = function () { - return this.control.get('itemTemplate'); -}; + if (metadata.OnPropertyChanged) { + dataSource.onPropertyChanged(function (context, args) { + new ScriptExecutor(parentView).executeScript(metadata.OnPropertyChanged.Name || metadata.OnPropertyChanged, args); + }); + } -Container.prototype.setItemTemplate = function (itemTemplate) { - if (typeof itemTemplate !== 'function') { - throw new Error('Function expected'); - } - this.control.set('itemTemplate', itemTemplate); -}; + if (metadata.OnItemDeleted) { + dataSource.onItemDeleted(function () { + new ScriptExecutor(parentView).executeScript(metadata.OnItemDeleted.Name || metadata.OnItemDeleted); + }); + } -Container.prototype.getItems = function () { - return this.control.get('items'); -}; + if (metadata.OnErrorValidator) { + dataSource.onErrorValidator(function () { + new ScriptExecutor(parentView).executeScript(metadata.OnErrorValidator.Name || metadata.OnErrorValidator); + }); + } + }, -Container.prototype.getGroupValueSelector = function () { - return this.control.get('groupValueSelector'); -}; + buildBindingBuilder: function(params){ -Container.prototype.setGroupValueSelector = function (value) { - this.control.set('groupValueSelector', value); -}; + return function(bindingMetadata){ + return params.builder.buildBinding(bindingMetadata, { + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }); + }; + }, -Container.prototype.getGroupItemTemplate = function () { - return this.control.get('groupItemTemplate'); -}; + initFileProvider: function (dataSource) { -Container.prototype.setGroupItemTemplate = function (value) { - this.control.set('groupItemTemplate', value); -}; + var host = InfinniUI.config.serverUrl; -Container.prototype.getGroupItemComparator = function () { - return this.control.get('groupItemComparator'); -}; + var fileUrlConstructor = new DocumentUploadQueryConstructor(host); -Container.prototype.setGroupItemComparator = function (value) { - this.control.set('groupItemComparator', value); -}; + var fileProvider = new DocumentFileProvider(fileUrlConstructor); + dataSource.setFileProvider(fileProvider); + } -//####app/elements/_base/container/containerBuilder.js -function ContainerBuilder() { - _.superClass(ContainerBuilder, this); -} -window.InfinniUI.ContainerBuilder = ContainerBuilder; +}); -_.inherit(ContainerBuilder, ElementBuilder); -/** - * @abstract - */ -_.extend(ContainerBuilder.prototype, { +_.extend(BaseDataSourceBuilder.prototype, DataSourceValidationNotifierMixin); - /** - * - * @param params - * @returns {{itemsBinding: {DataBinding}}} - */ - applyMetadata: function (params) { - var metadata = params.metadata; - var element = params.element; - var itemsBinding; +window.InfinniUI.BaseDataSourceBuilder = BaseDataSourceBuilder; - ElementBuilder.prototype.applyMetadata.call(this, params); +//####app/data/dataSource/restDataSourceBuilder.js +var RestDataSourceBuilder = function() { + _.superClass(RestDataSourceBuilder, this); +} - itemsBinding = this.initItems(params); - this.initGroup(params, itemsBinding); +_.inherit(RestDataSourceBuilder, BaseDataSourceBuilder); - return { - itemsBinding: itemsBinding - }; +_.extend(RestDataSourceBuilder.prototype, { + createDataSource: function(parent){ + return new RestDataSource({ + view: parent + }); }, - initItems: function (params) { - var metadata = params.metadata; - var itemsBinding = null; + applyMetadata: function(builder, parent, metadata, dataSource){ + BaseDataSourceBuilder.prototype.applyMetadata.call(this, builder, parent, metadata, dataSource); - if (Array.isArray(metadata.Items)) { // отдельные не шаблонизируемые items, в metadata.Items - список методанных item'ов - this.initNotTemplatingItems(params); - } else if (metadata.Items) { // шаблонизируемые однотипные items, в metadata.Items - биндинг на данные item'ов - itemsBinding = this.initTemplatingItems(params); + var tmpParams; + + this.initProviderErrorHandling(dataSource); + + if('GettingParams' in metadata){ + tmpParams = this.extractUrlParams(metadata['GettingParams'], '.urlParams.get.params'); + dataSource.setGettingUrlParams(tmpParams); + this.bindParams(metadata['GettingParams'], dataSource, parent, '.urlParams.get.params', builder); } - return itemsBinding; - }, + if('SettingParams' in metadata){ + tmpParams = this.extractUrlParams(metadata['SettingParams'], '.urlParams.set.params'); + dataSource.setSettingUrlParams(tmpParams); + this.bindParams(metadata['SettingParams'], dataSource, parent, '.urlParams.set.params', builder); + } - initTemplatingItems: function (params) { - var metadata = params.metadata; - var element = params.element; - var itemTemplate; - var binding; - var property; + if('DeletingParams' in metadata){ + tmpParams = this.extractUrlParams(metadata['DeletingParams'], '.urlParams.delet.params'); + dataSource.setDeletingUrlParams(tmpParams); + this.bindParams(metadata['DeletingParams'], dataSource, parent, '.urlParams.delet.params', builder); + } - binding = params.builder.buildBinding(metadata.Items, { - parentView: params.parentView, - basePathOfProperty: params.basePathOfProperty - }); + if('UpdatingItemsConverter' in metadata){ + dataSource.setUpdatingItemsConverter(function (items) { + return new ScriptExecutor(parent).executeScript(metadata['UpdatingItemsConverter'].Name || metadata['UpdatingItemsConverter'], { value: items, source: dataSource }); + }); + } - binding.setMode(InfinniUI.BindingModes.toElement); + }, - //if ('ItemComparator' in metadata) { - this.bindElementItemsWithSorting(binding, params); - //} else { - // binding.bindElement(element, 'items'); - //} + extractUrlParams: function(urlParamsMetadata, pathForBinding){ + var result = {}; + if('Origin' in urlParamsMetadata){ + result.origin = urlParamsMetadata['Origin']; + }else{ + result.origin = InfinniUI.config.serverUrl; + } - if ('ItemTemplate' in metadata) { - itemTemplate = this.buildItemTemplate(metadata.ItemTemplate, params); - } else if ('ItemFormat' in metadata) { - itemTemplate = this.buildItemFormat(binding, metadata.ItemFormat, params); - } else if ('ItemSelector' in metadata) { - itemTemplate = this.buildItemSelector(binding, metadata.ItemSelector, params); - } else { - if ('ItemProperty' in metadata) { - property = metadata.ItemProperty; - } else { - property = ''; - } - itemTemplate = this.buildItemProperty(binding, property, params); + if('Path' in urlParamsMetadata){ + result.path = urlParamsMetadata['Path']; } - element.setItemTemplate(itemTemplate); + if('Data' in urlParamsMetadata){ + result.data = urlParamsMetadata['Data']; + } - return binding; - }, + if('Method' in urlParamsMetadata){ + result.method = urlParamsMetadata['Method']; + } - initNotTemplatingItems: function (params) { - var itemsMetadata = params.metadata.Items; - var element = params.element; - //var fakeItems = (new Array(itemsMetadata.length + 1)).join(' ').split(''); - var items = itemsMetadata.slice(0); - element.getItems().set(items); - var itemTemplate = this.buildItemTemplateForUniqueItem(items, params); - element.setItemTemplate(itemTemplate); + result.params = {}; + + return result; }, - tuneItemsBinding: function (itemsBinding) { - var source = itemsBinding.getSource(); - if (typeof source.tryInitData == 'function') { - source.tryInitData(); + bindParams: function(methodMetadata, dataSource, parentView, pathForBinding, builder){ + if('Params' in methodMetadata){ + var params = methodMetadata['Params']; + for(var k in params){ + this.initBindingToProperty(params[k], dataSource, parentView, pathForBinding + '.' + k, builder); + } } }, - initGroup: function (params, itemsBinding) { - if (this.hasGrouping(params)) { - this.initGroupValueSelector(params); - this.initGroupItemTemplate(params, itemsBinding); + initBindingToProperty: function (valueMetadata, dataSource, parentView, pathForBinding, builder) { + if (typeof valueMetadata != 'object') { + if (valueMetadata !== undefined) { + dataSource.setProperty(pathForBinding, valueMetadata); + } + + } else { + var args = { + parent: parentView, + parentView: parentView + }; + + var dataBinding = builder.buildBinding(valueMetadata, args); + + dataBinding.setMode(InfinniUI.BindingModes.toElement); + + dataBinding.bindElement(dataSource, pathForBinding); } }, - hasGrouping: function (params) { - return params.metadata.GroupValueSelector || params.metadata.GroupValueProperty; - }, + initProviderErrorHandling: function(dataSource){ + dataSource.onProviderError(function(){ + var exchange = window.InfinniUI.global.messageBus; + exchange.send(messageTypes.onNotifyUser, {messageText: 'Ошибка на сервере', messageType: "error"}); - initGroupValueSelector: function (params) { - var metadata = params.metadata, - element = params.element, - groupValueSelector; + }); + } +}); - /* element.setGroupItemComparator(function(a, b) { - if (a < b) { - return -1; - } +window.InfinniUI.RestDataSourceBuilder = RestDataSourceBuilder; - if (a > b) { - return 1; - } +//####app/data/dataSource/documentDataSourceBuilder.js +var DocumentDataSourceBuilder = function() { + _.superClass(DocumentDataSourceBuilder, this); +}; - return 0; - });*/ +_.inherit(DocumentDataSourceBuilder, BaseDataSourceBuilder); - if (metadata.GroupValueSelector) { - groupValueSelector = function (context, args) { - var scriptExecutor = new ScriptExecutor(element.getScriptsStorage()); - return scriptExecutor.executeScript(metadata.GroupValueSelector.Name || metadata.GroupValueSelector, args) - }; - } else if (metadata.GroupValueProperty) { - groupValueSelector = function (context, args) { - return InfinniUI.ObjectUtils.getPropertyValue(args.value, metadata.GroupValueProperty); - } - } else { - //Без группировки - groupValueSelector = null - } - element.setGroupValueSelector(groupValueSelector); - }, +_.extend(DocumentDataSourceBuilder.prototype, { + applyMetadata: function(builder, parent, metadata, dataSource){ + BaseDataSourceBuilder.prototype.applyMetadata.call(this, builder, parent, metadata, dataSource); - initGroupItemTemplate: function (params, itemsBinding) { - var metadata = params.metadata; - var element = params.element; - var itemTemplate; - var property; + dataSource.setDocumentId(metadata['DocumentId']); - if (metadata.GroupItemTemplate) { - itemTemplate = this.buildItemTemplate(metadata.GroupItemTemplate, params); - } else if (metadata.GroupItemFormat) { - itemTemplate = this.buildItemFormat(itemsBinding, metadata.GroupItemFormat, params); - } else if (metadata.GroupItemSelector) { - itemTemplate = this.buildItemSelector(itemsBinding, metadata.GroupItemSelector, params); - } else if (metadata.GroupItemProperty) { - itemTemplate = this.buildItemProperty(itemsBinding, metadata.GroupItemProperty, params); - } + if('PageNumber' in metadata){ dataSource.setPageNumber(metadata['PageNumber']); } + if('PageSize' in metadata){ dataSource.setPageSize(metadata['PageSize']); } - if (itemTemplate) { - element.setGroupItemTemplate(itemTemplate); + if('Filter' in metadata){ dataSource.setFilter(metadata['Filter']); } + if('FilterParams' in metadata){ + var params = metadata['FilterParams']; + for(var k in params){ + this.initBindingToProperty(params[k], dataSource, parent, '.filterParams.' + k, builder); + } } + + if('Search' in metadata){ dataSource.setSearch(metadata['Search']); } + if('Select' in metadata){ dataSource.setSelect(metadata['Select']); } + if('Order' in metadata){ dataSource.setOrder(metadata['Order']); } + if('NeedTotalCount' in metadata){ dataSource.setNeedTotalCount(metadata['NeedTotalCount']); } }, - buildItemProperty: function (itemsBinding, itemPropertyMetadata, params) { + createDataSource: function(parent){ + return new DocumentDataSource({ + view: parent + }); + }, - return function (context, args) { - var index = args.index; - var label = new Label(this); - var sourceProperty; - var source = itemsBinding.getSource(); - var binding = new DataBinding(); + initBindingToProperty: RestDataSourceBuilder.prototype.initBindingToProperty +}); - sourceProperty = index.toString(); - if (itemsBinding.getSourceProperty() != '') { - sourceProperty = itemsBinding.getSourceProperty() + '.' + sourceProperty; - } - if (itemPropertyMetadata != '') { - sourceProperty = sourceProperty + '.' + itemPropertyMetadata; - } +window.InfinniUI.DocumentDataSourceBuilder = DocumentDataSourceBuilder; - binding.bindSource(source, sourceProperty); - binding.bindElement(label, 'value'); +//####app/elements/_base/element/element.js +var Element = function (parent, viewMode) { + this.parent = parent; + this.control = this.createControl(viewMode); + this.state = { + Enabled: true + }; - return label; - }; - }, + this.childElements = []; +}; + +Object.defineProperties(Element.prototype, { + name: { + get: function () { + return this.getName() + } + } +}); - buildItemFormat: function (itemsBinding, itemFormatMetadata, params) { +_.extend(Element.prototype, { - var format = this.buildDisplayFormat(itemFormatMetadata, params); - return function (context, args) { - var index = args.index; - var label = new Label(this); + createControl: function (viewMode) { + throw ('Не перегружен абстрактный метод Element.createControl'); + }, - var sourceProperty = itemsBinding.getSourceProperty(); - var source = itemsBinding.getSource(); - var binding = new DataBinding(); + setParent: function (parentElement) { + this.parent = parentElement; + }, - sourceProperty = index.toString(); - if (itemsBinding.getSourceProperty() != '') { - sourceProperty = itemsBinding.getSourceProperty() + '.' + sourceProperty; - } + getParent: function () { + return this.parent; + }, - label.setDisplayFormat(format); + getChildElements: function () { + return this.childElements; + }, - binding.bindSource(source, sourceProperty); - binding.bindElement(label, 'value'); + findAllChildrenByType: function (type) { + return this._findAllChildren(predicate, getChildElements); - return label; - }; + function predicate() { + return this.constructor.name === type; + } + function getChildElements(element) { + return element.findAllChildrenByType(type); + } }, - buildItemSelector: function (itemsBinding, itemSelectorMetadata, params) { + findAllChildrenByName: function (name) { + return this._findAllChildren(predicate, getChildElements); - return function (context, args) { - var index = args.index; - var label = new Label(this); - var scriptExecutor = new ScriptExecutor(params.parentView); + function predicate () { + return this.getName() === name; + } - var sourceProperty = itemsBinding.getSourceProperty(); - var source = itemsBinding.getSource(); - var binding = new DataBinding(); - binding.setMode(InfinniUI.BindingModes.toElement); + function getChildElements (element) { + return element.findAllChildrenByName(name); + } - sourceProperty = index.toString(); - if (itemsBinding.getSourceProperty() != '') { - sourceProperty = itemsBinding.getSourceProperty() + '.' + sourceProperty; - } + }, - binding.setConverter({ - toElement: function (_context, _args) { - return scriptExecutor.executeScript(itemSelectorMetadata.Name || itemSelectorMetadata, _args); + _findAllChildren: function (predicate, getChildElements) { + var elements = this.getChildElements(); + var items = []; + if (Array.isArray(elements)) { + elements.forEach(function (element) { + if (predicate.call(element)) { + items.push(element); } + Array.prototype.push.apply(items, getChildElements(element)); }); - - binding.bindSource(source, sourceProperty); - binding.bindElement(label, 'value'); - - return label; } - }, - - buildItemTemplate: function (templateMetadata, params) { - var element = params.element; - var builder = params.builder; - var basePathOfProperty = params.basePathOfProperty || new BasePathOfProperty(''); - var propertyForSource = params.metadata['Items']['Property'] || ''; - var that = this; - return function (context, args) { - var index = args.index; - var bindingIndex; - var argumentForBuilder = { - parent: params.element, - parentView: params.parentView - }; + return items; + }, - if (index !== undefined && index !== null) { - bindingIndex = that.bindingIndexByItemsIndex(index, params); + getView: function () { + if (!this.parentView) { + if (this.parent && this.parent.isView) { + this.parentView = this.parent; - if (bindingIndex !== undefined && bindingIndex !== null) { - argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild(propertyForSource, bindingIndex); + } else { + if (this.parent && this.parent.getView) { + this.parentView = this.parent.getView(); } else { - argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild(propertyForSource, index); + this.parentView = null; } } + } - return builder.build(templateMetadata, argumentForBuilder); - }; + return this.parentView; }, - /** - * @public - * @memberOf ContainerBuilder - * @description Возвращает функцию itemTemplate для не шаблонизируемого item'а. - * @param {Object} itemMetadata метаданные. - * @param {Object} params стандартные params, передаваемые внутри билдеров. - **/ - buildItemTemplateForUniqueItem: function (itemsMetadata, params) { - var element = params.element; - var builder = params.builder; - var basePathOfProperty = params.basePathOfProperty || new BasePathOfProperty(''); + getName: function () { + return this.control.get('name'); + }, - return function (context, args) { + setName: function (name) { + if(this.getName()){ + throw 'name already exists'; + } - var - index = args.index, - item = element.getItems().getByIndex(index), - argumentForBuilder = { - parent: params.element, - parentView: params.parentView, - basePathOfProperty: basePathOfProperty - }; + if (typeof name == 'string') { + this.control.set('name', name); + } + }, - return builder.build(item, argumentForBuilder); - }; + getProperty: function (name) { + var getterMethodName = 'get' + this._upperFirstSymbol(name); + if (typeof this[getterMethodName] == 'function') { + return this[getterMethodName](); + } else { + throw 'expect that ' + getterMethodName + ' is getter function'; + } }, - bindingIndexByItemsIndex: function (index, params) { - var element = params.element, - items = element.getItems(); + setProperty: function (name, value) { + var setterMethodName = 'set' + this._upperFirstSymbol(name), + getterMethodName; - return items.getProperty(index, 'bindingIndex'); + if (typeof this[setterMethodName] == 'function') { + this[setterMethodName](value); + } else { + if (this._isCollectionProperty(name)) { + getterMethodName = 'get' + this._upperFirstSymbol(name); + this[getterMethodName]().set(value); + } else { + throw 'expect that ' + setterMethodName + ' is setter function'; + } + } }, - bindElementItemsWithSorting: function (binding, params) { - // нетривиальный биндинг элементов нужен для того, чтобы правильно учитывались индексы при сортировке элементов - - var metadata = params.metadata, - element = params.element, - scriptExecutor = new ScriptExecutor(params.parent), - itemComparator; + _isCollectionProperty: function (propertyName) { + var getterMethodName = 'get' + this._upperFirstSymbol(propertyName); + return (typeof this[getterMethodName] == 'function') && this[getterMethodName]() instanceof Collection; + }, - if(metadata.ItemComparator){ - itemComparator = function (item1, item2) { - return scriptExecutor.executeScript(metadata.ItemComparator.Name || metadata.ItemComparator, {item1: item1, item2: item2}); - }; + onPropertyChanged: function (propertyName, handler) { + var subscribingMethodName = 'on' + this._upperFirstSymbol(propertyName) + 'Changed'; + if (typeof this[subscribingMethodName] == 'function') { + this[subscribingMethodName](handler); + } else { + this.control.on('change:' + propertyName, function (model, value) { + var parentView = this.getView(), + context = parentView ? parentView.getContext() : undefined, + args = { + property: propertyName, + oldValue: model.previous(propertyName), + newValue: value + }; + handler(context, args); + }.bind(this)); } + }, - var source = binding.getSource(); - source.onPropertyChanged('*', function (context, args) { - var items = element.getItems(); - //При замене целого элемента списка, заменить элемент в коллекции - if (args.property && args.property.match(/^\d+$/)) { - items.replace(args.oldValue, args.newValue); - } - }); - - binding.bindElement({ - setProperty: function (name, value) { - var items = element.getItems(), - isCollectionChanged; + getText: function () { + return this.control.get('text'); + }, - if(itemComparator){ + setText: function (text) { + if (typeof text !== 'undefined') { + this.control.set('text', text); + } + }, - isCollectionChanged = items.set(value, true); + getEnabled: function () { + return this.control.get('enabled'); + }, - items.forEach(function (item, index, collection) { - collection.setProperty(index, 'bindingIndex', index); - }); + setEnabled: function (isEnabled) { + if (typeof isEnabled !== 'boolean') { + return; + } - if (isCollectionChanged) { - items.sort(itemComparator); - } + this.setState('Enabled', isEnabled); - }else{ + var parentEnabled = this.control.get('parentEnabled'); + var old = this.control.get('enabled'); - isCollectionChanged = items.set(value); + isEnabled = parentEnabled && isEnabled; - items.forEach(function (item, index, collection) { - collection.setProperty(index, 'bindingIndex', index); - }); - } + if (isEnabled === old) { + return; + } - }, + this.control.set('enabled', isEnabled); + this.setParentEnabledOnChild(isEnabled); + }, - onPropertyChanged: function () { + setParentEnabledOnChild: function (value) { + var elements = this.getChildElements(); + if (_.isEmpty(elements) === false) { + for (var i = 0, ln = elements.length; i < ln; i = i + 1) { + if (typeof elements[i].setParentEnabled === 'undefined') { + continue; + } + elements[i].setParentEnabled(value); } + } + }, - }, 'items'); - } - -}, displayFormatBuilderMixin); + setParentEnabled: function (value) { + if (typeof value !== 'boolean') { + return; + } -//####app/elements/_base/editorBase/editorBaseBuilderMixin.js -var editorBaseBuilderMixin = { - initialize_editorBaseBuilder: function () { + var old = this.control.get('parentEnabled'); + this.control.set('parentEnabled', value); + if (old !== value) { + var enabled = value && this.getState('Enabled'); + this.control.set('enabled', enabled); + this.setParentEnabled(enabled); + this.setParentEnabledOnChild(enabled); + } }, - /** - * - * @param params - * @param {Object} [bindingOptions - * @param {Function} [bindingOptions.converter] Конвертер - * @param {string} [bindingOptions.valueProperty="value'] Имя атрибута значения - * @returns {*} - */ + getVisible: function () { + return this.control.get('visible'); + }, + setVisible: function (isVisible) { + if (typeof isVisible == 'boolean') { + this.control.set('visible', isVisible); + } + }, - /** - * - * @param params - * @param bindingOptions - * @returns {{valueBinding: {DataBinding}}} - */ - applyMetadata_editorBaseBuilder: function (params, bindingOptions) { - var metadata = params.metadata; - var element = params.element; + getStyle: function () { + return this.control.get('style'); + }, - bindingOptions = bindingOptions || {}; - bindingOptions.valueProperty = bindingOptions.valueProperty || 'value'; + setStyle: function (style) { + if (typeof style == 'string') { + this.control.set('style', style); + } + }, - element.setLabelFloating(metadata.LabelFloating); - element.setHintText(metadata.HintText); - element.setErrorText(metadata.ErrorText); - element.setWarningText(metadata.WarningText); + getTextHorizontalAlignment: function () { + return this.control.get('textHorizontalAlignment'); + }, - if (metadata.OnValueChanging) { - element.onValueChanging(function (context, args) { - var scriptExecutor = new ScriptExecutor(params.parentView); - return scriptExecutor.executeScript(metadata.OnValueChanging.Name || metadata.OnValueChanging, args); - }); - } - if (metadata.OnValueChanged) { - element.onValueChanged(function (context, args) { - new ScriptExecutor(params.parentView).executeScript(metadata.OnValueChanged.Name || metadata.OnValueChanged, args); - }); + setTextHorizontalAlignment: function (value) { + if (InfinniUI.Metadata.isValidValue(value, InfinniUI.TextHorizontalAlignment)) { + this.control.set('textHorizontalAlignment', value); } + }, - if (metadata.Value !== undefined) { - if (InfinniUI.Metadata.isBindingMetadata(metadata.Value)) { - var buildParams = { - parentView: params.parentView, - basePathOfProperty: params.basePathOfProperty - }; + getHorizontalAlignment: function () { + return this.control.get('horizontalAlignment'); + }, - var dataBinding = params.builder.buildBinding(metadata.Value, buildParams); - var mergedConverter = mergeConverters(dataBinding.getConverter(), bindingOptions.converter); + setHorizontalAlignment: function (horizontalAlignment) { + if (typeof horizontalAlignment == 'string') { + this.control.set('horizontalAlignment', horizontalAlignment); + } + }, - if (mergedConverter) { - dataBinding.setConverter(mergedConverter); - } - if (bindingOptions.mode) { - dataBinding.setMode(bindingOptions.mode); - } - dataBinding.bindElement(params.element, bindingOptions.valueProperty); + getVerticalAlignment: function () { + return this.control.get('verticalAlignment'); + }, - this.initValidationResultText(element, dataBinding); + setVerticalAlignment: function (verticalAlignment) { + if (typeof verticalAlignment == 'string') { + this.control.set('verticalAlignment', verticalAlignment); + } + }, - } else { - params.element.setValue(metadata.Value); - } + getTextStyle: function () { + return this.control.get('textStyle'); + }, + + setTextStyle: function (textStyle) { + if (typeof textStyle == 'string') { + this.control.set('textStyle', textStyle); } + }, - function mergeConverters(topPriority, nonPriority) { - topPriority = topPriority || {}; - nonPriority = nonPriority || {}; + getBackground: function () { + return this.control.get('background'); + }, - if(!topPriority.toElement && nonPriority.toElement) { - topPriority.toElement = nonPriority.toElement; - } + setBackground: function (background) { + if (typeof background == 'string') { + this.control.set('background', background); + } + }, - if(!topPriority.toSource && nonPriority.toSource) { - topPriority.toSource = nonPriority.toSource; - } + getForeground: function () { + return this.control.get('foreground'); + }, - return !_.isEmpty(topPriority) ? topPriority : null; + setForeground: function (foreground) { + if (typeof foreground == 'string') { + this.control.set('foreground', foreground); } + }, - return { - valueBinding: dataBinding - }; + onLoaded: function (handler) { + this.control.onLoaded(handler); }, - /** - * @description Инициализация подписки на события валидации для оповещения элемента - * @param binding - */ - initValidationResultText: function (element, binding) { - var source = binding.getSource(); - var property = binding.getSourceProperty(); + isLoaded: function () { + return this.control.isLoaded(); + }, - if (typeof source.onErrorValidator == 'function') { - source.onErrorValidator(function (context, args) { - var result = args.value, - text = ''; + getFocusable: function () { + return this.control.get('focusable') + }, - if (!result.isValid && Array.isArray(result.items)) { - text = getTextForItems(result.items); - } - element.setErrorText(text); - }); + setFocusable: function (value) { + if (_.isBoolean(value)) { + this.control.set('focusable', value); } + }, - if (typeof source.onWarningValidator == 'function') { - source.onWarningValidator(function (context, args) { - var result = args.value, - text = ''; + getFocused: function () { + return this.control.get('focused'); + }, - if (!result.isValid && Array.isArray(result.items)) { - text = getTextForItems(result.items); - } - element.setWarningText(text); - }); - } + setFocused: function (value) { + //Установка фокуса вручную + return this.control.setFocus(); + }, + onLostFocus: function (handler) { + this.control.on('OnLostFocus', handler); + }, + onGotFocus: function (handler) { + this.control.on('OnGotFocus', handler); + }, - function getTextForItems(items, callback) { - return items - .filter(function (item) { - return property === item.property; - }) - .map(function (item) { - return item.message; - }) - .join(' '); - } + setToolTip: function (value) { + this.control.set('toolTip', value); }, + getToolTip: function () { + return this.control.get('toolTip'); + }, -}; + setContextMenu: function(items) { + this.control.set('contextMenu', items); + }, -//####app/elements/_base/editorBase/editorBaseMixin.js -/** - * - * @mixin editorBaseMixin - */ -var editorBaseMixin = { - initialize_editorBase: function(){ + getContextMenu: function(items) { + return this.control.get('contextMenu'); + }, + getIsLoaded: function () { + return this.control.get('isLoaded'); }, - getValue: function () { - return this.control.getValue(); + setIsLoaded: function () { + this.control.set('isLoaded', true); }, - setValue: function (value) { - this.control.setValue(value); + setTag: function (value) { + this.control.set('tag', value); }, - getLabelFloating: function () { - return this.control.get('labelFloating'); + getTag: function () { + return this.control.get('tag'); }, - setLabelFloating: function (value) { - this.control.set('labelFloating', value); + render: function () { + return this.control.render(); }, - getHintText: function () { - return this.control.get('hintText'); + getWidth: function () { }, - setHintText: function (value) { - this.control.set('hintText', value); + getHeight: function () { }, - getErrorText: function () { - return this.control.get('errorText'); + getScriptsStorage: function () { + return this.getView(); }, - setErrorText: function (value) { - this.control.set('errorText', value); + /** + * Установка состояния валидации элеменат + * @param {String} [state="success"] + * @param {String} [message] + */ + setValidationState: function (state, message) { + this.control.set('validationMessage', message); + this.control.set('validationState', state); + }, + + /** + * Получение состояния валидации элеменат + * @return {String} [state="success"] + */ + getValidationState: function () { + return this.control.get('validationState'); }, - getWarningText: function () { - return this.control.get('warningText'); + getState: function (name) { + return this.state[name]; }, - setWarningText: function (value) { - this.control.set('warningText', value); + setState: function (name, value) { + this.state[name] = value; }, - - validateValue: function (value) { - + onBeforeClick: function (handler) { + return this.control.onBeforeClick(handler); }, - convertValue: function (value) { - return value; + onKeyDown: function (handler) { + var that = this, + callback = function (nativeEventData) { + var eventData = that._getHandlingKeyEventData(nativeEventData); + handler(eventData); + }; + return this.control.onKeyDown(callback); }, - onValueChanging: function (handler) { - this.control.onValueChanging( - this.createControlEventHandler(this, handler, {property: 'value'}) - ); + onKeyUp: function (handler) { + var that = this, + callback = function (nativeEventData) { + var eventData = that._getHandlingKeyEventData(nativeEventData); + handler(eventData); + }; + return this.control.onKeyUp(callback); }, - onValueChanged: function (handler) { - this.control.onValueChanged( - this.createControlEventHandler(this, handler, {property: 'value'}) - ); - } - -}; -//####app/elements/_base/listEditorBase/listEditorBase.js -function ListEditorBase(parent, viewMode) { - _.superClass(ListEditorBase, this, parent, viewMode); - - this.initialize_editorBase(); -} - -window.InfinniUI.ListEditorBase = ListEditorBase; - -_.inherit(ListEditorBase, Container); - - -_.extend(ListEditorBase.prototype, { - - getMultiSelect: function () { - return this.control.get('multiSelect'); + onClick: function (handler) { + var that = this, + callback = function (nativeEventData) { + var eventData = that._getHandlingMouseEventData(nativeEventData); + handler(eventData); + }; + return this.control.onClick(callback); }, - setMultiSelect: function (value) { - this.control.set('multiSelect', value); + onDoubleClick: function (handler) { + var that = this, + callback = function (nativeEventData) { + var eventData = that._getHandlingMouseEventData(nativeEventData); + handler(eventData); + }; + return this.control.onDoubleClick(callback); }, - getValueSelector: function () { - return this.control.get('valueSelector'); + onMouseDown: function (handler) { + var that = this, + callback = function (nativeEventData) { + var eventData = that._getHandlingMouseEventData(nativeEventData); + handler(eventData); + }; + return this.control.onMouseDown(callback); }, - setValueSelector: function (value) { - this.control.set('valueSelector', value); + onMouseUp: function (handler) { + var that = this, + callback = function (nativeEventData) { + var eventData = that._getHandlingMouseEventData(nativeEventData); + handler(eventData); + }; + return this.control.onMouseUp(callback); }, - getDisabledItemCondition: function () { - return this.control.get('disabledItemCondition'); + onMouseEnter: function (handler) { + var that = this, + callback = function (nativeEventData) { + var eventData = that._getHandlingMouseEventData(nativeEventData); + handler(eventData); + }; + return this.control.onMouseEnter(callback); }, - setDisabledItemCondition: function (value) { - this.control.set('disabledItemCondition', value); + onMouseLeave: function (handler) { + var that = this, + callback = function (nativeEventData) { + var eventData = that._getHandlingMouseEventData(nativeEventData); + handler(eventData); + }; + return this.control.onMouseLeave(callback); }, - setValueItem: function(item){ - var result; - var isMultiSelect = this.getMultiSelect(); - var valueSelector = this.getValueSelector(); - - if(isMultiSelect){ - result = []; - - for(var i = 0, ii = item.length; i < ii; i++){ - result[i] = valueSelector(null, {value: item[i]}); - } - - }else{ - result = valueSelector(null, {value: item}); - } - - this.setValue(result); + onMouseMove: function (handler) { + var that = this, + callback = function (nativeEventData) { + var eventData = that._getHandlingMouseEventData(nativeEventData); + handler(eventData); + }; + return this.control.onMouseMove(callback); }, - getSelectedItem: function () { - return this.control.get('selectedItem'); + onMouseWheel: function (handler) { + var that = this, + callback = function (nativeEventData) { + var eventData = that._getHandlingMouseEventData(nativeEventData); + handler(eventData); + }; + return this.control.onMouseWheel(callback); }, - setSelectedItem: function (value) { - this.control.set('selectedItem', value); + onRemove: function( handler ) { + return this.control.onRemove(this.createControlEventHandler(this, handler)); }, - onSelectedItemChanged: function (handler) { - this.control.onSelectedItemChanged(this.createControlEventHandler(this, handler)); - } + remove: function (isInitiatedByParent, parent) { - // UNUSED ? - //getValueComparator: function () { - // return this.control.get('valueComparator'); - //} + var logger = window.InfinniUI.global.logger; + if(this.isRemoved){ + logger.warn('Element.remove: Попытка удалить элемент, который уже был удален'); + return; + } -}, editorBaseMixin); + var children = this.childElements; -//####app/elements/_base/listEditorBase/listEditorBaseBuilder.js -function ListEditorBaseBuilder() { - _.superClass(ListEditorBaseBuilder, this); + for (var i = 0, ii = children.length; i < ii; i++) { + children[i].remove(true, this); + } - this.initialize_editorBaseBuilder(); -} + this.control.remove(); -window.InfinniUI.ListEditorBaseBuilder = ListEditorBaseBuilder; + if (this.parent && this.parent.removeChild && !isInitiatedByParent) { + if(this.parent.isRemoved){ + logger.warn('Element.remove: Попытка удалить элемент из родителя, который помечен как удаленный'); + }else{ + this.parent.removeChild(this); + } -_.inherit(ListEditorBaseBuilder, ContainerBuilder); + } + if( parent && this.parent && this.parent.removeChild && isInitiatedByParent && parent !== this.parent ) { + this.parent.removeChild(this); + } -_.extend(ListEditorBaseBuilder.prototype, { + this.isRemoved = true; - applyMetadata: function (params) { + this.childElements = undefined; + }, - var applyingMetadataResult = ContainerBuilder.prototype.applyMetadata.call(this, params), - itemsBinding = applyingMetadataResult.itemsBinding, - applyingMetadataResult2; + removeChild: function (child) { + var index = this.childElements.indexOf(child); + if (index != -1) { + this.childElements.splice(index, 1); + } + }, - this.initSelecting(params, itemsBinding); - this.initDisabledItemCondition(params); + addChild: function (child) { + if(!this.isRemoved){ + this.childElements.push(child); - this.initValueFeatures(params); + }else{ + var logger = window.InfinniUI.global.logger; + logger.warn('Element.addChild: Попытка добавить потомка в удаленный элемент'); + } - applyingMetadataResult2 = this.applyMetadata_editorBaseBuilder(params); - return _.extend(applyingMetadataResult, applyingMetadataResult2); }, + createControlEventHandler: function(element, handler, additionParams) { + var context; + var parentView = element.getView(); + additionParams = additionParams || {}; - initSelecting: function(params, itemsBinding){ - var metadata = params.metadata; - var element = params.element; - var dataSource = itemsBinding.getSource(); - var sourceProperty = itemsBinding.getSourceProperty(); - var isBindingOnWholeDS = sourceProperty == ''; + if (parentView) { + context = parentView.context; + } - if(isBindingOnWholeDS){ - dataSource.setSelectedItem(null); + return function (message) { + message = message || {}; + _.extend( + message, + additionParams + ); + message.source = element; - dataSource.onSelectedItemChanged(function(context, args){ - var currentSelectedItem = element.getSelectedItem(), - newSelectedItem = args.value; + return handler.call(undefined, context, message); + }; + }, - if(newSelectedItem != currentSelectedItem){ - element.setSelectedItem(newSelectedItem); - } - }); - } + _getHandlingKeyEventData: function (nativeData) { + var result = {}; - element.onSelectedItemChanged(function(context, args){ - var currentSelectedItem = dataSource.getSelectedItem(), - newSelectedItem = args.value; + result = { + source: this, + key: nativeData.which, + altKey: nativeData.altKey, + ctrlKey: nativeData.ctrlKey, + shiftKey: nativeData.shiftKey, + nativeEventData: nativeData + }; + return result; + }, - if(isBindingOnWholeDS && newSelectedItem != currentSelectedItem){ - dataSource.setSelectedItem(newSelectedItem); - } + _getHandlingMouseEventData: function (nativeData) { + var result = {}; - if (metadata.OnSelectedItemChanged) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnSelectedItemChanged.Name || metadata.OnSelectedItemChanged, args); - } - }); + result = { + source: this, + button: nativeData.which, + altKey: nativeData.altKey, + ctrlKey: nativeData.ctrlKey, + shiftKey: nativeData.shiftKey, + nativeEventData: nativeData + }; + return result; }, - initValueFeatures: function(params){ - var metadata = params.metadata; - var element = params.element; - - if (typeof metadata.MultiSelect !== 'undefined' && metadata.MultiSelect !== null) { - element.setMultiSelect(metadata.MultiSelect); - } - - this.initValueSelector(params); + _upperFirstSymbol: function (s) { + return s[0].toUpperCase() + s.substr(1); }, - initValueSelector: function (params) { - var metadata = params.metadata, - element = params.element, - valueSelector; + setFocus: function () { + this.control.setFocus(); + }, - if (metadata.ValueSelector) { - valueSelector = function (context, args) { - var scriptExecutor = new ScriptExecutor(params.element.getScriptsStorage()); - return scriptExecutor.executeScript(metadata.ValueSelector.Name || metadata.ValueSelector, args) - }; - } else if (metadata.ValueProperty) { - valueSelector = function (context, args) { - return InfinniUI.ObjectUtils.getPropertyValue(args.value, metadata.ValueProperty); + renderTree: function(textIndent) { + var textIndent = textIndent || ''; + console.log( textIndent + 'Name: ' + this.getName(), this ); + if( this.childElements !== undefined ) { + if( textIndent !== '' ) { + textIndent += '_____'; + } else { + textIndent += '_____'; } - } else { - valueSelector = function (context, args) { - return args.value; + for( var i = 0, ii = this.childElements.length; i < ii; i += 1 ) { + this.renderTree.call(this.childElements[i], textIndent); } } - element.setValueSelector(valueSelector); }, - initDisabledItemCondition: function (params) { - var metadata = params.metadata, - element = params.element, - disabledItemCondition; - - if (metadata.DisabledItemCondition) { - disabledItemCondition = function (context, args) { - var scriptExecutor = new ScriptExecutor(element.getScriptsStorage()); - return scriptExecutor.executeScript(metadata.DisabledItemCondition.Name || metadata.DisabledItemCondition, args) - }; + renderFullTree: function() { + var parent = this.parent; + while( parent.parent && parent.parent.parent !== undefined ) { + parent = parent.parent; } - - element.setDisabledItemCondition(disabledItemCondition); + this.renderTree.call(parent); } -}, editorBaseBuilderMixin); +}); -//####app/elements/_base/textEditorBase/textEditorBase.js +window.InfinniUI.Element = Element; + +//####app/elements/_base/element/elementBuilder.js /** * - * @param parent * @constructor - * @augments Element - * @mixes editorBaseMixin - * @mixes labelTextElementMixin */ -function TextEditorBase(parent) { - _.superClass(TextEditorBase, this, parent); - this.initialize_editorBase(); -} - -window.InfinniUI.TextEditorBase = TextEditorBase; - -_.inherit(TextEditorBase, Element); - -_.extend(TextEditorBase.prototype, { +var ElementBuilder = function () { +}; - setEditor: function (editor) { - this.control.set('editor', editor); - }, +_.extend(ElementBuilder.prototype, /** @lends ElementBuilder.prototype */ { - setDisplayFormat: function (value) { - this.control.set('displayFormat', value); - }, + build: function (context, args) { + args = args || {}; + var element = this.createElement(args), + params = _.extend(args, { element: element }); - getDisplayFormat: function () { - return this.control.get('displayFormat'); - }, + this.applyMetadata(params); - setEditMask: function (value) { - this.control.set('editMask', value); - }, + if (args.parentView && args.parentView.registerElement) { + args.parentView.registerElement(element); + } - getEditMask: function () { - return this.control.get('editMask'); - }, + if (args.parent && args.parent.addChild) { + args.parent.addChild(element); + } - /** - * @description Возвращает значение, которое введено в поле редактирования в данный момент - * @returns {*} - */ - getRawValue: function () { - var value = this.control.get('editor').getValue(), - editMask = this.getEditMask(); + return element; + }, - if (editMask) { - var val = editMask.getValue(); - var txt = editMask.getText(); + /** + * + * @param {Object} params + * @param {Builder} params.builder + * @param {View} params.parent + * @param {Object} params.metadata + * @param {ListBoxItemCollectionProperty} params.collectionProperty + */ + createElement: function (params) { + throw ('Не перегружен абстрактный метод ElementBuilder.createElement()'); + }, - if (isNotEmpty(val)) { - value = val; - } else if (isNotEmpty(txt)) { - value = txt; - } - } + /** + * + * @param {Object} params + * @param {Builder} params.builder + * @param {View} params.parent + * @param {Object} params.metadata + * @param {ListBoxItemCollectionProperty} params.collectionProperty + * @param {Element} params.element + */ + applyMetadata: function (params) { + var metadata = params.metadata, + element = params.element; - return value; + this.initBindingToProperty(params, 'Text'); + this.initBindingToProperty(params, 'Visible', true); + this.initBindingToProperty(params, 'Enabled', true); + this.initBindingToProperty(params, 'HorizontalAlignment'); + this.initBindingToProperty(params, 'TextHorizontalAlignment'); + this.initBindingToProperty(params, 'VerticalAlignment'); + this.initBindingToProperty(params, 'TextStyle'); + this.initBindingToProperty(params, 'Foreground'); + this.initBindingToProperty(params, 'Background'); + this.initBindingToProperty(params, 'Style'); + this.initBindingToProperty(params, 'Tag'); + this.initBindingToProperty(params, 'Focusable', true); - function isNotEmpty(val) { - return val !== null && typeof val !== 'undefined'; - } - }, + if( metadata.ToolTip ) { + this.initToolTip(params); + } + if( metadata.ContextMenu ) { + this.initContextMenu(params); + } - getInputType: function () { - return this.control.get('inputType'); - }, + if ('Name' in metadata) { + element.setName(metadata.Name); + } - setInputType: function (inputType) { - if (inputType) { - this.control.set('inputType', inputType); - } - } -}, editorBaseMixin, labelTextElementMixin); + if (metadata.OnLoaded) { + element.onLoaded(function () { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnLoaded.Name || metadata.OnLoaded, { source: element }); + }); + } -//####app/elements/_base/textEditorBase/textEditorBaseBuilder.js -/** - * - * @constructor - * @augments ElementBuilder - * @mixes editorBaseBuilderMixin - * @mixes displayFormatBuilderMixin - * - */ -function TextEditorBaseBuilder() { - _.superClass(TextEditorBaseBuilder, this); - this.initialize_editorBaseBuilder(); -} + if (metadata.OnGotFocus) { + element.onGotFocus(function () { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnGotFocus.Name || metadata.OnGotFocus, { source: element }); + }); + } -window.InfinniUI.TextEditorBaseBuilder = TextEditorBaseBuilder; + if (metadata.OnLostFocus) { + element.onLostFocus(function () { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnLostFocus.Name || metadata.OnLostFocus, { source: element }); + }); + } -_.inherit(TextEditorBaseBuilder, ElementBuilder); + if (metadata.OnDoubleClick) { + element.onDoubleClick(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnDoubleClick.Name || metadata.OnDoubleClick, args); + }); + } -_.extend(TextEditorBaseBuilder.prototype, { + if (metadata.OnClick) { + element.onClick(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnClick.Name || metadata.OnClick, args); + }); + } - applyMetadata: function (params) { - ElementBuilder.prototype.applyMetadata.call(this, params); - this.applyMetadata_editorBaseBuilder(params); + if (metadata.OnMouseEnter) { + element.onMouseEnter(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnMouseEnter.Name || metadata.OnMouseEnter, args); + }); + } - var metadata = params.metadata; - var element = params.element; + if (metadata.OnMouseLeave) { + element.onMouseLeave(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnMouseLeave.Name || metadata.OnMouseLeave, args); + }); + } - this.initBindingToProperty(params, 'LabelText'); + if (metadata.OnMouseMove) { + element.onMouseMove(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnMouseMove.Name || metadata.OnMouseMove, args); + }); + } - element.setInputType(this.getCompatibleInputType(params)); - this - .initDisplayFormat(params) - .initEditMask(params) - .initEditor(params); - }, + if (metadata.OnKeyDown) { + element.onKeyDown(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnKeyDown.Name || metadata.OnKeyDown, args); + }); + } - getCompatibleInputType: function (params) { - var inputType = params.metadata.Type, - editMask = params.metadata.EditMask; + if (metadata.OnKeyUp) { + element.onKeyUp(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnKeyUp.Name || metadata.OnKeyUp, args); + }); + } - if (typeof inputType === 'undefined') { - inputType = params.element.getInputType(); - } + if (metadata.OnMouseDown) { + element.onMouseDown(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnMouseDown.Name || metadata.OnMouseDown, args); + }); + } - if (editMask) { - //Маска редактирования задается только для input[type=text] - inputType = 'text' - } - return inputType; - }, + if (metadata.OnMouseUp) { + element.onMouseUp(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnMouseUp.Name || metadata.OnMouseUp, args); + }); + } - initEditor: function (params) { - var element = params.element; - var editor = new TextEditor(); - editor - .setDisplayFormat(element.getDisplayFormat()) - .setEditMask(element.getEditMask()) - .setValueConverter(function () { - return element.convertValue.bind(element) - }) - .setValidatorValue(element.validateValue.bind(element)); + if (metadata.OnMouseWheel) { + element.onMouseWheel(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnMouseWheel.Name || metadata.OnMouseWheel, args); + }); + } + }, - element.setEditor(editor); + initBindingToProperty: function (params, propertyName, isBooleanBinding) { + var metadata = params.metadata, + propertyMetadata = metadata[propertyName], + element = params.element, + lowerCasePropertyName = this.lowerFirstSymbol(propertyName), + converter; - editor.onValueChanged(function (value) { - //element.setValue(element.convertValue(value)); - element.setValue(value); - }); + if (!propertyMetadata || typeof propertyMetadata != 'object') { + if (propertyMetadata !== undefined) { + params.element['set' + propertyName](propertyMetadata); + } + return null; - element.onValueChanged(function (context, args) { - editor.setValue(args.newValue); - }); + } else { + var args = { + parent: params.parent, + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }; - editor.setValue(element.getValue()); + var dataBinding = params.builder.buildBinding(metadata[propertyName], args); + var oldConverter; - return this; - }, + if (isBooleanBinding) { + dataBinding.setMode(InfinniUI.BindingModes.toElement); - initDisplayFormat: function (params) { - var - metadata = params.metadata, - format = this.buildDisplayFormat(metadata.DisplayFormat, params); + converter = dataBinding.getConverter(); + if (!converter) { + converter = {}; + } - params.element.setDisplayFormat(format); - return this; - }, + if(!converter.toElement){ + converter.toElement = function (context, args) { + return !!args.value; + }; + }else{ + oldConverter = converter.toElement; - initEditMask: function (params) { - var - metadata = params.metadata, - builder = params.builder, - editMask; + converter.toElement = function (context, args) { + var tmp = oldConverter(context, args); + return !!tmp; + }; + } - if (metadata.EditMask) { - editMask = builder.build(metadata.EditMask, { - parentView: params.parentView, - formatOptions: params.formatOptions - }); - } - params.element.setEditMask(editMask); - return this; - } -}, editorBaseBuilderMixin, displayFormatBuilderMixin); + dataBinding.setConverter(converter); + } + dataBinding.bindElement(element, lowerCasePropertyName); + return dataBinding; + } + }, -//####app/elements/_base/textEditor/textEditor.js -/** - * @constructor - */ + initToolTip: function (params) { + var builder = params.builder, + element = params.element, + metadata = params.metadata; -var TextEditor = function () { - var model = new TextEditorModel(); - - model.on('invalid', function (model, error) { - console.log('error', error); - }); + var tooltipBuilderParams = { + basePathOfProperty: params.basePathOfProperty, + parent: element, + parentView: params.parentView + }; - //@TODO Handle Enabled state + element.setToolTip(builder.buildType('ToolTip', metadata['ToolTip'], tooltipBuilderParams)); + }, - this._model = model; + initContextMenu: function(params) { + var exchange = window.InfinniUI.global.messageBus, + builder = params.builder, + element = params.element, + metadata = params.metadata, + contextMenu; -}; + var argumentForBuilder = { + parent: element, + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }; -window.InfinniUI.TextEditor = TextEditor; + contextMenu = builder.buildType('ContextMenu', { + "Items": metadata.ContextMenu.Items + }, argumentForBuilder); -TextEditor.prototype.setDisplayFormat = function (displayFormat) { - this._model.set('displayFormat', displayFormat); - return this; -}; + element.setContextMenu(contextMenu); + exchange.send(messageTypes.onContextMenu.name, { source: element, content: contextMenu.render() }); + }, -TextEditor.prototype.setEditMask = function (editMask) { - this._model.set('editMask', editMask); - return this; -}; + lowerFirstSymbol: function(s){ + return s[0].toLowerCase() + s.substr(1); + } -TextEditor.prototype.setValidatorValue = function (validatorValue) { - this._model.set('validateValue', validatorValue); - return this; -}; +}); -TextEditor.prototype.setValueConverter = function (converter) { - this._model.set('valueConverter', converter); - return this; -}; +window.InfinniUI.ElementBuilder = ElementBuilder; -TextEditor.prototype.getValue = function() { - return this._model.getValue(); -}; +//####app/elements/_base/_mixins/builderValuePropertyMixin.js +var builderValuePropertyMixin = { -/** - * - * @param {HTMLInputElement} inputElement - * @returns {*} - */ -TextEditor.prototype.render = function (inputElement) { + /** + * @param {Object} params + * @param {Boolean|false} useValidation Использовать валидацию + * @returns {*} + */ + initValueProperty: function (params, useValidation) { + var metadata = params.metadata; - this._view = new TextEditorView({ - model: this._model, - el: inputElement - }); + if (typeof useValidation === 'undefined') { + useValidation = false; + } - //return this._view.render(); -}; + if (metadata.Value !== undefined) { + var dataBinding = params.builder.build(params.view, metadata.Value, params.collectionProperty); -TextEditor.prototype.setValue = function (value) { - this._model.set('originalValue', value, {originalValue: true}); - return this; -}; + dataBinding.setElement(params.element); -TextEditor.prototype.onValueChanged = function (handler) { - this._model.on('change:originalValue', function (model, value, options) { - if (options.originalValue === true) { - return; - } + if (dataBinding != null) { + dataBinding.onPropertyValueChanged(function (dataSourceName, value) { + params.element.setValue(dataBinding.getPropertyValue()); + }); - handler.call(null, value); - }); -}; + var data = dataBinding.getPropertyValue(); + if (data !== null && typeof data !== 'undefined') { + params.element.setValue(data); + } -//####app/elements/listBox/listBox.js -function ListBox(parent, viewMode) { - _.superClass(ListBox, this, parent, viewMode); -} + params.element.onValueChanged(function (dataSourceName, value) { + dataBinding.setPropertyValue(value); + }); + } -window.InfinniUI.ListBox = ListBox; -_.inherit(ListBox, ListEditorBase); + if (useValidation && dataBinding) { + params.element.onLostFocus(function () { + dataBinding.validate(); + }); + } -ListBox.prototype.createControl = function (viewMode) { - return new ListBoxControl(viewMode); -}; + return dataBinding; + } + } -ListBox.prototype.setEnabled = function (value) { - if( _.isBoolean(value) ) { - ListEditorBase.prototype.setEnabled.call(this, value); - if( value ) { - this.control.updateDisabledItem(); - } else { - this.control.disableAll(); - } - } }; +//####app/elements/_base/_mixins/buttonBuilderMixin.js +var buttonBuilderMixin = { + applyButtonMetadata: function(params){ + var element = params.element; + var metadata = params.metadata; + var builder = params.builder; -//####app/elements/listBox/listBoxBuilder.js -function ListBoxBuilder() { - _.superClass(ListBoxBuilder, this); -} + this.initTemplatingContent(params); + + if (metadata.Action) { + var args = { + parentView: params.parentView, + parent: element, + basePathOfProperty: params.basePathOfProperty + }; + var action = builder.build(metadata.Action, args); + element.onClick(function(){ + action.execute(); + }); + } + }, -window.InfinniUI.ListBoxBuilder = ListBoxBuilder; + initTemplatingContent: function(params){ + var element = params.element; + var metadata = params.metadata; + var builder = params.builder; + var contentTemplate, contentBinding; -_.inherit(ListBoxBuilder, ListEditorBaseBuilder); + if('ContentTemplate' in metadata){ + contentTemplate = this.buildContentTemplate(metadata['ContentTemplate'], params); + element.setContentTemplate(contentTemplate); + } -_.extend(ListBoxBuilder.prototype, /** @lends ListBoxBuilder.prototype */{ + if('Content' in metadata){ + contentBinding = builder.buildBinding(metadata['Content'], { + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }); - createElement: function (params) { - return new ListBox(params.parent, params.metadata['ViewMode']); + contentBinding.bindElement(element, 'content'); + } }, - applyMetadata: function (params) { - ListEditorBaseBuilder.prototype.applyMetadata.call(this, params); - } - -}); + buildContentTemplate: function (templateMetadata, params) { + var element = params.element; + var builder = params.builder; + var basePathOfProperty = params.basePathOfProperty; -//####app/elements/textBox/textBox.js -/** - * - * @param parent - * @constructor - * @augments TextEditorBase - */ -function TextBox(parent) { - _.superClass(TextBox, this, parent); -} + return function(context, args) { + var argumentForBuilder = { + parent: params.element, + parentView: params.parentView, + basePathOfProperty: basePathOfProperty + }; -window.InfinniUI.TextBox = TextBox; + return builder.build(templateMetadata, argumentForBuilder); + }; + } +}; +//####app/elements/_base/_mixins/buttonMixin.js +var buttonMixin = { -_.inherit(TextBox, TextEditorBase); + buttonInit: function () { + this.isFirstAction = true; + }, -_.extend(TextBox.prototype, { - createControl: function (parent) { - return new TextBoxControl(parent); + getContent: function () { + return this.control.get('content'); }, - getMultiline: function () { - return this.control.get('multiline'); + setContent: function (value) { + this.control.set('content', value); }, - setMultiline: function (value) { - this.control.set('multiline', value); + getContentTemplate: function () { + return this.control.get('contentTemplate'); }, - getLineCount: function () { - return this.control.get('lineCount'); + setContentTemplate: function (value) { + this.control.set('contentTemplate', value); }, - setLineCount: function (value) { - this.control.set('lineCount', value); - } + setAction: function (value) { + var control = this.control; -}); + control.set('action', value); + if (this.isFirstAction) { + this.isFirstAction = false; + this.onClick(function () { + var action = control.get('action'); -//####app/elements/textBox/textBoxBuilder.js -/** - * - * @constructor - * @augments TextEditorBaseBuilder - */ -function TextBoxBuilder() { - _.superClass(TextBoxBuilder, this); -} + if (action ) { + action.execute(); + } + }); + } + }, + + getAction: function () { + return this.control.get('action'); + }, -window.InfinniUI.TextBoxBuilder = TextBoxBuilder; + click: function () { + this.control.click(); + }, -_.inherit(TextBoxBuilder, TextEditorBaseBuilder); + onClick: function(handler){ + var that = this; -TextBoxBuilder.prototype.createElement = function (params) { - return new TextBox(params.parent); -}; + Element.prototype.onClick.call(this, onClickHandlerWrap); -TextBoxBuilder.prototype.applyMetadata = function (params) { - TextEditorBaseBuilder.prototype.applyMetadata.call(this, params); + function onClickHandlerWrap(args){ + var enabled = that.getEnabled(); - var element = params.element; - var metadata = params.metadata; - var lineCount = metadata.LineCount; - element.setMultiline(metadata.Multiline); - if (metadata.Multiline && lineCount === null || typeof lineCount === 'undefined') { - lineCount = 2; + if(enabled){ + handler(args); + } + } } - element.setLineCount(lineCount); -}; -//####app/elements/dateTimePicker/dateTimePicker.js -/** - * - * @param parent - * @constructor - * @augments TextEditorBase - */ -function DateTimePicker(parent) { - _.superClass(DateTimePicker, this, parent); -} +}; +//####app/elements/_base/_mixins/displayFormatBuilderMixin.js +/** + * @mixin + */ +var displayFormatBuilderMixin = { + + /** + * Возвращает функцию форматирования значения + * @see {@link http://docs.infinnity.ru/docs/Specifications/UserInterface/Components/TextEditorBase/TextEditorBase.setDisplayFormat/} + * @param {String} displayFormat + * @param {Object} params + * @param {ApplicationBuilder} params.builder + * @returns {Function} + */ + buildDisplayFormat: function (displayFormat, params) { + var formatOptions = params.formatOptions; + var builder = params.builder; + var formatter, format = defaultFormat; + if (typeof displayFormat === 'string') { + formatter = builder.buildType('ObjectFormat', {Format: displayFormat}); + format = function (context, args){ + args = args || {}; + return formatter.format(args.value); + } + } else if (displayFormat && typeof displayFormat === 'object') { + formatter = builder.build(displayFormat); + + format = function (context, args){ + args = args || {}; + return formatter.format(args.value); + } + } + + if (formatter) { + formatter.setOptions(formatOptions); + } + + return format; + + function defaultFormat(context, args) { + args = args || {}; + return args.value; + } + } +}; -window.InfinniUI.DateTimePicker = DateTimePicker; +//####app/elements/_base/_mixins/labelTextElementMixin.js +var labelTextElementMixin = { + getLabelText: function () { + return this.control.get('labelText'); + }, + setLabelText: function (value) { + this.control.set('labelText', value); + } +}; +//####app/elements/_base/_mixins/routerServiceMixin.js +var routerServiceMixin = { -_.inherit(DateTimePicker, TextEditorBase); + replaceParamsInHref: function(oldHref, param, newValue, hrefPattern) { + if( hrefPattern ) { + var newHref = hrefPattern.split('?')[0], + query = hrefPattern.split('?')[1], + tmpArr = newHref.split('/'), + index = tmpArr.indexOf(':' + param); -DateTimePicker.prototype.createControl = function (parent) { - return new DateTimePickerControl(parent); -}; + if( index === -1 ) { + throw new Error('Different param names in metadata and InfinniUI.config.Routes'); + } + tmpArr = oldHref.split('/'); + tmpArr[index] = newValue; + tmpArr = tmpArr.join('/'); + if( query ) { + tmpArr += '?' + query; + } + return tmpArr; + } else { + return oldHref.replace(':' + param, newValue); + } + }, -DateTimePicker.prototype.getMinValue = function () { - return this.control.get('minValue'); -}; + replaceParamsInQuery: function(oldHref, queryParam, newValue, queryPattern) { + if( queryPattern ) { + var newHref = oldHref.split('?')[0], + query = oldHref.split('?')[1], + queryTmp = queryPattern.split('?')[1], + tmpArr = queryTmp.split('&'), + index = -1; -DateTimePicker.prototype.setMinValue = function (value) { - this.control.set('minValue', value); -}; + for(var i = 0, ii = tmpArr.length; i < ii; i += 1) { + if( tmpArr[i].indexOf(':' + queryParam) !== -1 ) { + index = i; + } + } -DateTimePicker.prototype.getMaxValue = function () { - return this.control.get('maxValue'); -}; + if( index === -1 ) { + throw new Error('Different query names in metadata and InfinniUI.config.Routes'); + } + tmpArr = query.split('&'); + var tmpValue = tmpArr[index].split('='); + tmpValue[1] = newValue; + tmpArr[index] = tmpValue.join('='); + var finalString = newHref + '?' + tmpArr.join('&'); + return finalString; + } else { + return oldHref.replace(':' + queryParam, newValue); + } + }, -DateTimePicker.prototype.setMaxValue = function (value) { - this.control.set('maxValue', value); -}; + bindParams: function(params, paramName, paramValue, hrefPattern) { + var element = params.element, + builder = params.builder, + that = this, + args = { + parent: params.parent, + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }; -DateTimePicker.prototype.getMode = function () { - return this.control.get('mode'); -}; + var dataBinding = params.builder.buildBinding(paramValue, args); -DateTimePicker.prototype.setMode = function (value) { - this.control.set('mode', value); -}; + dataBinding.bindElement({ + onPropertyChanged: function() {}, + setProperty: function(elementProperty, newValue) { + var oldHref = element.getHref(), + newHref = that.replaceParamsInHref(oldHref, paramName, newValue, hrefPattern); + element.setHref(newHref); + }, + getProperty: function() {} + }, ''); + }, -DateTimePicker.prototype.getTimeZone = function () { - return this.control.get('timeZone'); -}; + bindQuery: function(params, queryName, queryValue, queryPattern) { + var element = params.element, + builder = params.builder, + that = this, + args = { + parent: params.parent, + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }; -DateTimePicker.prototype.setTimeZone = function (value) { - if (_.isNumber(value)) { - this.control.set('timeZone', value); - } -}; + var dataBinding = params.builder.buildBinding(queryValue, args); -DateTimePicker.prototype.setDateFormat = function (value) { - this.control.set('format', value); + dataBinding.bindElement({ + onPropertyChanged: function() {}, + setProperty: function(elementProperty, newValue) { + var oldHref = element.getHref(), + newHref = that.replaceParamsInQuery(oldHref, queryName, newValue, queryPattern); + element.setHref(newHref); + }, + getProperty: function() {} + }, ''); + } }; -DateTimePicker.prototype.validateValue = function (value) { - if (value === null || value === '' || typeof value === 'undefined') { - return; - } +//####app/elements/_base/_mixins/valuePropertyMixin.js +var valuePropertyMixin = { - var minValue = InfinniUI.DateUtils.restoreTimezoneOffset(this.getMinValue(), this.getTimeZone()); - var maxValue = InfinniUI.DateUtils.restoreTimezoneOffset(this.getMaxValue(), this.getTimeZone()); + getValue: function(){ + return this.control.get('value'); + }, - var isValid = InfinniUI.DateUtils.checkRangeDate(value, minValue, maxValue); + setValue: function(value){ + return this.control.set('value', value); + }, - if (!isValid) { - return "Неверное значение"; + onValueChanged: function(handler){ + this.control.onValueChanged(handler); } -}; - +}; +//####app/elements/_base/_mixins/veiwBuilderHeaderTemplateMixin.js +var viewBuilderHeaderTemplateMixin = { + + /** + * @protected + * @param params + */ + buildHeaderTemplate: function (view, params) { + var + builder = params.builder, + metadata = params.metadata, + headerTemplate; + + if (metadata.HeaderTemplate) { + //@TODO Build header template by metadata + headerTemplate = function (context, args) { + var + paramsForBuilder = { + parent: view, + parentView: view, + basePathOfProperty: params.basePathOfProperty + }; + + return builder.build(metadata.HeaderTemplate, paramsForBuilder); + } + } else { + //@TODO Build header template by default + headerTemplate = function (context, args) { + var + label = new Label(); + + label.setValue(view.getText()); + view.onPropertyChanged("text", function (context, args) { + label.setValue(args.newValue); + }); + + return label; + } + } + return headerTemplate; + } + +}; -//####app/elements/dateTimePicker/dateTimePickerBuilder.js +//####app/elements/_base/container/container.js /** - * + * @param parent * @constructor - * @augments TextEditorBaseBuilder + * @augments Element */ -function DateTimePickerBuilder() { - _.superClass(DateTimePickerBuilder, this); +function Container(parent, viewMode) { + _.superClass(Container, this, parent, viewMode); } -window.InfinniUI.DateTimePickerBuilder = DateTimePickerBuilder; - -_.inherit(DateTimePickerBuilder, TextEditorBaseBuilder); - -DateTimePickerBuilder.prototype.createElement = function (params) { - return new DateTimePicker(params.parent); -}; - -DateTimePickerBuilder.prototype.applyMetadata = function (params) { - var element = params.element; - - this.applyDefaultMetadata(params); - var metadata = params.metadata; - - TextEditorBaseBuilder.prototype.applyMetadata.call(this, params); - - element.setTimeZone(metadata.TimeZone); - element.setMode(metadata.Mode); - - this.applyMinValue(element, metadata.MinValue); - this.applyMaxValue(element, metadata.MaxValue); - - //var format = params.builder.buildType(params.parent, 'DateFormat', {}, null); - //element.setDateFormat(format); -}; - -DateTimePickerBuilder.prototype.applyMinValue = function (element, minValue) { - element.setMinValue(InfinniUI.DateUtils.parseISO8601toDate(minValue)); -}; - -DateTimePickerBuilder.prototype.applyMaxValue = function (element, maxValue) { - element.setMaxValue(InfinniUI.DateUtils.parseISO8601toDate(maxValue)); -}; - -DateTimePickerBuilder.prototype.applyDefaultMetadata = function (params) { - var metadata = params.metadata; - var defaultFormat = { - Date: '{:d}', - DateTime: '{:g}', - Time: '{:T}' - }, - defaultEditMask = { - Date: {DateTimeEditMask: {Mask: 'd'}}, - DateTime: {DateTimeEditMask: {Mask: 'g'}}, - Time: {DateTimeEditMask: {Mask: 'T'}} - }; - - params.metadata = _.extend({}, metadata); - - _.defaults(params.metadata, {Mode: 'Date'}); - _.defaults(params.metadata, { - DisplayFormat: defaultFormat[params.metadata.Mode], - EditMask: defaultEditMask[params.metadata.Mode] - }); -}; +window.InfinniUI.Container = Container; -DateTimePickerBuilder.prototype.initDisplayFormat = function (params) { - return TextEditorBaseBuilder.prototype.initDisplayFormat.call(this, this.applyTimeZone(params)); -}; +_.inherit(Container, Element); -DateTimePickerBuilder.prototype.initEditMask = function (params) { - return TextEditorBaseBuilder.prototype.initEditMask.call(this, this.applyTimeZone(params)); +Container.prototype.getItemTemplate = function () { + return this.control.get('itemTemplate'); }; -DateTimePickerBuilder.prototype.applyTimeZone = function (params) { - var metadata = params.metadata; - var _params = {}; - var formatOptions = {}; - - if (typeof metadata.TimeZone !== 'undefined' && metadata.TimeZone !== null ) { - formatOptions.TimeZone = metadata.TimeZone; +Container.prototype.setItemTemplate = function (itemTemplate) { + if (typeof itemTemplate !== 'function') { + throw new Error('Function expected'); } - - _.defaults(_params, params, {formatOptions: formatOptions}); - return _params; + this.control.set('itemTemplate', itemTemplate); }; -//####app/elements/datePicker/datePicker.js -function DatePicker(parent) { - _.superClass(DatePicker, this, parent); - - this.setMode('DatePicker'); - this.setTimeZone(); -} - -window.InfinniUI.DatePicker = DatePicker; - -_.inherit(DatePicker, DateTimePicker); - -DatePicker.prototype.setTimeZone = function () { - DateTimePicker.prototype.setTimeZone.call(this, 0); +Container.prototype.getItems = function () { + return this.control.get('items'); }; -DatePicker.prototype.createControl = function (parent) { - return new DatePickerControl(parent); +Container.prototype.getGroupValueSelector = function () { + return this.control.get('groupValueSelector'); }; -DatePicker.prototype.convertValue = function (value) { - var _value = null; +Container.prototype.setGroupValueSelector = function (value) { + this.control.set('groupValueSelector', value); +}; - if(typeof value === 'undefined' || value === null || !value.toString().length) { - _value = null; - } else { - _value = InfinniUI.DateUtils.dateToTimestamp(value); - } +Container.prototype.getGroupItemTemplate = function () { + return this.control.get('groupItemTemplate'); +}; - return _value; +Container.prototype.setGroupItemTemplate = function (value) { + this.control.set('groupItemTemplate', value); }; -//####app/elements/datePicker/datePickerBuilder.js -function DatePickerBuilder() { - _.superClass(DatePickerBuilder, this); -} +Container.prototype.getGroupItemComparator = function () { + return this.control.get('groupItemComparator'); +}; -window.InfinniUI.DatePickerBuilder = DatePickerBuilder; +Container.prototype.setGroupItemComparator = function (value) { + this.control.set('groupItemComparator', value); +}; -_.inherit(DatePickerBuilder, DateTimePickerBuilder); -DatePickerBuilder.prototype.createElement = function (params) { - return new DatePicker(params.parent); -}; +//####app/elements/_base/container/containerBuilder.js +function ContainerBuilder() { + _.superClass(ContainerBuilder, this); +} +window.InfinniUI.ContainerBuilder = ContainerBuilder; -DatePickerBuilder.prototype.applyDefaultMetadata = function (params) { +_.inherit(ContainerBuilder, ElementBuilder); - params.metadata = _.extend({}, params.metadata, { - Mode: 'DatePicker', - TimeZone: 0 - }); +/** + * @abstract + */ +_.extend(ContainerBuilder.prototype, { - _.defaults(params.metadata, { - DisplayFormat: '{:d}', - EditMask: {DateTimeEditMask: {Mask: 'd'}} - }); -}; + /** + * + * @param params + * @returns {{itemsBinding: {DataBinding}}} + */ + applyMetadata: function (params) { + var metadata = params.metadata; + var element = params.element; + var itemsBinding; -//####app/elements/timePicker/timePicker.js -function TimePicker(parent) { - _.superClass(TimePicker, this, parent); + ElementBuilder.prototype.applyMetadata.call(this, params); - this.setMode('TimePicker'); - this.setTimeZone(); -} + itemsBinding = this.initItems(params); + this.initGroup(params, itemsBinding); -window.InfinniUI.TimePicker = TimePicker; + return { + itemsBinding: itemsBinding + }; + }, -_.inherit(TimePicker, DateTimePicker); + initItems: function (params) { + var metadata = params.metadata; + var itemsBinding = null; + if (Array.isArray(metadata.Items)) { // отдельные не шаблонизируемые items, в metadata.Items - список методанных item'ов + this.initNotTemplatingItems(params); + } else if (metadata.Items) { // шаблонизируемые однотипные items, в metadata.Items - биндинг на данные item'ов + itemsBinding = this.initTemplatingItems(params); + } -TimePicker.prototype.createControl = function (parent) { - return new TimePickerControl(parent); -}; + return itemsBinding; + }, -TimePicker.prototype.setTimeZone = function () { - DateTimePicker.prototype.setTimeZone.call(this, 0); -}; + initTemplatingItems: function (params) { + var metadata = params.metadata; + var element = params.element; + var itemTemplate; + var binding; + var property; -TimePicker.prototype.convertValue = function (value) { - var _value = null; + binding = params.builder.buildBinding(metadata.Items, { + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }); - if(typeof value === 'undefined' || value === null || !value.toString().length) { - _value = null; - } else { - _value = InfinniUI.DateUtils.dateToTimestampTime(value); - } + binding.setMode(InfinniUI.BindingModes.toElement); - return _value; -}; + //if ('ItemComparator' in metadata) { + this.bindElementItemsWithSorting(binding, params); + //} else { + // binding.bindElement(element, 'items'); + //} -//####app/elements/timePicker/timePickerBuilder.js -function TimePickerBuilder() { - _.superClass(TimePickerBuilder, this); -} -window.InfinniUI.TimePickerBuilder = TimePickerBuilder; + if ('ItemTemplate' in metadata) { + itemTemplate = this.buildItemTemplate(metadata.ItemTemplate, params); + } else if ('ItemFormat' in metadata) { + itemTemplate = this.buildItemFormat(binding, metadata.ItemFormat, params); + } else if ('ItemSelector' in metadata) { + itemTemplate = this.buildItemSelector(binding, metadata.ItemSelector, params); + } else { + if ('ItemProperty' in metadata) { + property = metadata.ItemProperty; + } else { + property = ''; + } + itemTemplate = this.buildItemProperty(binding, property, params); + } -_.inherit(TimePickerBuilder, DateTimePickerBuilder); + element.setItemTemplate(itemTemplate); -TimePickerBuilder.prototype.createElement = function (params) { - return new TimePicker(params.parent); -}; + return binding; + }, -TimePickerBuilder.prototype.applyDefaultMetadata = function (params) { + initNotTemplatingItems: function (params) { + var itemsMetadata = params.metadata.Items; + var element = params.element; + //var fakeItems = (new Array(itemsMetadata.length + 1)).join(' ').split(''); + var items = itemsMetadata.slice(0); + element.getItems().set(items); + var itemTemplate = this.buildItemTemplateForUniqueItem(items, params); + element.setItemTemplate(itemTemplate); + }, - params.metadata = _.extend({}, params.metadata, { - Mode: 'TimePicker', - TimeZone: 0 - }); + tuneItemsBinding: function (itemsBinding) { + var source = itemsBinding.getSource(); + if (typeof source.tryInitData == 'function') { + source.tryInitData(); + } + }, - _.defaults(params.metadata, { - DisplayFormat: '{:T}', - EditMask: { - DateTimeEditMask: { - Mask: 'T' - } + initGroup: function (params, itemsBinding) { + if (this.hasGrouping(params)) { + this.initGroupValueSelector(params); + this.initGroupItemTemplate(params, itemsBinding); } - }); + }, -}; + hasGrouping: function (params) { + return params.metadata.GroupValueSelector || params.metadata.GroupValueProperty; + }, -TimePickerBuilder.prototype.applyMinValue = function (element, minValue) { - var date = InfinniUI.DateUtils.parseTimeISO8601toDate(minValue, 0); + initGroupValueSelector: function (params) { + var metadata = params.metadata, + element = params.element, + groupValueSelector; - if (typeof date !== 'undefined') { - element.setMinValue(date); - } -}; + /* element.setGroupItemComparator(function(a, b) { + if (a < b) { + return -1; + } -TimePickerBuilder.prototype.applyMaxValue = function (element, maxValue) { - var date = InfinniUI.DateUtils.parseTimeISO8601toDate(maxValue, 0); + if (a > b) { + return 1; + } - if (typeof date !== 'undefined') { - element.setMaxValue(date); - } -}; + return 0; + });*/ -//####app/elements/stackPanel/stackPanel.js -/** - * @param parent - * @constructor - * @augments Container - */ -function StackPanel(parent, viewMode) { - _.superClass(StackPanel, this, parent, viewMode); -} + if (metadata.GroupValueSelector) { + groupValueSelector = function (context, args) { + var scriptExecutor = new ScriptExecutor(element.getScriptsStorage()); + return scriptExecutor.executeScript(metadata.GroupValueSelector.Name || metadata.GroupValueSelector, args) + }; + } else if (metadata.GroupValueProperty) { + groupValueSelector = function (context, args) { + return InfinniUI.ObjectUtils.getPropertyValue(args.value, metadata.GroupValueProperty); + } + } else { + //Без группировки + groupValueSelector = null + } + element.setGroupValueSelector(groupValueSelector); + }, -window.InfinniUI.StackPanel = StackPanel; + initGroupItemTemplate: function (params, itemsBinding) { + var metadata = params.metadata; + var element = params.element; + var itemTemplate; + var property; -_.inherit(StackPanel, Container); + if (metadata.GroupItemTemplate) { + itemTemplate = this.buildItemTemplate(metadata.GroupItemTemplate, params); + } else if (metadata.GroupItemFormat) { + itemTemplate = this.buildItemFormat(itemsBinding, metadata.GroupItemFormat, params); + } else if (metadata.GroupItemSelector) { + itemTemplate = this.buildItemSelector(itemsBinding, metadata.GroupItemSelector, params); + } else if (metadata.GroupItemProperty) { + itemTemplate = this.buildItemProperty(itemsBinding, metadata.GroupItemProperty, params); + } -StackPanel.prototype.getOrientation = function () { - return this.control.get('orientation'); -}; + if (itemTemplate) { + element.setGroupItemTemplate(itemTemplate); + } + }, -StackPanel.prototype.setOrientation = function (value) { - if (InfinniUI.Metadata.isValidValue(value, InfinniUI.StackPanelOrientation)) { - this.control.set('orientation', value) - } -}; + buildItemProperty: function (itemsBinding, itemPropertyMetadata, params) { -StackPanel.prototype.createControl = function (viewMode) { - return new StackPanelControl(viewMode); -}; + return function (context, args) { + var index = args.index; + var label = new Label(this); + var sourceProperty; + var source = itemsBinding.getSource(); + var binding = new DataBinding(); -//####app/elements/stackPanel/stackPanelBuilder.js -/** - * @constructor - * @augments ContainerBuilder - */ -function StackPanelBuilder() { - _.superClass(StackPanelBuilder, this); -} + sourceProperty = index.toString(); + if (itemsBinding.getSourceProperty() != '') { + sourceProperty = itemsBinding.getSourceProperty() + '.' + sourceProperty; + } + if (itemPropertyMetadata != '') { + sourceProperty = sourceProperty + '.' + itemPropertyMetadata; + } -window.InfinniUI.StackPanelBuilder = StackPanelBuilder; + binding.bindSource(source, sourceProperty); + binding.bindElement(label, 'value'); -_.inherit(StackPanelBuilder, ContainerBuilder); + return label; + }; + }, -_.extend(StackPanelBuilder.prototype, - /** @lends StackPanelBuilder.prototype*/ - { - createElement: function (params) { - return new StackPanel(params.parent, params.metadata['ViewMode']); - }, + buildItemFormat: function (itemsBinding, itemFormatMetadata, params) { - /** - * @param {Object} params - * @param {StackPanel} params.element - * @param {Object} params.metadata - */ - applyMetadata: function (params) { - var - metadata = params.metadata, - element = params.element; + var format = this.buildDisplayFormat(itemFormatMetadata, params); + return function (context, args) { + var index = args.index; + var label = new Label(this); - var result = ContainerBuilder.prototype.applyMetadata.call(this, params); - element.setOrientation(metadata.Orientation); + var sourceProperty = itemsBinding.getSourceProperty(); + var source = itemsBinding.getSource(); + var binding = new DataBinding(); - return result; - } + sourceProperty = index.toString(); + if (itemsBinding.getSourceProperty() != '') { + sourceProperty = itemsBinding.getSourceProperty() + '.' + sourceProperty; + } - }); + label.setDisplayFormat(format); -//####app/elements/button/button.js -/** - * @param parent - * @augments Element - * @constructor - */ -function Button(parent, viewMode) { - _.superClass(Button, this, parent, viewMode); - this.buttonInit(); -} + binding.bindSource(source, sourceProperty); + binding.bindElement(label, 'value'); -window.InfinniUI.Button = Button; + return label; + }; -_.inherit(Button, Element); + }, -_.extend(Button.prototype, { + buildItemSelector: function (itemsBinding, itemSelectorMetadata, params) { - createControl: function (viewMode) { - return new ButtonControl(viewMode); - }, + return function (context, args) { + var index = args.index; + var label = new Label(this); + var scriptExecutor = new ScriptExecutor(params.parentView); - setType: function(type) { - this.control.setType(type); - }, + var sourceProperty = itemsBinding.getSourceProperty(); + var source = itemsBinding.getSource(); + var binding = new DataBinding(); + binding.setMode(InfinniUI.BindingModes.toElement); - getType: function() { - return this.control.getType(); - } + sourceProperty = index.toString(); + if (itemsBinding.getSourceProperty() != '') { + sourceProperty = itemsBinding.getSourceProperty() + '.' + sourceProperty; + } -}, buttonMixin); + binding.setConverter({ + toElement: function (_context, _args) { + return scriptExecutor.executeScript(itemSelectorMetadata.Name || itemSelectorMetadata, _args); + } + }); -//####app/elements/button/buttonBuilder.js -function ButtonBuilder() { - _.superClass(ButtonBuilder, this); -} + binding.bindSource(source, sourceProperty); + binding.bindElement(label, 'value'); -window.InfinniUI.ButtonBuilder = ButtonBuilder; + return label; + } + }, -_.inherit(ButtonBuilder, ElementBuilder); + buildItemTemplate: function (templateMetadata, params) { + var element = params.element; + var builder = params.builder; + var basePathOfProperty = params.basePathOfProperty || new BasePathOfProperty(''); + var propertyForSource = params.metadata['Items']['Property'] || ''; + var that = this; -_.extend(ButtonBuilder.prototype, { + return function (context, args) { + var index = args.index; + var bindingIndex; + var argumentForBuilder = { + parent: params.element, + parentView: params.parentView + }; - createElement: function (params) { - var viewMode = this.detectViewMode(params); - return new Button(params.parent, viewMode); - }, + if (index !== undefined && index !== null) { + bindingIndex = that.bindingIndexByItemsIndex(index, params); - detectViewMode: function(params){ - var viewMode = params.metadata['ViewMode']; - var el = params.parent; - var exit = false; + if (bindingIndex !== undefined && bindingIndex !== null) { + argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild(propertyForSource, bindingIndex); + } else { + argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild(propertyForSource, index); + } + } - if(!viewMode){ - while(!exit){ - if(el){ - if(el instanceof PopupButton){ - viewMode = 'link'; - exit = true; + return builder.build(templateMetadata, argumentForBuilder); + }; + }, - }else if(el instanceof MenuBar){ - viewMode = 'menuItem'; - exit = true; + /** + * @public + * @memberOf ContainerBuilder + * @description Возвращает функцию itemTemplate для не шаблонизируемого item'а. + * @param {Object} itemMetadata метаданные. + * @param {Object} params стандартные params, передаваемые внутри билдеров. + **/ + buildItemTemplateForUniqueItem: function (itemsMetadata, params) { + var element = params.element; + var builder = params.builder; + var basePathOfProperty = params.basePathOfProperty || new BasePathOfProperty(''); - }else if(el instanceof View){ - exit = true; + return function (context, args) { - }else{ - el = el.parent; + var + index = args.index, + item = element.getItems().getByIndex(index), + argumentForBuilder = { + parent: params.element, + parentView: params.parentView, + basePathOfProperty: basePathOfProperty + }; - } - }else{ - exit = true; - } - } + return builder.build(item, argumentForBuilder); + }; + }, - } + bindingIndexByItemsIndex: function (index, params) { + var element = params.element, + items = element.getItems(); - return viewMode + return items.getProperty(index, 'bindingIndex'); }, - applyMetadata: function (params) { - ElementBuilder.prototype.applyMetadata.call(this, params); + bindElementItemsWithSorting: function (binding, params) { + // нетривиальный биндинг элементов нужен для того, чтобы правильно учитывались индексы при сортировке элементов - this.applyButtonMetadata(params); + var metadata = params.metadata, + element = params.element, + scriptExecutor = new ScriptExecutor(params.parent), + itemComparator; - if( params.metadata.Type ) { - params.element.setType(params.metadata.Type); + if(metadata.ItemComparator){ + itemComparator = function (item1, item2) { + return scriptExecutor.executeScript(metadata.ItemComparator.Name || metadata.ItemComparator, {item1: item1, item2: item2}); + }; } - } -}, buttonBuilderMixin); + var source = binding.getSource(); + source.onPropertyChanged('*', function (context, args) { + var items = element.getItems(); + //При замене целого элемента списка, заменить элемент в коллекции + if (args.property && args.property.match(/^\d+$/)) { + items.replace(args.oldValue, args.newValue); + } + }); + + binding.bindElement({ + setProperty: function (name, value) { + var items = element.getItems(), + isCollectionChanged; -//####app/elements/buttonEdit/buttonEdit.js -/** - * - * @param parent - * @constructor - * @augments TextBox - */ -function ButtonEdit(parent) { - _.superClass(ButtonEdit, this, parent); -} + if(!element.isRemoved) { + if (itemComparator) { -window.InfinniUI.ButtonEdit = ButtonEdit; + isCollectionChanged = items.set(value, true); -_.inherit(ButtonEdit, TextBox); + items.forEach(function (item, index, collection) { + collection.setProperty(index, 'bindingIndex', index); + }); -ButtonEdit.prototype.createControl = function (parent) { - return new ButtonEditControl(parent); -}; + if (isCollectionChanged) { + items.sort(itemComparator); + } -/** - * @public - * @param {String} icon - */ -ButtonEdit.prototype.setIcon = function (icon) { - if (icon && icon.toLowerCase) { - icon = icon.toLowerCase(); - } - this.control.set('icon', icon); -}; + } else { -/** - * @public - * @returns {String} - */ -ButtonEdit.prototype.getIcon = function () { - return this.control.get('icon'); -}; + isCollectionChanged = items.set(value); -/** - * @public - * @param {boolean} readOnly - */ -ButtonEdit.prototype.setReadOnly = function (readOnly) { - if (typeof readOnly !== 'undefined' && readOnly !== null) { - this.control.set('readOnly', !!readOnly); - } -}; + items.forEach(function (item, index, collection) { + collection.setProperty(index, 'bindingIndex', index); + }); + } + } -/** - * @public - * @returns {boolean} - */ -ButtonEdit.prototype.getReadOnly = function () { - return this.control.get('readOnly'); -}; + }, -/** - * @public - * @param {boolean} showClear - */ -ButtonEdit.prototype.setShowClear = function (showClear) { - if (typeof showClear !== 'undefined' && showClear !== null) { - this.control.set('showClear', !!showClear); + onPropertyChanged: function () { + } + + }, 'items'); } -}; -/** - * @public - * @returns {boolean} - */ -ButtonEdit.prototype.getShowClear = function () { - return this.control.get('showClear'); -}; +}, displayFormatBuilderMixin); -ButtonEdit.prototype.onButtonClick = function (handler) { - var element = this; - var callback = function (nativeEventData) { - var eventData = element._getHandlingMouseEventData(nativeEventData); - handler(eventData); - }; - return this.control.onButtonClick(callback); -}; +//####app/elements/_base/editorBase/editorBaseBuilderMixin.js +var editorBaseBuilderMixin = { + initialize_editorBaseBuilder: function () { -//####app/elements/buttonEdit/buttonEditBuilder.js -/** - * - * @constructor - * @augments TextBoxBuilder - */ -function ButtonEditBuilder() { - _.superClass(ButtonEditBuilder, this); -} + }, -window.InfinniUI.ButtonEditBuilder = ButtonEditBuilder; + /** + * + * @param params + * @param {Object} [bindingOptions + * @param {Function} [bindingOptions.converter] Конвертер + * @param {string} [bindingOptions.valueProperty="value'] Имя атрибута значения + * @returns {*} + */ -_.inherit(ButtonEditBuilder, TextBoxBuilder); -ButtonEditBuilder.prototype.createElement = function (params) { - return new ButtonEdit(params.parent); -}; + /** + * + * @param params + * @param bindingOptions + * @returns {{valueBinding: {DataBinding}}} + */ + applyMetadata_editorBaseBuilder: function (params, bindingOptions) { + var metadata = params.metadata; + var element = params.element; -ButtonEditBuilder.prototype.applyMetadata = function (params) { - TextBoxBuilder.prototype.applyMetadata.call(this, params); + bindingOptions = bindingOptions || {}; + bindingOptions.valueProperty = bindingOptions.valueProperty || 'value'; - this.initBindingToProperty(params, 'Icon'); - this.initBindingToProperty(params, 'ReadOnly', true); - this.initBindingToProperty(params, 'ShowClear', true); + element.setLabelFloating(metadata.LabelFloating); + element.setHintText(metadata.HintText); + element.setErrorText(metadata.ErrorText); + element.setWarningText(metadata.WarningText); - this.buildOnButtonClick(params); - this.buildButtonAction(params); -}; + if (metadata.OnValueChanging) { + element.onValueChanging(function (context, args) { + var scriptExecutor = new ScriptExecutor(params.parentView); + return scriptExecutor.executeScript(metadata.OnValueChanging.Name || metadata.OnValueChanging, args); + }); + } + if (metadata.OnValueChanged) { + element.onValueChanged(function (context, args) { + new ScriptExecutor(params.parentView).executeScript(metadata.OnValueChanged.Name || metadata.OnValueChanged, args); + }); + } + + if (metadata.Value !== undefined) { + if (InfinniUI.Metadata.isBindingMetadata(metadata.Value)) { + var buildParams = { + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }; + var dataBinding = params.builder.buildBinding(metadata.Value, buildParams); + var mergedConverter = mergeConverters(dataBinding.getConverter(), bindingOptions.converter); -/** - * @protected - * @param params - */ -ButtonEditBuilder.prototype.buildButtonAction = function (params) { - /** @type {ButtonEdit} **/ - var element = params.element; - var metadata = params.metadata; - var builder = params.builder; + if (mergedConverter) { + dataBinding.setConverter(mergedConverter); + } + if (bindingOptions.mode) { + dataBinding.setMode(bindingOptions.mode); + } + dataBinding.bindElement(params.element, bindingOptions.valueProperty); - if (!metadata.Action) { - return; - } + this.initValidationResultText(element, dataBinding); - var args = { - parentView: params.parentView, - parent: element, - basePathOfProperty: params.basePathOfProperty - }; - var action = builder.build(metadata.Action, args); - element.onButtonClick(function(){ - action.execute(); - }); -}; + } else { + params.element.setValue(metadata.Value); + } + } -/** - * @protected - * @param params - */ -ButtonEditBuilder.prototype.buildOnButtonClick = function (params) { - /** @type {ButtonEdit} **/ - var element = params.element; - var metadata = params.metadata; + function mergeConverters(topPriority, nonPriority) { + topPriority = topPriority || {}; + nonPriority = nonPriority || {}; - var onButtonClick = metadata.OnButtonClick; - if (!onButtonClick) { - return; - } + if(!topPriority.toElement && nonPriority.toElement) { + topPriority.toElement = nonPriority.toElement; + } - element.onButtonClick(function (args) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(onButtonClick.Name || onButtonClick, args); - }); + if(!topPriority.toSource && nonPriority.toSource) { + topPriority.toSource = nonPriority.toSource; + } -}; + if( !topPriority._element && nonPriority._element ) { + topPriority._element = nonPriority._element; + } + return !_.isEmpty(topPriority) ? topPriority : null; + } + return { + valueBinding: dataBinding + }; + }, -//####app/elements/checkBox/checkBox.js -/** - * - * @param parent - * @constructor - * @augment Element - */ -function CheckBox(parent) { - _.superClass(CheckBox, this, parent); - this.initialize_editorBase(); -} + /** + * @description Инициализация подписки на события валидации для оповещения элемента + * @param binding + */ + initValidationResultText: function (element, binding) { + var source = binding.getSource(); + var property = binding.getSourceProperty(); -window.InfinniUI.CheckBox = CheckBox; + if (typeof source.onErrorValidator == 'function') { + source.onErrorValidator(function (context, args) { + var result = args.value, + text = ''; -_.inherit(CheckBox, Element); + if (!result.IsValid && Array.isArray(result.Items)) { + text = getTextForItems(result.Items); + } + element.setErrorText(text); + }); + } -_.extend(CheckBox.prototype, { + function getTextForItems(items, callback) { + return items + .filter(function (item) { + return property === item.Property; + }) + .map(function (item) { + return item.Message; + }) + .join(' '); + } + }, - createControl: function (parent) { - return new CheckBoxControl(parent); - } -}, editorBaseMixin); +}; -//####app/elements/checkBox/checkBoxBuilder.js +//####app/elements/_base/editorBase/editorBaseMixin.js /** * - * @constructor - * @augments ElementBuilder + * @mixin editorBaseMixin */ -function CheckBoxBuilder() { - _.superClass(CheckBoxBuilder, this); - this.initialize_editorBaseBuilder(); -} +var editorBaseMixin = { + initialize_editorBase: function(){ -window.InfinniUI.CheckBoxBuilder = CheckBoxBuilder; + }, -_.inherit(CheckBoxBuilder, ElementBuilder); + getValue: function () { + return this.control.getValue(); + }, + setValue: function (value) { + this.control.setValue(value); + }, -_.extend(CheckBoxBuilder.prototype, { - createElement: function (params) { - return new CheckBox(params.parent); + getLabelFloating: function () { + return this.control.get('labelFloating'); }, - applyMetadata: function (params) { - ElementBuilder.prototype.applyMetadata.call(this, params); - this.applyMetadata_editorBaseBuilder(params); + setLabelFloating: function (value) { + this.control.set('labelFloating', value); + }, - //var element = params.element; - //var metadata = params.metadata; - } -}, editorBaseBuilderMixin); + getHintText: function () { + return this.control.get('hintText'); + }, + setHintText: function (value) { + this.control.set('hintText', value); + }, -//####app/elements/comboBox/comboBox.js -/** - * @augments ListEditorBase - * @param parent - * @constructor - * @mixes labelTextElementMixin - */ -function ComboBox(parent) { - _.superClass(ComboBox, this, parent); -} + getErrorText: function () { + return this.control.get('errorText'); + }, -window.InfinniUI.ComboBox = ComboBox; + setErrorText: function (value) { + this.control.set('errorText', value); + }, -_.inherit(ComboBox, ListEditorBase); + getWarningText: function () { + return this.control.get('warningText'); + }, -_.extend(ComboBox.prototype, labelTextElementMixin); + setWarningText: function (value) { + this.control.set('warningText', value); + }, -ComboBox.prototype.createControl = function () { - return new ComboBoxControl(); -}; -ComboBox.prototype.setValueTemplate = function (value) { - this.control.set('valueTemplate', value); -}; + validateValue: function (value) { -ComboBox.prototype.getValueTemplate = function () { - return this.control.get('valueTemplate'); -}; + }, -ComboBox.prototype.getAutocomplete = function () { - return this.control.get('autocomplete'); -}; + convertValue: function (value) { + return value; + }, -ComboBox.prototype.setAutocomplete = function (value) { - if (typeof value === 'boolean') { - this.control.set('autocomplete', value); - } -}; + onValueChanging: function (handler) { + this.control.onValueChanging( + this.createControlEventHandler(this, handler, {property: 'value'}) + ); + }, -ComboBox.prototype.setShowClear = function (value) { - if (typeof value === 'boolean') { - this.control.set('showClear', value); + onValueChanged: function (handler) { + this.control.onValueChanged( + this.createControlEventHandler(this, handler, {property: 'value'}) + ); } -}; -ComboBox.prototype.getShowClear = function () { - return this.control.get('showClear'); -}; - -ComboBox.prototype.getAutocompleteValue = function () { - return this.control.get('autocompleteValue'); -}; - -ComboBox.prototype.setAutocompleteValue = function (value) { - this.control.set('autocompleteValue', value); }; +//####app/elements/_base/listEditorBase/listEditorBase.js +function ListEditorBase(parent, viewMode) { + _.superClass(ListEditorBase, this, parent, viewMode); - -//####app/elements/comboBox/comboBoxBuilder.js -/** - * @augments ListEditorBaseBuilder - * @constructor - */ -function ComboBoxBuilder() { - _.superClass(ComboBoxBuilder, this); + this.initialize_editorBase(); } -window.InfinniUI.ComboBoxBuilder = ComboBoxBuilder; - -_.inherit(ComboBoxBuilder, ListEditorBaseBuilder); - -_.extend(ComboBoxBuilder.prototype, /** @lends ComboBoxBuilder.prototype */{ - - createElement: function (params) { - return new ComboBox(params.parent); - }, - - applyMetadata: function (params) { - var element = params.element; - var that = this; +window.InfinniUI.ListEditorBase = ListEditorBase; - var data = ListEditorBaseBuilder.prototype.applyMetadata.call(this, params); - this.initValueTemplate(data.valueBinding, params); - this.initBindingToProperty(params, 'LabelText'); - element.setAutocomplete(params.metadata.Autocomplete); - element.setShowClear(params.metadata.ShowClear); +_.inherit(ListEditorBase, Container); - if(params.metadata.Autocomplete){ - var name = element.getName(); - if(!name){ - name = that.generateName(); - element.setName(name); - } - } +_.extend(ListEditorBase.prototype, { + getMultiSelect: function () { + return this.control.get('multiSelect'); }, - initValueTemplate: function (binding, params) { - - var metadata = params.metadata; - var element = params.element; - var valueTemplate; - var property; - - - if ('ValueTemplate' in metadata) { - valueTemplate = this.buildValueTemplate(metadata.ValueTemplate, params); - } else if ('ValueFormat' in metadata) { - valueTemplate = this.buildValueTemplateByFormat(binding, metadata.ValueFormat, params); - } else { - valueTemplate = this.buildValueTemplateByDefault(binding, params); - } - - element.setValueTemplate(valueTemplate); + setMultiSelect: function (value) { + this.control.set('multiSelect', value); }, - buildValueTemplate: function (templateMetadata, params) { - var element = params.element; - var builder = params.builder; - var basePathOfProperty = params.basePathOfProperty || new BasePathOfProperty(''); - var that = this; - - return function (context, args) { - var index = args.index; - var bindingIndex; - var argumentForBuilder = { - parent: params.element, - parentView: params.parentView - }; - - if (index !== undefined && index !== null) { - //bindingIndex = that.bindingIndexByItemsIndex(index, params); - bindingIndex = index; - - if (bindingIndex !== undefined && bindingIndex !== null) { - argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild('', bindingIndex); - } else { - argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild('', index); - } - } + getValueSelector: function () { + return this.control.get('valueSelector'); + }, - return builder.build(templateMetadata, argumentForBuilder); - }; + setValueSelector: function (value) { + this.control.set('valueSelector', value); }, - buildValueTemplateByFormat: function (binding, valueFormatMetadata, params) { - var format = this.buildDisplayFormat(valueFormatMetadata, params); - return function (context, args) { - var index = args.index; - var value = args.value; + getDisabledItemCondition: function () { + return this.control.get('disabledItemCondition'); + }, - var label = new Label(this); - label.setHorizontalAlignment('Left'); - label.setDisplayFormat(format); - label.setValue(value); - return label; - }; + setDisabledItemCondition: function (value) { + this.control.set('disabledItemCondition', value); }, - buildValueTemplateByDefault: function (binding, params) { + setValueItem: function(item){ + var result; + var isMultiSelect = this.getMultiSelect(); + var valueSelector = this.getValueSelector(); - return function (context, args) { - var index = args.index; - var value = args.value; + if(isMultiSelect){ + result = []; - var label = new Label(this); - label.setHorizontalAlignment('Left'); - label.setValue(value); + for(var i = 0, ii = item.length; i < ii; i++){ + result[i] = valueSelector(null, {value: item[i]}); + } - return label; - }; + }else{ + result = valueSelector(null, {value: item}); + } + + this.setValue(result); }, - generateName: function(){ - return 'combobox-' + guid(); + getSelectedItem: function () { + return this.control.get('selectedItem'); + }, + + setSelectedItem: function (value) { + this.control.set('selectedItem', value); + }, + + onSelectedItemChanged: function (handler) { + this.control.onSelectedItemChanged(this.createControlEventHandler(this, handler)); } -}); -//####app/elements/contextMenu/contextMenu.js -/** - * @class - * @constructor - * @arguments Container - */ -function ContextMenu(parent) { - _.superClass(ContextMenu, this, parent); -} + // UNUSED ? + //getValueComparator: function () { + // return this.control.get('valueComparator'); + //} -window.InfinniUI.ContextMenu = ContextMenu; +}, editorBaseMixin); -_.inherit(ContextMenu, Container); +//####app/elements/_base/listEditorBase/listEditorBaseBuilder.js +function ListEditorBaseBuilder() { + _.superClass(ListEditorBaseBuilder, this); -_.extend(ContextMenu.prototype, { + this.initialize_editorBaseBuilder(); +} - createControl: function () { - return new ContextMenuControl(); - } +window.InfinniUI.ListEditorBaseBuilder = ListEditorBaseBuilder; -}); +_.inherit(ListEditorBaseBuilder, ContainerBuilder); -//####app/elements/contextMenu/contextMenuBuilder.js -/** - * @constructor - * @arguments ContainerBuilder - */ -function ContextMenuBuilder() { - _.superClass(ContextMenuBuilder, this); -} -window.InfinniUI.ContextMenuBuilder = ContextMenuBuilder; +_.extend(ListEditorBaseBuilder.prototype, { -_.inherit(ContextMenuBuilder, ContainerBuilder); + applyMetadata: function (params) { -_.extend(ContextMenuBuilder.prototype, /** @lends ContextMenuBuilder.prototype */{ + var applyingMetadataResult = ContainerBuilder.prototype.applyMetadata.call(this, params), + itemsBinding = applyingMetadataResult.itemsBinding, + applyingMetadataResult2; - createElement: function (params) { - return new ContextMenu(params.parent); - }, + this.initSelecting(params, itemsBinding); + this.initDisabledItemCondition(params); - applyMetadata: function (params) { - ContainerBuilder.prototype.applyMetadata.call(this, params); - } + this.initValueFeatures(params); -}); + applyingMetadataResult2 = this.applyMetadata_editorBaseBuilder(params); + return _.extend(applyingMetadataResult, applyingMetadataResult2); + }, -//####app/elements/dataGrid/dataGrid.js -function DataGrid(parent) { - _.superClass(DataGrid, this, parent); -} -window.InfinniUI.DataGrid = DataGrid; + initSelecting: function(params, itemsBinding){ + var metadata = params.metadata; + var element = params.element; + var source = itemsBinding.getSource(); + var sourceProperty = itemsBinding.getSourceProperty(); + var isBindingOnWholeDS = sourceProperty == '', + sourceIsDataSource = source instanceof InfinniUI.BaseDataSource; -_.inherit(DataGrid, ListEditorBase); + if(sourceIsDataSource && isBindingOnWholeDS){ + source.setSelectedItem(null); -/** - * Возвращает коллекцию колонок таблицы {@see DataGridColumn} - * @returns {Collection} - */ -DataGrid.prototype.getColumns = function () { - return this.control.get('columns'); -}; + source.onSelectedItemChanged(function(context, args){ + var currentSelectedItem = element.getSelectedItem(), + newSelectedItem = args.value; -DataGrid.prototype.setShowSelectors = function (value) { - if (typeof value !== 'undefined' && value !== null) { - this.control.set('showSelectors', !!value); - } -}; + if(newSelectedItem != currentSelectedItem){ + element.setSelectedItem(newSelectedItem); + } + }); + } -DataGrid.prototype.getShowSelectors = function () { - return this.control.get('showSelectors'); -}; + element.onSelectedItemChanged(function(context, args){ -DataGrid.prototype.createRow = function () { - return new DataGridRow(this); -}; + if(sourceIsDataSource && isBindingOnWholeDS) { + var currentSelectedItem = source.getSelectedItem(), + newSelectedItem = args.value; -DataGrid.prototype.setEnabled = function (value) { - if( _.isBoolean(value) ) { - this.control.setEnabled(value); - } -}; + if (newSelectedItem != currentSelectedItem) { + source.setSelectedItem(newSelectedItem); + } + } -/** - * @description Устанавливает значение, определяющее виден ли элемент "Выбрать все" в шапке таблицы. - * @param {boolean} value - */ -DataGrid.prototype.setCheckAllVisible = function (value) { - if (_.isBoolean(value)) { - this.control.set('checkAllVisible', value); - } -}; + if (metadata.OnSelectedItemChanged) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnSelectedItemChanged.Name || metadata.OnSelectedItemChanged, args); + } + }); + }, -/** - * @description Возвращает значение, определяющее виден ли элемент "Выбрать все" в шапке таблицы. - * @returns {boolean} - */ -DataGrid.prototype.getCheckAllVisible = function () { - return this.control.get('checkAllVisible'); -}; + initValueFeatures: function(params){ + var metadata = params.metadata; + var element = params.element; -/** - * @description Возвращает состояние элемента "Выбрать все" из шапки таблицы - * @returns {boolean} - */ -DataGrid.prototype.getCheckAll = function () { - return this.control.get('checkAll'); -}; + if (typeof metadata.MultiSelect !== 'undefined' && metadata.MultiSelect !== null) { + element.setMultiSelect(metadata.MultiSelect); + } -/** - * @description Устанавливает обработчик события о том, что изменилось состояние элемента "Выбрать все" в шапке таблицы - * @param {function} handler - */ -DataGrid.prototype.onCheckAllChanged = function (handler) { - this.control.onCheckAllChanged(this.createControlEventHandler(this, handler)); -}; + this.initValueSelector(params); + }, -DataGrid.prototype.createControl = function () { - return new DataGridControl(); -}; + initValueSelector: function (params) { + var metadata = params.metadata, + element = params.element, + valueSelector; + + if (metadata.ValueSelector) { + valueSelector = function (context, args) { + var scriptExecutor = new ScriptExecutor(params.element.getScriptsStorage()); + return scriptExecutor.executeScript(metadata.ValueSelector.Name || metadata.ValueSelector, args) + }; + } else if (metadata.ValueProperty) { + valueSelector = function (context, args) { + return InfinniUI.ObjectUtils.getPropertyValue(args.value, metadata.ValueProperty); + } + } else { + valueSelector = function (context, args) { + return args.value; + } + } + element.setValueSelector(valueSelector); + }, + initDisabledItemCondition: function (params) { + var metadata = params.metadata, + element = params.element, + disabledItemCondition; -DataGrid.prototype.onRowClick = function (handler) { - var that = this, - callback = function (nativeEventData) { - var eventData = that._getHandlingMouseEventData(nativeEventData); - handler(eventData); - }; - return this.control.onRowClick(callback); -}; + if (metadata.DisabledItemCondition) { + disabledItemCondition = function (context, args) { + var scriptExecutor = new ScriptExecutor(element.getScriptsStorage()); + return scriptExecutor.executeScript(metadata.DisabledItemCondition.Name || metadata.DisabledItemCondition, args) + }; + } -DataGrid.prototype.onRowDoubleClick = function (handler) { - var that = this, - callback = function (nativeEventData) { - var eventData = that._getHandlingMouseEventData(nativeEventData); - handler(eventData); - }; - return this.control.onRowDoubleClick(callback); -}; + element.setDisabledItemCondition(disabledItemCondition); + } +}, editorBaseBuilderMixin); -//####app/elements/dataGrid/dataGridBuilder.js -function DataGridBuilder() { - _.superClass(DataGridBuilder, this); - this.columnBuilder = new DataGridColumnBuilder(); +//####app/elements/_base/textEditorBase/textEditorBase.js +/** + * + * @param parent + * @constructor + * @augments Element + * @mixes editorBaseMixin + * @mixes labelTextElementMixin + */ +function TextEditorBase(parent) { + _.superClass(TextEditorBase, this, parent); + this.initialize_editorBase(); } -window.InfinniUI.DataGridBuilder = DataGridBuilder; +window.InfinniUI.TextEditorBase = TextEditorBase; -_.inherit(DataGridBuilder, ListEditorBaseBuilder); +_.inherit(TextEditorBase, Element); -_.extend(DataGridBuilder.prototype, /** @lends DataGridBuilder.prototype */{ +_.extend(TextEditorBase.prototype, { - createElement: function (params) { - return new DataGrid(params.parent); + setEditor: function (editor) { + this.control.set('editor', editor); }, - applyMetadata: function (params) { - ListEditorBaseBuilder.prototype.applyMetadata.call(this, params); + setDisplayFormat: function (value) { + this.control.set('displayFormat', value); + }, - var metadata = params.metadata; - /** @type DataGrid **/ - var element = params.element; - element.setShowSelectors(metadata.ShowSelectors); - element.setCheckAllVisible(metadata.CheckAllVisible); + getDisplayFormat: function () { + return this.control.get('displayFormat'); + }, - if(metadata.OnCheckAllChanged){ - element.onCheckAllChanged(function(context, args) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnCheckAllChanged.Name || metadata.OnCheckAllChanged, args); - }); - } + setEditMask: function (value) { + this.control.set('editMask', value); + }, - if( metadata.OnRowClick ) { - element.onRowClick(function (args) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnRowClick.Name || metadata.OnRowClick, args); - }); - } + getEditMask: function () { + return this.control.get('editMask'); + }, - if( metadata.OnRowDoubleClick ) { - element.onRowDoubleClick(function (args) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnRowDoubleClick.Name || metadata.OnRowDoubleClick, args); - }); - } + /** + * @description Возвращает значение, которое введено в поле редактирования в данный момент + * @returns {*} + */ + getRawValue: function () { + var value = this.control.get('editor').getValue(), + editMask = this.getEditMask(); - this.applyColumnsMetadata(params); - }, + if (editMask) { + var val = editMask.getValue(); + var txt = editMask.getText(); - applyColumnsMetadata: function (params) { - var metadata = params.metadata, - element = params.element, - collection = element.getColumns(); + if (isNotEmpty(val)) { + value = val; + } else if (isNotEmpty(txt)) { + value = txt; + } + } - if (Array.isArray(metadata.Columns)) { - var columns = metadata.Columns.map(function (columnMetaData) { - return this.buildColumn(columnMetaData, params); - }, this); + return value; - collection.reset(columns); + function isNotEmpty(val) { + return val !== null && typeof val !== 'undefined'; } - }, - buildColumn: function (metadata, params) { - return this.columnBuilder.build(params.element, metadata, params); + getInputType: function () { + return this.control.get('inputType'); }, - buildItemProperty: function (itemsBinding, itemPropertyMetadata, params) { - var dataGrid = params.element; - var builder = this; - - return function (context, args) { - var row = dataGrid.createRow(); - row.setGrid(dataGrid); - - ['RowStyle', 'RowBackground', 'RowForeground', 'RowTextStyle'] - .forEach(initBindingToRowProperty.bind(null, row, args.index)); - - var columns = dataGrid.getColumns(); - - var cellItemTemplates = columns.toArray().map(function (column, index) { - var cellTemplate = column.getCellTemplate(); - var template = cellTemplate(itemsBinding); - return template.bind(column, context, args); - }); - row.setCellTemplates(cellItemTemplates); - row.setMultiSelect(dataGrid.getMultiSelect()); - row.setShowSelectors(dataGrid.getShowSelectors()); - return row; - }; - - function initBindingToRowProperty(row, index, propertyName) { - var basePathOfProperty = params.basePathOfProperty || new BasePathOfProperty(''); - var argumentForBuilder = { - element: row, - parent: dataGrid, - builder: params.builder, - metadata: params.metadata, - parentView: params.parentView - }; - argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild('', index); - - builder.initBindingToProperty(argumentForBuilder, propertyName); + setInputType: function (inputType) { + if (inputType) { + this.control.set('inputType', inputType); } } -}); +}, editorBaseMixin, labelTextElementMixin); -//####app/elements/dataGrid/dataGridColumn.js -function DataGridColumn() { - this._values = Object.create(null); +//####app/elements/_base/textEditorBase/textEditorBaseBuilder.js +/** + * + * @constructor + * @augments ElementBuilder + * @mixes editorBaseBuilderMixin + * @mixes displayFormatBuilderMixin + * + */ +function TextEditorBaseBuilder() { + _.superClass(TextEditorBaseBuilder, this); + this.initialize_editorBaseBuilder(); } -DataGridColumn.prototype.setHeader = function (value) { - this.setProperty('header', value); -}; - -DataGridColumn.prototype.getHeader = function () { - return this.getProperty('header'); -}; - -DataGridColumn.prototype.setCellTemplate = function (value) { - this.setProperty('cellTemplate', value); -}; - -DataGridColumn.prototype.getCellTemplate = function () { - return this.getProperty('cellTemplate'); -}; +window.InfinniUI.TextEditorBaseBuilder = TextEditorBaseBuilder; -DataGridColumn.prototype.setCellSelector = function (value) { - this.setProperty('cellSelector', value); -}; +_.inherit(TextEditorBaseBuilder, ElementBuilder); -DataGridColumn.prototype.getCellSelector = function () { - return this.getProperty('cellSelector'); -}; +_.extend(TextEditorBaseBuilder.prototype, { -DataGridColumn.prototype.setHeaderTemplate = function (value) { - this.setProperty('cellHeaderTemplate', value); -}; + applyMetadata: function (params) { + ElementBuilder.prototype.applyMetadata.call(this, params); + this.applyMetadata_editorBaseBuilder(params); -DataGridColumn.prototype.getHeaderTemplate = function () { - return this.getProperty('cellHeaderTemplate'); -}; + var metadata = params.metadata; + var element = params.element; -DataGridColumn.prototype.setWidth = function (value) { - this.setProperty('width', value); -}; + this.initBindingToProperty(params, 'LabelText'); -DataGridColumn.prototype.getWidth = function (value) { - return this.getProperty('width'); -}; + element.setInputType(this.getCompatibleInputType(params)); + this + .initDisplayFormat(params) + .initEditMask(params) + .initEditor(params); + }, -DataGridColumn.prototype.setSortable = function (value) { - this.setProperty('sortable', value); -}; + getCompatibleInputType: function (params) { + var inputType = params.metadata.Type, + editMask = params.metadata.EditMask; -DataGridColumn.prototype.getSortable = function () { - return this.getProperty('sortable'); -}; + if (typeof inputType === 'undefined') { + inputType = params.element.getInputType(); + } -DataGridColumn.prototype.isSortable = function () { - return this.getSortable(); -}; + if (editMask) { + //Маска редактирования задается только для input[type=text] + inputType = 'text' + } + return inputType; + }, -DataGridColumn.prototype.setSortDirection = function (value) { - this.setProperty('sortDirection', value); -}; + initEditor: function (params) { + var element = params.element; + var editor = new TextEditor(); + editor + .setDisplayFormat(element.getDisplayFormat()) + .setEditMask(element.getEditMask()) + .setValueConverter(function () { + return element.convertValue.bind(element) + }) + .setValidatorValue(element.validateValue.bind(element)); -DataGridColumn.prototype.getSortDirection = function () { - return this.getProperty('sortDirection'); -}; + element.setEditor(editor); -DataGridColumn.prototype.setSortFunction = function (handler) { - this.setProperty('sortFunction', handler); -}; + editor.onValueChanged(function (value) { + //element.setValue(element.convertValue(value)); + element.setValue(value); + }); -DataGridColumn.prototype.getSortFunction = function () { - return this.getProperty('sortFunction'); -}; + element.onValueChanged(function (context, args) { + editor.setValue(args.newValue); + }); -DataGridColumn.prototype.setIsHeaderTemplateEmpty = function (value) { - this.setProperty('isHeaderTemplateEmpty', value); -}; + editor.setValue(element.getValue()); -DataGridColumn.prototype.getIsHeaderTemplateEmpty = function () { - return this.getProperty('isHeaderTemplateEmpty'); -}; + return this; + }, -DataGridColumn.prototype.onSort = function (handler) { - var that = this, - callback = function (nativeEventData) { - handler(nativeEventData); - }; - this.on('onSort', callback); -}; + initDisplayFormat: function (params) { + var + metadata = params.metadata, + format = this.buildDisplayFormat(metadata.DisplayFormat, params); -/** - * @description Для взаимодействие с DataBinding - * @param propertyName - * @param callback - */ -DataGridColumn.prototype.onPropertyChanged = function (propertyName, callback) { - this.on('change:' + propertyName, callback); -}; + params.element.setDisplayFormat(format); + return this; + }, -/** - * @description Для взаимодействие с DataBinding - * @param propertyName - * @param propertyValue - */ -DataGridColumn.prototype.setProperty = function (propertyName, propertyValue) { - var oldValue = this._values[propertyName]; + initEditMask: function (params) { + var + metadata = params.metadata, + builder = params.builder, + editMask; - this._values[propertyName] = propertyValue; - if (oldValue !== propertyValue) { - this.trigger('change:' + propertyName, null, { - property: propertyName, - oldValue: oldValue, - newValue: propertyValue - }); + if (metadata.EditMask) { + editMask = builder.build(metadata.EditMask, { + parentView: params.parentView, + formatOptions: params.formatOptions + }); + } + params.element.setEditMask(editMask); + return this; } -}; +}, editorBaseBuilderMixin, displayFormatBuilderMixin); -DataGridColumn.prototype.getProperty = function (propertyName) { - return this._values[propertyName]; -}; -_.extend(DataGridColumn.prototype, Backbone.Events); -//####app/elements/dataGrid/dataGridColumnBuilder.js -/** - * - * @constructor - */ -function DataGridColumnBuilder () { +//####app/elements/_base/textEditor/textEditor.js +/** + * @constructor + */ + +var TextEditor = function () { + var model = new TextEditorModel(); + + model.on('invalid', function (model, error) { + console.log('error', error); + }); + + //@TODO Handle Enabled state + + this._model = model; + +}; + +window.InfinniUI.TextEditor = TextEditor; + +TextEditor.prototype.setDisplayFormat = function (displayFormat) { + this._model.set('displayFormat', displayFormat); + return this; +}; + +TextEditor.prototype.setEditMask = function (editMask) { + this._model.set('editMask', editMask); + return this; +}; + +TextEditor.prototype.setValidatorValue = function (validatorValue) { + this._model.set('validateValue', validatorValue); + return this; +}; + +TextEditor.prototype.setValueConverter = function (converter) { + this._model.set('valueConverter', converter); + return this; +}; + +TextEditor.prototype.getValue = function() { + return this._model.getValue(); +}; + +/** + * + * @param {HTMLInputElement} inputElement + * @returns {*} + */ +TextEditor.prototype.render = function (inputElement) { + + this._view = new TextEditorView({ + model: this._model, + el: inputElement + }); + + //return this._view.render(); +}; + +TextEditor.prototype.setValue = function (value) { + this._model.set('originalValue', value, {originalValue: true}); + return this; +}; + +TextEditor.prototype.onValueChanged = function (handler) { + this._model.on('change:originalValue', function (model, value, options) { + if (options.originalValue === true) { + return; + } + + handler.call(null, value); + }); +}; +//####app/elements/listBox/listBox.js +function ListBox(parent, viewMode) { + _.superClass(ListBox, this, parent, viewMode); } -_.extend(DataGridColumnBuilder.prototype, displayFormatBuilderMixin); - -/** - * - * @param {DataGrid} element - * @param {Object} metadata метаданные колонки грида - * @param {Object} params - * @returns {DataGridColumn} - */ -DataGridColumnBuilder.prototype.build = function (element, metadata, params) { - var column = new DataGridColumn(); - - - this - .buildHeader(column, metadata, params) - .buildHeaderTemplate(column, metadata, params) - .buildCellTemplate(column, metadata, params) - .buildWidth(column, metadata); - - if( metadata.Sortable ) { - column.setSortable(true); - column.setSortDirection( null ); - if( metadata.SortedDefault && ( metadata.SortedDefault === 'asc' || metadata.SortedDefault === 'desc' ) ) { - column.setSortDirection( metadata.SortedDefault ); - } +window.InfinniUI.ListBox = ListBox; - if (metadata.SortFunction) { - column.onSort(function (args) { - new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.SortFunction.Name || metadata.SortFunction, args); - }); - } - } +_.inherit(ListBox, ListEditorBase); - return column; +ListBox.prototype.createControl = function (viewMode) { + return new ListBoxControl(viewMode); }; -DataGridColumnBuilder.prototype.buildWidth = function (column, metadata) { - var width = metadata.Width; - - if (width !== null && typeof width !== 'undefined') { - column.setWidth(width); - } - - return this; +ListBox.prototype.setEnabled = function (value) { + if( _.isBoolean(value) ) { + ListEditorBase.prototype.setEnabled.call(this, value); + if( value ) { + this.control.updateDisabledItem(); + } else { + this.control.disableAll(); + } + } }; -/** - * @protected - * @param {DataGridColumn} column - * @param {Object} metadata - * @param {Object} params - * @returns {DataGridColumnBuilder} - */ -DataGridColumnBuilder.prototype.buildHeader = function (column, metadata, params) { - - if (metadata.Header && typeof metadata.Header === 'object') { - //Header указывает на DataBinding - var - builder = params.builder, - binding = builder.buildType('PropertyBinding', metadata.Header, { - parent: params.element, - parentView: params.parentView, - basePathOfProperty: params.basePathOfProperty - }); - - binding.bindElement(column, 'header'); - } else { - //Header содержит значение для шаблона - column.setHeader(metadata.Header); - } - return this; -}; +//####app/elements/listBox/listBoxBuilder.js +function ListBoxBuilder() { + _.superClass(ListBoxBuilder, this); +} + +window.InfinniUI.ListBoxBuilder = ListBoxBuilder; + +_.inherit(ListBoxBuilder, ListEditorBaseBuilder); + +_.extend(ListBoxBuilder.prototype, /** @lends ListBoxBuilder.prototype */{ + + createElement: function (params) { + return new ListBox(params.parent, params.metadata['ViewMode']); + }, + + applyMetadata: function (params) { + ListEditorBaseBuilder.prototype.applyMetadata.call(this, params); + } + +}); -/** - * @protected - * @param {DataGridColumn} column - * @param {Object} metadata - * @param {Object} params - * @returns {DataGridColumnBuilder} - */ -DataGridColumnBuilder.prototype.buildCellTemplate = function (column, metadata, params) { - var cellTemplate; - - if ('CellTemplate' in metadata) { - cellTemplate = this.buildCellTemplateByTemplate(params, metadata.CellTemplate); - } else if ('CellFormat' in metadata) { - cellTemplate = this.buildCellTemplateByFormat(params, metadata.CellFormat); - } else if ('CellSelector' in metadata) { - cellTemplate = this.buildCellTemplateBySelector(params, metadata.CellSelector); - } else { - var cellProperty = 'CellProperty' in metadata ? metadata.CellProperty : ''; - cellTemplate = this.buildCellTemplateByDefault(params, cellProperty); - } - column.setCellTemplate(cellTemplate); - return this; -}; +//####app/elements/textBox/textBox.js +/** + * + * @param parent + * @constructor + * @augments TextEditorBase + */ +function TextBox(parent) { + _.superClass(TextBox, this, parent); +} + +window.InfinniUI.TextBox = TextBox; + +_.inherit(TextBox, TextEditorBase); + +_.extend(TextBox.prototype, { + createControl: function (parent) { + return new TextBoxControl(parent); + }, + + getMultiline: function () { + return this.control.get('multiline'); + }, + + setMultiline: function (value) { + this.control.set('multiline', value); + }, + + getLineCount: function () { + return this.control.get('lineCount'); + }, + + setLineCount: function (value) { + this.control.set('lineCount', value); + } + +}); + + -DataGridColumnBuilder.prototype.buildCellTemplateByTemplate = function (params, cellTemplateMetadata) { - var dataGrid = params.element; - var builder = params.builder; - var basePathOfProperty = params.basePathOfProperty || new BasePathOfProperty(''); +//####app/elements/textBox/textBoxBuilder.js +/** + * + * @constructor + * @augments TextEditorBaseBuilder + */ +function TextBoxBuilder() { + _.superClass(TextBoxBuilder, this); +} + +window.InfinniUI.TextBoxBuilder = TextBoxBuilder; + +_.inherit(TextBoxBuilder, TextEditorBaseBuilder); + +TextBoxBuilder.prototype.createElement = function (params) { + return new TextBox(params.parent); +}; + +TextBoxBuilder.prototype.applyMetadata = function (params) { + TextEditorBaseBuilder.prototype.applyMetadata.call(this, params); + + var element = params.element; + var metadata = params.metadata; + var lineCount = metadata.LineCount; + element.setMultiline(metadata.Multiline); + if (metadata.Multiline && lineCount === null || typeof lineCount === 'undefined') { + lineCount = 2; + } + element.setLineCount(lineCount); +}; - return function (itemsBinding) { - return function (context, args) { - var index = args.index; - var argumentForBuilder = { - parent: dataGrid, - parentView: params.parentView - }; - argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild('', index); +//####app/elements/dateTimePicker/dateTimePicker.js +/** + * + * @param parent + * @constructor + * @augments TextEditorBase + */ +function DateTimePicker(parent) { + _.superClass(DateTimePicker, this, parent); +} + +window.InfinniUI.DateTimePicker = DateTimePicker; + +_.inherit(DateTimePicker, TextEditorBase); + +DateTimePicker.prototype.createControl = function (parent) { + return new DateTimePickerControl(parent); +}; + +DateTimePicker.prototype.getMinValue = function () { + return this.control.get('minValue'); +}; + +DateTimePicker.prototype.setMinValue = function (value) { + this.control.set('minValue', value); +}; + +DateTimePicker.prototype.getMaxValue = function () { + return this.control.get('maxValue'); +}; + +DateTimePicker.prototype.setMaxValue = function (value) { + this.control.set('maxValue', value); +}; + +DateTimePicker.prototype.getMode = function () { + return this.control.get('mode'); +}; + +DateTimePicker.prototype.setMode = function (value) { + this.control.set('mode', value); +}; + +DateTimePicker.prototype.getTimeZone = function () { + return this.control.get('timeZone'); +}; + +DateTimePicker.prototype.setTimeZone = function (value) { + if (_.isNumber(value)) { + this.control.set('timeZone', value); + } +}; + +DateTimePicker.prototype.setDateFormat = function (value) { + this.control.set('format', value); +}; + +DateTimePicker.prototype.validateValue = function (value) { + if (value === null || value === '' || typeof value === 'undefined') { + return; + } + + var minValue = InfinniUI.DateUtils.restoreTimezoneOffset(this.getMinValue(), this.getTimeZone()); + var maxValue = InfinniUI.DateUtils.restoreTimezoneOffset(this.getMaxValue(), this.getTimeZone()); + + var isValid = InfinniUI.DateUtils.checkRangeDate(value, minValue, maxValue); + + if (!isValid) { + return "Неверное значение"; + } +}; + + - return builder.build(cellTemplateMetadata, argumentForBuilder); - } +//####app/elements/dateTimePicker/dateTimePickerBuilder.js +/** + * + * @constructor + * @augments TextEditorBaseBuilder + */ +function DateTimePickerBuilder() { + _.superClass(DateTimePickerBuilder, this); +} + +window.InfinniUI.DateTimePickerBuilder = DateTimePickerBuilder; + +_.inherit(DateTimePickerBuilder, TextEditorBaseBuilder); + +DateTimePickerBuilder.prototype.createElement = function (params) { + return new DateTimePicker(params.parent); +}; + +DateTimePickerBuilder.prototype.applyMetadata = function (params) { + var element = params.element; + + this.applyDefaultMetadata(params); + var metadata = params.metadata; + + TextEditorBaseBuilder.prototype.applyMetadata.call(this, params); + + element.setTimeZone(metadata.TimeZone); + element.setMode(metadata.Mode); + + this.applyMinValue(element, metadata.MinValue); + this.applyMaxValue(element, metadata.MaxValue); + + //var format = params.builder.buildType(params.parent, 'DateFormat', {}, null); + //element.setDateFormat(format); +}; + +DateTimePickerBuilder.prototype.applyMinValue = function (element, minValue) { + element.setMinValue(InfinniUI.DateUtils.parseISO8601toDate(minValue)); +}; + +DateTimePickerBuilder.prototype.applyMaxValue = function (element, maxValue) { + element.setMaxValue(InfinniUI.DateUtils.parseISO8601toDate(maxValue)); +}; + +DateTimePickerBuilder.prototype.applyDefaultMetadata = function (params) { + var metadata = params.metadata; + var defaultFormat = { + Date: '{:d}', + DateTime: '{:g}', + Time: '{:T}' + }, + defaultEditMask = { + Date: {DateTimeEditMask: {Mask: 'd'}}, + DateTime: {DateTimeEditMask: {Mask: 'g'}}, + Time: {DateTimeEditMask: {Mask: 'T'}} + }; + + params.metadata = _.extend({}, metadata); + + _.defaults(params.metadata, {Mode: 'Date'}); + _.defaults(params.metadata, { + DisplayFormat: defaultFormat[params.metadata.Mode], + EditMask: defaultEditMask[params.metadata.Mode] + }); +}; + +DateTimePickerBuilder.prototype.initDisplayFormat = function (params) { + return TextEditorBaseBuilder.prototype.initDisplayFormat.call(this, this.applyTimeZone(params)); +}; + +DateTimePickerBuilder.prototype.initEditMask = function (params) { + return TextEditorBaseBuilder.prototype.initEditMask.call(this, this.applyTimeZone(params)); +}; + +DateTimePickerBuilder.prototype.applyTimeZone = function (params) { + var metadata = params.metadata; + var _params = {}; + var formatOptions = {}; + + if (typeof metadata.TimeZone !== 'undefined' && metadata.TimeZone !== null ) { + formatOptions.TimeZone = metadata.TimeZone; + } + + _.defaults(_params, params, {formatOptions: formatOptions}); + return _params; +}; - }; -}; +//####app/elements/datePicker/datePicker.js +function DatePicker(parent) { + _.superClass(DatePicker, this, parent); + + this.setMode('DatePicker'); + this.setTimeZone(); +} + +window.InfinniUI.DatePicker = DatePicker; + +_.inherit(DatePicker, DateTimePicker); + +DatePicker.prototype.setTimeZone = function () { + DateTimePicker.prototype.setTimeZone.call(this, 0); +}; + +DatePicker.prototype.createControl = function (parent) { + return new DatePickerControl(parent); +}; + +DatePicker.prototype.convertValue = function (value) { + var _value = null; + + if(typeof value === 'undefined' || value === null || !value.toString().length) { + _value = null; + } else { + _value = InfinniUI.DateUtils.dateToTimestamp(value); + } + + return _value; +}; -DataGridColumnBuilder.prototype.buildCellTemplateByFormat = function (params, cellFormatMetadata) { - var column = params.element, - grid = column.parent, - format = this.buildDisplayFormat(cellFormatMetadata, params); +//####app/elements/datePicker/datePickerBuilder.js +function DatePickerBuilder() { + _.superClass(DatePickerBuilder, this); +} + +window.InfinniUI.DatePickerBuilder = DatePickerBuilder; + +_.inherit(DatePickerBuilder, DateTimePickerBuilder); + +DatePickerBuilder.prototype.createElement = function (params) { + return new DatePicker(params.parent); +}; + + +DatePickerBuilder.prototype.applyDefaultMetadata = function (params) { + + params.metadata = _.extend({}, params.metadata, { + Mode: 'DatePicker', + TimeZone: 0 + }); + + _.defaults(params.metadata, { + DisplayFormat: '{:d}', + EditMask: {DateTimeEditMask: {Mask: 'd'}} + }); +}; - return function (itemsBinding) { - return function (context, args) { - var index = args.index; - var label = new Label(this); +//####app/elements/timePicker/timePicker.js +function TimePicker(parent) { + _.superClass(TimePicker, this, parent); - var sourceProperty = itemsBinding.getSourceProperty(); - var source = itemsBinding.getSource(); - var binding = new DataBinding(); + this.setMode('TimePicker'); + this.setTimeZone(); +} - sourceProperty = index.toString(); - if (itemsBinding.getSourceProperty() != '') { - sourceProperty = itemsBinding.getSourceProperty() + '.' + sourceProperty; - } +window.InfinniUI.TimePicker = TimePicker; - label.setDisplayFormat(format); +_.inherit(TimePicker, DateTimePicker); - binding.bindSource(source, sourceProperty); - binding.bindElement(label, 'value'); - return label; - }; - }; +TimePicker.prototype.createControl = function (parent) { + return new TimePickerControl(parent); +}; +TimePicker.prototype.setTimeZone = function () { + DateTimePicker.prototype.setTimeZone.call(this, 0); }; -DataGridColumnBuilder.prototype.buildCellTemplateBySelector = function (params, cellSelectorMetadata) { - var column = params.element, - grid = column.parent; +TimePicker.prototype.convertValue = function (value) { + var _value = null; - return function () { - return function (context, args) { - var label = new Label(this); - var scriptExecutor = new ScriptExecutor(grid.getScriptsStorage()); - var value = scriptExecutor.executeScript(cellSelectorMetadata.Name || cellSelectorMetadata, { - value: args.item - }); + if(typeof value === 'undefined' || value === null || !value.toString().length) { + _value = null; + } else { + _value = InfinniUI.DateUtils.dateToTimestampTime(value); + } - label.setText(value); - return label; - }; - }; + return _value; }; -DataGridColumnBuilder.prototype.buildCellTemplateByDefault = function (params, cellProperty) { - var column = params.element, - grid = column.parent; - - return function (itemsBinding) { +//####app/elements/timePicker/timePickerBuilder.js +function TimePickerBuilder() { + _.superClass(TimePickerBuilder, this); +} + +window.InfinniUI.TimePickerBuilder = TimePickerBuilder; + +_.inherit(TimePickerBuilder, DateTimePickerBuilder); + +TimePickerBuilder.prototype.createElement = function (params) { + return new TimePicker(params.parent); +}; + +TimePickerBuilder.prototype.applyDefaultMetadata = function (params) { + + params.metadata = _.extend({}, params.metadata, { + Mode: 'TimePicker', + TimeZone: 0 + }); + + _.defaults(params.metadata, { + DisplayFormat: '{:T}', + EditMask: { + DateTimeEditMask: { + Mask: 'T' + } + } + }); + +}; + +TimePickerBuilder.prototype.applyMinValue = function (element, minValue) { + var date = InfinniUI.DateUtils.parseTimeISO8601toDate(minValue, 0); + + if (typeof date !== 'undefined') { + element.setMinValue(date); + } +}; + +TimePickerBuilder.prototype.applyMaxValue = function (element, maxValue) { + var date = InfinniUI.DateUtils.parseTimeISO8601toDate(maxValue, 0); + + if (typeof date !== 'undefined') { + element.setMaxValue(date); + } +}; - return function (context, args) { - var index = args.index; - var label = new Label(grid); +//####app/elements/stackPanel/stackPanel.js +/** + * @param parent + * @constructor + * @augments Container + */ +function StackPanel(parent, viewMode) { + _.superClass(StackPanel, this, parent, viewMode); +} + +window.InfinniUI.StackPanel = StackPanel; + +_.inherit(StackPanel, Container); + +StackPanel.prototype.getOrientation = function () { + return this.control.get('orientation'); +}; + +StackPanel.prototype.setOrientation = function (value) { + if (InfinniUI.Metadata.isValidValue(value, InfinniUI.StackPanelOrientation)) { + this.control.set('orientation', value) + } +}; + +StackPanel.prototype.createControl = function (viewMode) { + return new StackPanelControl(viewMode); +}; +//####app/elements/stackPanel/stackPanelBuilder.js +/** + * @constructor + * @augments ContainerBuilder + */ +function StackPanelBuilder() { + _.superClass(StackPanelBuilder, this); +} + +window.InfinniUI.StackPanelBuilder = StackPanelBuilder; + +_.inherit(StackPanelBuilder, ContainerBuilder); + +_.extend(StackPanelBuilder.prototype, + /** @lends StackPanelBuilder.prototype*/ + { + createElement: function (params) { + return new StackPanel(params.parent, params.metadata['ViewMode']); + }, + + /** + * @param {Object} params + * @param {StackPanel} params.element + * @param {Object} params.metadata + */ + applyMetadata: function (params) { + var + metadata = params.metadata, + element = params.element; + + var result = ContainerBuilder.prototype.applyMetadata.call(this, params); + element.setOrientation(metadata.Orientation); + + return result; + } + + }); - var sourceProperty; - var source = itemsBinding.getSource(); - var binding = new DataBinding(); +//####app/elements/button/button.js +/** + * @param parent + * @augments Element + * @constructor + */ +function Button(parent, viewMode) { + _.superClass(Button, this, parent, viewMode); + this.buttonInit(); +} + +window.InfinniUI.Button = Button; + +_.inherit(Button, Element); + +_.extend(Button.prototype, { + + createControl: function (viewMode) { + return new ButtonControl(viewMode); + }, + + setType: function(type) { + this.control.setType(type); + }, + + getType: function() { + return this.control.getType(); + } + +}, buttonMixin); - sourceProperty = index.toString(); - if (itemsBinding.getSourceProperty() != '') { - sourceProperty = itemsBinding.getSourceProperty() + '.' + sourceProperty; - } +//####app/elements/button/buttonBuilder.js +function ButtonBuilder() { + _.superClass(ButtonBuilder, this); +} + +window.InfinniUI.ButtonBuilder = ButtonBuilder; + +_.inherit(ButtonBuilder, ElementBuilder); + +_.extend(ButtonBuilder.prototype, { + + createElement: function (params) { + var viewMode = this.detectViewMode(params); + return new Button(params.parent, viewMode); + }, + + detectViewMode: function(params){ + var viewMode = params.metadata['ViewMode']; + var el = params.parent; + var exit = false; + + if(!viewMode){ + while(!exit){ + if(el){ + if(el instanceof PopupButton){ + viewMode = 'link'; + exit = true; + + }else if(el instanceof MenuBar){ + viewMode = 'menuItem'; + exit = true; + + }else if(el instanceof View){ + exit = true; + + }else{ + el = el.parent; + + } + }else{ + exit = true; + } + } + + } + + return viewMode + }, + + applyMetadata: function (params) { + ElementBuilder.prototype.applyMetadata.call(this, params); + + this.applyButtonMetadata(params); + + if( params.metadata.Type ) { + params.element.setType(params.metadata.Type); + } + } + +}, buttonBuilderMixin); - if (cellProperty != '') { - sourceProperty = sourceProperty + '.' + cellProperty; - } +//####app/elements/buttonEdit/buttonEdit.js +/** + * + * @param parent + * @constructor + * @augments TextBox + */ +function ButtonEdit(parent) { + _.superClass(ButtonEdit, this, parent); +} + +window.InfinniUI.ButtonEdit = ButtonEdit; + +_.inherit(ButtonEdit, TextBox); + +ButtonEdit.prototype.createControl = function (parent) { + return new ButtonEditControl(parent); +}; + +/** + * @public + * @param {String} icon + */ +ButtonEdit.prototype.setIcon = function (icon) { + if (icon && icon.toLowerCase) { + icon = icon.toLowerCase(); + } + this.control.set('icon', icon); +}; + +/** + * @public + * @returns {String} + */ +ButtonEdit.prototype.getIcon = function () { + return this.control.get('icon'); +}; + +/** + * @public + * @param {boolean} readOnly + */ +ButtonEdit.prototype.setReadOnly = function (readOnly) { + if (typeof readOnly !== 'undefined' && readOnly !== null) { + this.control.set('readOnly', !!readOnly); + } +}; + +/** + * @public + * @returns {boolean} + */ +ButtonEdit.prototype.getReadOnly = function () { + return this.control.get('readOnly'); +}; + +/** + * @public + * @param {boolean} showClear + */ +ButtonEdit.prototype.setShowClear = function (showClear) { + if (typeof showClear !== 'undefined' && showClear !== null) { + this.control.set('showClear', !!showClear); + } +}; + +/** + * @public + * @returns {boolean} + */ +ButtonEdit.prototype.getShowClear = function () { + return this.control.get('showClear'); +}; + + +ButtonEdit.prototype.onButtonClick = function (handler) { + var element = this; + var callback = function (nativeEventData) { + var eventData = element._getHandlingMouseEventData(nativeEventData); + handler(eventData); + }; + return this.control.onButtonClick(callback); +}; - binding.bindSource(source, sourceProperty); - binding.bindElement(label, 'value'); +//####app/elements/buttonEdit/buttonEditBuilder.js +/** + * + * @constructor + * @augments TextBoxBuilder + */ +function ButtonEditBuilder() { + _.superClass(ButtonEditBuilder, this); +} + +window.InfinniUI.ButtonEditBuilder = ButtonEditBuilder; + +_.inherit(ButtonEditBuilder, TextBoxBuilder); + +ButtonEditBuilder.prototype.createElement = function (params) { + return new ButtonEdit(params.parent); +}; + +ButtonEditBuilder.prototype.applyMetadata = function (params) { + TextBoxBuilder.prototype.applyMetadata.call(this, params); + + this.initBindingToProperty(params, 'Icon'); + this.initBindingToProperty(params, 'ReadOnly', true); + this.initBindingToProperty(params, 'ShowClear', true); + + this.buildOnButtonClick(params); + this.buildButtonAction(params); +}; + + +/** + * @protected + * @param params + */ +ButtonEditBuilder.prototype.buildButtonAction = function (params) { + /** @type {ButtonEdit} **/ + var element = params.element; + var metadata = params.metadata; + var builder = params.builder; + + if (!metadata.Action) { + return; + } + + var args = { + parentView: params.parentView, + parent: element, + basePathOfProperty: params.basePathOfProperty + }; + var action = builder.build(metadata.Action, args); + element.onButtonClick(function(){ + action.execute(); + }); +}; + +/** + * @protected + * @param params + */ +ButtonEditBuilder.prototype.buildOnButtonClick = function (params) { + /** @type {ButtonEdit} **/ + var element = params.element; + var metadata = params.metadata; + + var onButtonClick = metadata.OnButtonClick; + if (!onButtonClick) { + return; + } + + element.onButtonClick(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(onButtonClick.Name || onButtonClick, args); + }); + +}; + + - return label; - } - } +//####app/elements/checkBox/checkBox.js +/** + * + * @param parent + * @constructor + * @augment Element + */ +function CheckBox(parent) { + _.superClass(CheckBox, this, parent); + this.initialize_editorBase(); +} + +window.InfinniUI.CheckBox = CheckBox; + +_.inherit(CheckBox, Element); + + +_.extend(CheckBox.prototype, { + + createControl: function (parent) { + return new CheckBoxControl(parent); + } + +}, editorBaseMixin); -}; +//####app/elements/checkBox/checkBoxBuilder.js +/** + * + * @constructor + * @augments ElementBuilder + */ +function CheckBoxBuilder() { + _.superClass(CheckBoxBuilder, this); + this.initialize_editorBaseBuilder(); +} + +window.InfinniUI.CheckBoxBuilder = CheckBoxBuilder; + +_.inherit(CheckBoxBuilder, ElementBuilder); + + +_.extend(CheckBoxBuilder.prototype, { + createElement: function (params) { + return new CheckBox(params.parent); + }, + + applyMetadata: function (params) { + ElementBuilder.prototype.applyMetadata.call(this, params); + this.applyMetadata_editorBaseBuilder(params); + + //var element = params.element; + //var metadata = params.metadata; + } +}, editorBaseBuilderMixin); + +//####app/elements/comboBox/comboBox.js /** - * @protected - * @param {DataGridColumn} column - * @param {Object} metadata - * @param {Object} params - * @returns {DataGridColumnBuilder} + * @augments ListEditorBase + * @param parent + * @constructor + * @mixes labelTextElementMixin */ -DataGridColumnBuilder.prototype.buildCellSelector = function (column, metadata, params) { +function ComboBox(parent) { + _.superClass(ComboBox, this, parent); +} - var cellSelector; +window.InfinniUI.ComboBox = ComboBox; - if (metadata.CellSelector) { - cellSelector = function (context, args) { - var scriptExecutor = new ScriptExecutor(params.parent); - return scriptExecutor.executeScript(metadata.CellSelector.Name || metadata.CellSelector, args) - }; - } else if (metadata.CellProperty) { - var propertyName = metadata.CellProperty; - cellSelector = function (value) { - return InfinniUI.ObjectUtils.getPropertyValue(value, propertyName); - } - } else { - cellSelector = function (value) { - return value; - } - } +_.inherit(ComboBox, ListEditorBase); - column.setCellSelector(cellSelector); - return this; +_.extend(ComboBox.prototype, labelTextElementMixin); + +ComboBox.prototype.createControl = function () { + return new ComboBoxControl(); }; -/** - * @protected - * @param {DataGridColumn} column - * @param {Object} metadata - * @param {Object} params - * @returns {DataGridColumnBuilder} - */ -DataGridColumnBuilder.prototype.buildHeaderTemplate = function (column, metadata, params) { - var - headerTemplate, - headerTemplateMetadata = metadata.HeaderTemplate; +ComboBox.prototype.setValueTemplate = function (value) { + this.control.set('valueTemplate', value); +}; - if (typeof headerTemplateMetadata === 'undefined' || _.isEmpty(headerTemplateMetadata)) { - headerTemplate = this.buildHeaderTemplateByDefault(params); - column.setIsHeaderTemplateEmpty(true); - } else { - headerTemplate = this.buildHeaderTemplateByMetadata(headerTemplateMetadata, params); - column.setIsHeaderTemplateEmpty(false); +ComboBox.prototype.getValueTemplate = function () { + return this.control.get('valueTemplate'); +}; + +ComboBox.prototype.getAutocomplete = function () { + return this.control.get('autocomplete'); +}; + +ComboBox.prototype.setAutocomplete = function (value) { + if (typeof value === 'boolean') { + this.control.set('autocomplete', value); } +}; - column.setHeaderTemplate(headerTemplate); +ComboBox.prototype.setShowClear = function (value) { + if (typeof value === 'boolean') { + this.control.set('showClear', value); + } +}; - return this; +ComboBox.prototype.getShowClear = function () { + return this.control.get('showClear'); }; -/** - * @protected - * @param {Object} headerTemplateMetadata - * @param {Object} params - * @returns {Function} - */ -DataGridColumnBuilder.prototype.buildHeaderTemplateByMetadata = function (headerTemplateMetadata, params) { - var element = params.element; - var builder = params.builder; - - return function(context, args) { - var argumentForBuilder = { - parent: element, - parentView: params.parentView - }; +ComboBox.prototype.getAutocompleteValue = function () { + return this.control.get('autocompleteValue'); +}; - return builder.build(headerTemplateMetadata, argumentForBuilder); - }; +ComboBox.prototype.setAutocompleteValue = function (value) { + this.control.set('autocompleteValue', value); }; + +//####app/elements/comboBox/comboBoxBuilder.js /** - * @protected - * @param {Object} params - * @returns {Function} + * @augments ListEditorBaseBuilder + * @constructor */ -DataGridColumnBuilder.prototype.buildHeaderTemplateByDefault = function (params) { +function ComboBoxBuilder() { + _.superClass(ComboBoxBuilder, this); +} - return function (context, args) { - var label = new Label(this); - label.setText(args.value); - return label; - }; +window.InfinniUI.ComboBoxBuilder = ComboBoxBuilder; -}; +_.inherit(ComboBoxBuilder, ListEditorBaseBuilder); -//####app/elements/dataNavigation/dataNavigation.js -function DataNavigation (parent) { - _.superClass(DataNavigation, this, parent); -} +_.extend(ComboBoxBuilder.prototype, /** @lends ComboBoxBuilder.prototype */{ + + createElement: function (params) { + return new ComboBox(params.parent); + }, + + applyMetadata: function (params) { + var element = params.element; + var that = this; -window.InfinniUI.DataNavigation = DataNavigation; + var data = ListEditorBaseBuilder.prototype.applyMetadata.call(this, params); + this.initValueTemplate(data.valueBinding, params); + this.initBindingToProperty(params, 'LabelText'); + element.setAutocomplete(params.metadata.Autocomplete); + element.setShowClear(params.metadata.ShowClear); -_.inherit(DataNavigation, Element); + if(params.metadata.Autocomplete){ + var name = element.getName(); -_.extend(DataNavigation.prototype, { + if(!name){ + name = that.generateName(); + element.setName(name); + } + } - createControl: function () { - return new DataNavigationControl(); }, - getDataSource: function () { - return this.control.get('dataSource'); - }, + initValueTemplate: function (binding, params) { - setDataSource: function (value) { - this.control.set('dataSource', value); - }, + var metadata = params.metadata; + var element = params.element; + var valueTemplate; + var property; - getAvailablePageSizes: function () { - return this.control.get('availablePageSizes'); - }, - setPageNumber: function (value) { - this.control.set('pageNumber', value) - }, + if ('ValueTemplate' in metadata) { + valueTemplate = this.buildValueTemplate(metadata.ValueTemplate, params); + } else if ('ValueFormat' in metadata) { + valueTemplate = this.buildValueTemplateByFormat(binding, metadata.ValueFormat, params); + } else { + valueTemplate = this.buildValueTemplateByDefault(binding, params); + } - getPageNumber: function () { - return this.control.get('pageNumber'); + element.setValueTemplate(valueTemplate); }, - onPageNumberChanged: function (handler) { - this.control.onPageNumberChanged(this.createControlEventHandler(this, handler)); - }, + buildValueTemplate: function (templateMetadata, params) { + var element = params.element; + var builder = params.builder; + var basePathOfProperty = params.basePathOfProperty || new BasePathOfProperty(''); + var that = this; - setPageSize: function (value) { - this.control.set('pageSize', value) - }, + return function (context, args) { + var index = args.index; + var bindingIndex; + var argumentForBuilder = { + parent: params.element, + parentView: params.parentView + }; - getPageSize: function () { - return this.control.get('pageSize'); - }, + if (index !== undefined && index !== null) { + //bindingIndex = that.bindingIndexByItemsIndex(index, params); + bindingIndex = index; - onPageSizeChanged: function (handler) { - this.control.onPageSizeChanged(this.createControlEventHandler(this, handler)); - }, + if (bindingIndex !== undefined && bindingIndex !== null) { + argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild('', bindingIndex); + } else { + argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild('', index); + } + } - getPageCount: function () { - return this.control.get('pageCount'); + return builder.build(templateMetadata, argumentForBuilder); + }; }, - setPageCount: function (value) { - this.control.set('pageCount', value) + buildValueTemplateByFormat: function (binding, valueFormatMetadata, params) { + var format = this.buildDisplayFormat(valueFormatMetadata, params); + return function (context, args) { + var index = args.index; + var value = args.value; + + var label = new Label(this); + label.setHorizontalAlignment('Left'); + label.setDisplayFormat(format); + label.setValue(value); + return label; + }; }, - getIsDataReady: function () { - return this.control.get('isDataReady'); + buildValueTemplateByDefault: function (binding, params) { + + return function (context, args) { + var index = args.index; + var value = args.value; + + var label = new Label(this); + label.setHorizontalAlignment('Left'); + label.setValue(value); + + return label; + }; }, - setIsDataReady: function (value) { - this.control.set('isDataReady', value) + generateName: function(){ + return 'combobox-' + guid(); } - }); -//####app/elements/dataNavigation/dataNavigationBuilder.js -function DataNavigationBuilder () { - _.superClass(DataNavigationBuilder, this); +//####app/elements/contextMenu/contextMenu.js +/** + * @class + * @constructor + * @arguments Container + */ +function ContextMenu(parent) { + _.superClass(ContextMenu, this, parent); } -window.InfinniUI.DataNavigationBuilder = DataNavigationBuilder; +window.InfinniUI.ContextMenu = ContextMenu; -_.inherit(DataNavigationBuilder, ElementBuilder); +_.inherit(ContextMenu, Container); -_.extend(DataNavigationBuilder.prototype, { +_.extend(ContextMenu.prototype, { - createElement: function (params) { - return new DataNavigation(params.parent); - }, + createControl: function () { + return new ContextMenuControl(); + } - applyMetadata: function (params) { - ElementBuilder.prototype.applyMetadata.call(this, params); +}); - var element = params.element; - var metadata = params.metadata; - var pageSize; - var that = this; +//####app/elements/contextMenu/contextMenuBuilder.js +/** + * @constructor + * @arguments ContainerBuilder + */ +function ContextMenuBuilder() { + _.superClass(ContextMenuBuilder, this); +} - if (Array.isArray(metadata.AvailablePageSizes)) { - element.getAvailablePageSizes().reset(metadata.AvailablePageSizes); - } +window.InfinniUI.ContextMenuBuilder = ContextMenuBuilder; - var ds = this.findDataSource(params); - if (ds) { - pageSize = ds.getProperty('.pageSize'); +_.inherit(ContextMenuBuilder, ContainerBuilder); - element.setDataSource(ds); - element.setPageSize(pageSize); +_.extend(ContextMenuBuilder.prototype, /** @lends ContextMenuBuilder.prototype */{ - ds.onItemsUpdated(function(){ - that.onDataUpdated(element, ds); - }); + createElement: function (params) { + return new ContextMenu(params.parent); + }, - if(ds.isDataReady()){ - this.onDataUpdated(element, ds); - } + applyMetadata: function (params) { + ContainerBuilder.prototype.applyMetadata.call(this, params); + } + +}); + +//####app/elements/dataGrid/dataGrid.js +function DataGrid(parent) { + _.superClass(DataGrid, this, parent); +} + +window.InfinniUI.DataGrid = DataGrid; + +_.inherit(DataGrid, ListEditorBase); + +/** + * Возвращает коллекцию колонок таблицы {@see DataGridColumn} + * @returns {Collection} + */ +DataGrid.prototype.getColumns = function () { + return this.control.get('columns'); +}; + +DataGrid.prototype.setShowSelectors = function (value) { + if (typeof value !== 'undefined' && value !== null) { + this.control.set('showSelectors', !!value); + } +}; + +DataGrid.prototype.getShowSelectors = function () { + return this.control.get('showSelectors'); +}; + +DataGrid.prototype.createRow = function () { + return new DataGridRow(this); +}; + +DataGrid.prototype.setEnabled = function (value) { + if( _.isBoolean(value) ) { + this.control.setEnabled(value); + } +}; + +/** + * @description Устанавливает значение, определяющее виден ли элемент "Выбрать все" в шапке таблицы. + * @param {boolean} value + */ +DataGrid.prototype.setCheckAllVisible = function (value) { + if (_.isBoolean(value)) { + this.control.set('checkAllVisible', value); + } +}; + +/** + * @description Возвращает значение, определяющее виден ли элемент "Выбрать все" в шапке таблицы. + * @returns {boolean} + */ +DataGrid.prototype.getCheckAllVisible = function () { + return this.control.get('checkAllVisible'); +}; + +/** + * @description Возвращает состояние элемента "Выбрать все" из шапки таблицы + * @returns {boolean} + */ +DataGrid.prototype.getCheckAll = function () { + return this.control.get('checkAll'); +}; + +/** + * @description Устанавливает обработчик события о том, что изменилось состояние элемента "Выбрать все" в шапке таблицы + * @param {function} handler + */ +DataGrid.prototype.onCheckAllChanged = function (handler) { + this.control.onCheckAllChanged(this.createControlEventHandler(this, handler)); +}; + +DataGrid.prototype.createControl = function () { + return new DataGridControl(); +}; + + +DataGrid.prototype.onRowClick = function (handler) { + var that = this, + callback = function (nativeEventData) { + var eventData = that._getHandlingMouseEventData(nativeEventData); + handler(eventData); + }; + return this.control.onRowClick(callback); +}; + +DataGrid.prototype.onRowDoubleClick = function (handler) { + var that = this, + callback = function (nativeEventData) { + var eventData = that._getHandlingMouseEventData(nativeEventData); + handler(eventData); + }; + return this.control.onRowDoubleClick(callback); +}; - element.onPageNumberChanged(function (context, message) { - ds.setProperty('.pageNumber', message.value); - }); +//####app/elements/dataGrid/dataGridBuilder.js +function DataGridBuilder() { + _.superClass(DataGridBuilder, this); + this.columnBuilder = new DataGridColumnBuilder(); +} + +window.InfinniUI.DataGridBuilder = DataGridBuilder; + +_.inherit(DataGridBuilder, ListEditorBaseBuilder); + +_.extend(DataGridBuilder.prototype, /** @lends DataGridBuilder.prototype */{ + + createElement: function (params) { + return new DataGrid(params.parent); + }, + + applyMetadata: function (params) { + ListEditorBaseBuilder.prototype.applyMetadata.call(this, params); + + var metadata = params.metadata; + /** @type DataGrid **/ + var element = params.element; + element.setShowSelectors(metadata.ShowSelectors); + element.setCheckAllVisible(metadata.CheckAllVisible); + + if(metadata.OnCheckAllChanged){ + element.onCheckAllChanged(function(context, args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnCheckAllChanged.Name || metadata.OnCheckAllChanged, args); + }); + } + + if( metadata.OnRowClick ) { + element.onRowClick(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnRowClick.Name || metadata.OnRowClick, args); + }); + } + + if( metadata.OnRowDoubleClick ) { + element.onRowDoubleClick(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.OnRowDoubleClick.Name || metadata.OnRowDoubleClick, args); + }); + } + + this.applyColumnsMetadata(params); + }, + + applyColumnsMetadata: function (params) { + var metadata = params.metadata, + element = params.element, + collection = element.getColumns(); + + if (Array.isArray(metadata.Columns)) { + var columns = metadata.Columns.map(function (columnMetaData) { + return this.buildColumn(columnMetaData, params); + }, this); + + collection.reset(columns); + } + + }, + + buildColumn: function (metadata, params) { + return this.columnBuilder.build(params.element, metadata, params); + }, + + buildItemProperty: function (itemsBinding, itemPropertyMetadata, params) { + var dataGrid = params.element; + var builder = this; + + return function (context, args) { + + var row = params.builder.buildType('DataGridRow', {}, { + parent: dataGrid, + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }); + + row.setGrid(dataGrid); + + ['RowStyle', 'RowBackground', 'RowForeground', 'RowTextStyle'] + .forEach(initBindingToRowProperty.bind(null, row, args.index)); + + var columns = dataGrid.getColumns(); + + var cellElements = columns.toArray().map(function (column, index) { + var cellTemplate = column.getCellTemplate(); + var template = cellTemplate(itemsBinding, row); + var cellEl = template(context, args); + + return cellEl; + }); + row.setCellElements(cellElements); + row.setMultiSelect(dataGrid.getMultiSelect()); + row.setShowSelectors(dataGrid.getShowSelectors()); + return row; + }; + + function initBindingToRowProperty(row, index, propertyName) { + var basePathOfProperty = params.basePathOfProperty || new BasePathOfProperty(''); + var argumentForBuilder = { + element: row, + parent: dataGrid, + builder: params.builder, + metadata: params.metadata, + parentView: params.parentView + }; + argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild('', index); + + builder.initBindingToProperty(argumentForBuilder, propertyName); + } + } + +}); - element.onPageSizeChanged(function (context, message) { - ds.setProperty('.pageSize', message.value); - }); - } else { - console.error('DataSource not found'); - } +//####app/elements/dataGrid/dataGridColumn.js +function DataGridColumn() { + this._values = Object.create(null); +} + +DataGridColumn.prototype.setHeader = function (value) { + this.setProperty('header', value); +}; + +DataGridColumn.prototype.getHeader = function () { + return this.getProperty('header'); +}; + +DataGridColumn.prototype.setCellTemplate = function (value) { + this.setProperty('cellTemplate', value); +}; + +DataGridColumn.prototype.getCellTemplate = function () { + return this.getProperty('cellTemplate'); +}; + +DataGridColumn.prototype.setCellSelector = function (value) { + this.setProperty('cellSelector', value); +}; + +DataGridColumn.prototype.getCellSelector = function () { + return this.getProperty('cellSelector'); +}; + +DataGridColumn.prototype.setHeaderTemplate = function (value) { + this.setProperty('cellHeaderTemplate', value); +}; + +DataGridColumn.prototype.getHeaderTemplate = function () { + return this.getProperty('cellHeaderTemplate'); +}; + +DataGridColumn.prototype.setWidth = function (value) { + this.setProperty('width', value); +}; + +DataGridColumn.prototype.getWidth = function (value) { + return this.getProperty('width'); +}; + +DataGridColumn.prototype.setSortable = function (value) { + this.setProperty('sortable', value); +}; + +DataGridColumn.prototype.getSortable = function () { + return this.getProperty('sortable'); +}; + +DataGridColumn.prototype.isSortable = function () { + return this.getSortable(); +}; + +DataGridColumn.prototype.setSortDirection = function (value) { + this.setProperty('sortDirection', value); +}; + +DataGridColumn.prototype.getSortDirection = function () { + return this.getProperty('sortDirection'); +}; + +DataGridColumn.prototype.setSortFunction = function (handler) { + this.setProperty('sortFunction', handler); +}; + +DataGridColumn.prototype.getSortFunction = function () { + return this.getProperty('sortFunction'); +}; + +DataGridColumn.prototype.setIsHeaderTemplateEmpty = function (value) { + this.setProperty('isHeaderTemplateEmpty', value); +}; + +DataGridColumn.prototype.getIsHeaderTemplateEmpty = function () { + return this.getProperty('isHeaderTemplateEmpty'); +}; + +DataGridColumn.prototype.onSort = function (handler) { + var that = this, + callback = function (nativeEventData) { + handler(nativeEventData); + }; + this.on('onSort', callback); +}; + +/** + * @description Для взаимодействие с DataBinding + * @param propertyName + * @param callback + */ +DataGridColumn.prototype.onPropertyChanged = function (propertyName, callback) { + this.on('change:' + propertyName, callback); +}; + +/** + * @description Для взаимодействие с DataBinding + * @param propertyName + * @param propertyValue + */ +DataGridColumn.prototype.setProperty = function (propertyName, propertyValue) { + var oldValue = this._values[propertyName]; + + this._values[propertyName] = propertyValue; + if (oldValue !== propertyValue) { + this.trigger('change:' + propertyName, null, { + property: propertyName, + oldValue: oldValue, + newValue: propertyValue + }); + } +}; + +DataGridColumn.prototype.getProperty = function (propertyName) { + return this._values[propertyName]; +}; + +_.extend(DataGridColumn.prototype, Backbone.Events); - }, +//####app/elements/dataGrid/dataGridColumnBuilder.js +/** + * + * @constructor + */ +function DataGridColumnBuilder () { + + +} + +_.extend(DataGridColumnBuilder.prototype, displayFormatBuilderMixin); + +/** + * + * @param {DataGrid} element + * @param {Object} metadata метаданные колонки грида + * @param {Object} params + * @returns {DataGridColumn} + */ +DataGridColumnBuilder.prototype.build = function (element, metadata, params) { + var column = new DataGridColumn(); + + + this + .buildHeader(column, metadata, params) + .buildHeaderTemplate(column, metadata, params) + .buildCellTemplate(column, metadata, params) + .buildWidth(column, metadata); + + if( metadata.Sortable ) { + column.setSortable(true); + column.setSortDirection( null ); + if( metadata.SortedDefault && ( metadata.SortedDefault === 'asc' || metadata.SortedDefault === 'desc' ) ) { + column.setSortDirection( metadata.SortedDefault ); + } + + if (metadata.SortFunction) { + column.onSort(function (args) { + new ScriptExecutor(element.getScriptsStorage()).executeScript(metadata.SortFunction.Name || metadata.SortFunction, args); + }); + } + } + + return column; +}; + +DataGridColumnBuilder.prototype.buildWidth = function (column, metadata) { + var width = metadata.Width; + + if (width !== null && typeof width !== 'undefined') { + column.setWidth(width); + } + + return this; +}; + +/** + * @protected + * @param {DataGridColumn} column + * @param {Object} metadata + * @param {Object} params + * @returns {DataGridColumnBuilder} + */ +DataGridColumnBuilder.prototype.buildHeader = function (column, metadata, params) { + + if (metadata.Header && typeof metadata.Header === 'object') { + //Header указывает на DataBinding + var + builder = params.builder, + binding = builder.buildType('PropertyBinding', metadata.Header, { + parent: params.element, + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }); + + binding.bindElement(column, 'header'); + } else { + //Header содержит значение для шаблона + column.setHeader(metadata.Header); + } + return this; +}; + +/** + * @protected + * @param {DataGridColumn} column + * @param {Object} metadata + * @param {Object} params + * @returns {DataGridColumnBuilder} + */ +DataGridColumnBuilder.prototype.buildCellTemplate = function (column, metadata, params) { + var cellTemplate; + + if ('CellTemplate' in metadata) { + cellTemplate = this.buildCellTemplateByTemplate(params, metadata.CellTemplate); + } else if ('CellFormat' in metadata) { + cellTemplate = this.buildCellTemplateByFormat(params, metadata.CellFormat); + } else if ('CellSelector' in metadata) { + cellTemplate = this.buildCellTemplateBySelector(params, metadata.CellSelector); + } else { + var cellProperty = 'CellProperty' in metadata ? metadata.CellProperty : ''; + cellTemplate = this.buildCellTemplateByDefault(params, cellProperty); + } + column.setCellTemplate(cellTemplate); + return this; +}; + +DataGridColumnBuilder.prototype.buildCellTemplateByTemplate = function (params, cellTemplateMetadata) { + var dataGrid = params.element; + var builder = params.builder; + var basePathOfProperty = params.basePathOfProperty || new BasePathOfProperty(''); + + return function (itemsBinding, row) { + return function (context, args) { + var index = args.index; + var argumentForBuilder = { + parent: row, + parentView: params.parentView + }; + argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild('', index); + + return builder.build(cellTemplateMetadata, argumentForBuilder); + } + + }; +}; + +DataGridColumnBuilder.prototype.buildCellTemplateByFormat = function (params, cellFormatMetadata) { + var column = params.element, + grid = column.parent, + format = this.buildDisplayFormat(cellFormatMetadata, params); + + return function (itemsBinding, row) { + return function (context, args) { + var index = args.index; + var builder = params.builder; + + var sourceProperty = itemsBinding.getSourceProperty(); + var source = itemsBinding.getSource(); + var binding = new DataBinding(); + + sourceProperty = index.toString(); + if (itemsBinding.getSourceProperty() != '') { + sourceProperty = itemsBinding.getSourceProperty() + '.' + sourceProperty; + } + + var label = builder.buildType('Label', {}, { + parent: row, + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }); + + label.setDisplayFormat(format); + + binding.bindSource(source, sourceProperty); + binding.bindElement(label, 'value'); + + return label; + }; + }; + +}; + +DataGridColumnBuilder.prototype.buildCellTemplateBySelector = function (params, cellSelectorMetadata) { + var column = params.element, + grid = column.parent; + + return function (itemsBinding, row) { + return function (context, args) { + + var label = params.builder.buildType('Label', {}, { + parent: row, + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }); + + var scriptExecutor = new ScriptExecutor(grid.getScriptsStorage()); + var value = scriptExecutor.executeScript(cellSelectorMetadata.Name || cellSelectorMetadata, { + value: args.item + }); + + label.setText(value); + return label; + }; + }; +}; + +DataGridColumnBuilder.prototype.buildCellTemplateByDefault = function (params, cellProperty) { + var grid = params.element; + + return function (itemsBinding, row) { + + return function (context, args) { + var index = args.index; + var builder = params.builder; + + var sourceProperty; + var source = itemsBinding.getSource(); + var binding = new DataBinding(); + + sourceProperty = index.toString(); + if (itemsBinding.getSourceProperty() != '') { + sourceProperty = itemsBinding.getSourceProperty() + '.' + sourceProperty; + } + + if (cellProperty != '') { + sourceProperty = sourceProperty + '.' + cellProperty; + } + + + var label = builder.buildType('Label', {}, { + parent: row, + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }); + + binding.bindSource(source, sourceProperty); + binding.bindElement(label, 'value'); + + return label; + } + } + +}; + +/** + * @protected + * @param {DataGridColumn} column + * @param {Object} metadata + * @param {Object} params + * @returns {DataGridColumnBuilder} + */ +DataGridColumnBuilder.prototype.buildCellSelector = function (column, metadata, params) { + + var cellSelector; + + if (metadata.CellSelector) { + cellSelector = function (context, args) { + var scriptExecutor = new ScriptExecutor(params.parent); + return scriptExecutor.executeScript(metadata.CellSelector.Name || metadata.CellSelector, args) + }; + } else if (metadata.CellProperty) { + var propertyName = metadata.CellProperty; + cellSelector = function (value) { + return InfinniUI.ObjectUtils.getPropertyValue(value, propertyName); + } + } else { + cellSelector = function (value) { + return value; + } + } + + column.setCellSelector(cellSelector); + return this; +}; + +/** + * @protected + * @param {DataGridColumn} column + * @param {Object} metadata + * @param {Object} params + * @returns {DataGridColumnBuilder} + */ +DataGridColumnBuilder.prototype.buildHeaderTemplate = function (column, metadata, params) { + var + headerTemplate, + headerTemplateMetadata = metadata.HeaderTemplate; + + if (typeof headerTemplateMetadata === 'undefined' || _.isEmpty(headerTemplateMetadata)) { + headerTemplate = this.buildHeaderTemplateByDefault(params); + column.setIsHeaderTemplateEmpty(true); + } else { + headerTemplate = this.buildHeaderTemplateByMetadata(headerTemplateMetadata, params); + column.setIsHeaderTemplateEmpty(false); + } + + column.setHeaderTemplate(headerTemplate); + + return this; +}; + +/** + * @protected + * @param {Object} headerTemplateMetadata + * @param {Object} params + * @returns {Function} + */ +DataGridColumnBuilder.prototype.buildHeaderTemplateByMetadata = function (headerTemplateMetadata, params) { + var element = params.element; + var builder = params.builder; + + return function(context, args) { + var argumentForBuilder = { + parent: element, + parentView: params.parentView + }; + + return builder.build(headerTemplateMetadata, argumentForBuilder); + }; +}; + +/** + * @protected + * @param {Object} params + * @param {DataGrid} params.element + * @returns {Function} + */ +DataGridColumnBuilder.prototype.buildHeaderTemplateByDefault = function (params) { + + var builder = params.builder; + + + return function (context, args) { + + var label = builder.buildType('Label', {}, { + parent: params.element, + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }); + + label.setText(args.value); + return label; + }; + +}; + +//####app/elements/dataGrid/dataGridRowBuilder.js +function DataGridRowBuilder() { + _.superClass(DataGridRowBuilder, this); +} - onDataUpdated: function(element, dataSource){ - var dsTotalCount = dataSource.getProperty('.totalCount'), - pageSize = dataSource.getProperty('.pageSize'), - pageNumber = dataSource.getProperty('.pageNumber'), - pageCount; +window.InfinniUI.DataGridRowBuilder = DataGridRowBuilder; - if(typeof dsTotalCount == 'number'){ - pageCount = Math.ceil(dsTotalCount/pageSize); - element.setPageCount(pageCount); - } +_.inherit(DataGridRowBuilder, ElementBuilder); - element.setPageNumber(pageNumber); - element.setIsDataReady(true); +_.extend(DataGridRowBuilder.prototype, /** @lends DataGridBuilder.prototype */{ + + createElement: function( params ) { + return new DataGridRow(params.parent); }, - - findDataSource: function (params) { - var - name = params.metadata.DataSource, - view = params.parentView, - context, - dataSource; + + applyMetadata: function( params ) { + ElementBuilder.prototype.applyMetadata.call(this, params); - if (name && view) { - context = view.getContext(); - dataSource = context.dataSources[name]; - } - - return dataSource; } - }); +//####app/elements/dataNavigation/dataNavigation.js +function DataNavigation (parent) { + _.superClass(DataNavigation, this, parent); +} + +window.InfinniUI.DataNavigation = DataNavigation; + +_.inherit(DataNavigation, Element); + +_.extend(DataNavigation.prototype, { + + createControl: function () { + return new DataNavigationControl(); + }, + + getDataSource: function () { + return this.control.get('dataSource'); + }, + + setDataSource: function (value) { + this.control.set('dataSource', value); + }, + + getAvailablePageSizes: function () { + return this.control.get('availablePageSizes'); + }, + + setPageNumber: function (value) { + this.control.set('pageNumber', value) + }, + + getPageNumber: function () { + return this.control.get('pageNumber'); + }, + + onPageNumberChanged: function (handler) { + this.control.onPageNumberChanged(this.createControlEventHandler(this, handler)); + }, + + setPageSize: function (value) { + this.control.set('pageSize', value) + }, + + getPageSize: function () { + return this.control.get('pageSize'); + }, + + onPageSizeChanged: function (handler) { + this.control.onPageSizeChanged(this.createControlEventHandler(this, handler)); + }, + + getPageCount: function () { + return this.control.get('pageCount'); + }, + + setPageCount: function (value) { + this.control.set('pageCount', value) + }, + + getIsDataReady: function () { + return this.control.get('isDataReady'); + }, + + setIsDataReady: function (value) { + this.control.set('isDataReady', value) + } + +}); + +//####app/elements/dataNavigation/dataNavigationBuilder.js +function DataNavigationBuilder () { + _.superClass(DataNavigationBuilder, this); +} + +window.InfinniUI.DataNavigationBuilder = DataNavigationBuilder; + +_.inherit(DataNavigationBuilder, ElementBuilder); + +_.extend(DataNavigationBuilder.prototype, { + + createElement: function (params) { + return new DataNavigation(params.parent); + }, + + applyMetadata: function (params) { + ElementBuilder.prototype.applyMetadata.call(this, params); + + var element = params.element; + var metadata = params.metadata; + var pageSize; + var that = this; + + if (Array.isArray(metadata.AvailablePageSizes)) { + element.getAvailablePageSizes().reset(metadata.AvailablePageSizes); + } + + var ds = this.findDataSource(params); + if (ds) { + pageSize = ds.getProperty('.pageSize'); + + element.setDataSource(ds); + element.setPageSize(pageSize); + + ds.onItemsUpdated(function(){ + that.onDataUpdated(element, ds); + }); + + if(ds.isDataReady()){ + this.onDataUpdated(element, ds); + } + + element.onPageNumberChanged(function (context, message) { + ds.setProperty('.pageNumber', message.value); + }); + + element.onPageSizeChanged(function (context, message) { + ds.setProperty('.pageSize', message.value); + }); + } else { + console.error('DataSource not found'); + } + + }, + + onDataUpdated: function(element, dataSource){ + var dsTotalCount = dataSource.getProperty('.totalCount'), + pageSize = dataSource.getProperty('.pageSize'), + pageNumber = dataSource.getProperty('.pageNumber'), + pageCount; + + if(typeof dsTotalCount == 'number'){ + pageCount = Math.ceil(dsTotalCount/pageSize); + element.setPageCount(pageCount); + } + + element.setPageNumber(pageNumber); + element.setIsDataReady(true); + }, + + findDataSource: function (params) { + var + name = params.metadata.DataSource, + view = params.parentView, + context, + dataSource; + + if (name && view) { + context = view.getContext(); + dataSource = context.dataSources[name]; + } + + return dataSource; + } + +}); + //####app/elements/divider/divider.js /** * @@ -23728,7 +24027,7 @@ _.extend(ExtensionPanelBuilder.prototype, { var parameters = {}; _.each(metadata.Parameters, function (parameterMetadata) { - var param = builder.buildType('Parameter', parameterMetadata, {parentView: parentView}); + var param = builder.buildType('Parameter', parameterMetadata, {parentView: parentView, basePathOfProperty: params.basePathOfProperty}); parameters[param.getName()] = param; }); @@ -23745,216 +24044,219 @@ _.extend(ExtensionPanelBuilder.prototype, { }); //####app/elements/fileBox/fileBox.js -/** - * - * @param parent - * @augments Element - * @mixes editorBaseMixin - * @mixes labelTextElementMixin - * @constructor - */ -function FileBox(parent) { - _.superClass(FileBox, this, parent); - - this.initialize_editorBase(); -} - -window.InfinniUI.FileBox = FileBox; - -_.inherit(FileBox, Element); - -_.extend(FileBox.prototype, { - getFile: function () { - return this.control.get('file'); - }, - - createControl: function () { - return new FileBoxControl(); - }, - - /** - * @description Возвращает максимальный размер данных в байтах - * @returns {number} - */ - getMaxSize: function () { - return this.control.get('maxSize'); - }, - - /** - * @description Устанавливает максимальный размер данных в байтах - * @param {number} value - */ - setMaxSize: function (value) { - this.control.set('maxSize', value); - }, - - /** - * @description Возвращает коллекцию допустимых форматов данных - * @returns {Collection} - */ - getAcceptTypes: function () { - return this.control.get('acceptTypes'); - }, - - - /** - * Методы, не описанные в документации - */ - - - /** - * @description Недокументированный! - * @param {Array} types - */ - setAcceptTypes: function (types) { - var collection = this.getAcceptTypes(); - if (Array.isArray(types)) { - collection.set(types) - } - }, - - // НЕдокументированные методы - setFile: function (value) { - this.control.set('file', value); - }, - - setFileName: function (value) { - this.control.set('fileName', value); - return this; - }, - - setFileSize: function (value) { - this.control.set('fileSize', value); - return this; - }, - - setFileTime: function (value) { - this.control.set('fileTime', value); - return this; - }, - - setFileType: function (value) { - this.control.set('fileType', value); - return this; - } - - // - //setUrl: function (value) { - // this.control.set('url', value); - //}, - // - //getUrl: function () { - // return this.control.get('url'); - //} - -}, - editorBaseMixin, - labelTextElementMixin -); +/** + * + * @param parent + * @augments Element + * @mixes editorBaseMixin + * @mixes labelTextElementMixin + * @constructor + */ +function FileBox(parent) { + _.superClass(FileBox, this, parent); + + this.initialize_editorBase(); +} + +window.InfinniUI.FileBox = FileBox; + +_.inherit(FileBox, Element); + +_.extend(FileBox.prototype, { + getFile: function () { + return this.control.get('file'); + }, + + createControl: function () { + return new FileBoxControl(); + }, + + /** + * @description Возвращает максимальный размер данных в байтах + * @returns {number} + */ + getMaxSize: function () { + return this.control.get('maxSize'); + }, + + /** + * @description Устанавливает максимальный размер данных в байтах + * @param {number} value + */ + setMaxSize: function (value) { + this.control.set('maxSize', value); + }, + + /** + * @description Возвращает коллекцию допустимых форматов данных + * @returns {Collection} + */ + getAcceptTypes: function () { + return this.control.get('acceptTypes'); + }, + + + /** + * Методы, не описанные в документации + */ + + + /** + * @description Недокументированный! + * @param {Array} types + */ + setAcceptTypes: function (types) { + var collection = this.getAcceptTypes(); + if (Array.isArray(types)) { + collection.set(types) + } + }, + + // НЕдокументированные методы + setFile: function (value) { + this.control.set('file', value); + }, + + setFileName: function (value) { + this.control.set('fileName', value); + return this; + }, + + setFileSize: function (value) { + this.control.set('fileSize', value); + return this; + }, + + setFileTime: function (value) { + this.control.set('fileTime', value); + return this; + }, + + setFileType: function (value) { + this.control.set('fileType', value); + return this; + } + + // + //setUrl: function (value) { + // this.control.set('url', value); + //}, + // + //getUrl: function () { + // return this.control.get('url'); + //} + +}, + editorBaseMixin, + labelTextElementMixin +); //####app/elements/fileBox/fileBoxBuilder.js -/** - * - * @constructor - * @augments ElementBuilder - * @mixes editorBaseBuilderMixin - */ -function FileBoxBuilder() { - _.superClass(FileBoxBuilder, this); - this.initialize_editorBaseBuilder(); -} - -window.InfinniUI.FileBoxBuilder = FileBoxBuilder; - -_.inherit(FileBoxBuilder, ElementBuilder); - -_.extend(FileBoxBuilder.prototype, { - - createElement: function (params) { - return new FileBox(params.parent); - }, - - applyMetadata: function (params) { - ElementBuilder.prototype.applyMetadata.call(this, params); - - var element = params.element; - var metadata = params.metadata; - - if (Array.isArray(metadata.AcceptTypes)) { - element.setAcceptTypes(metadata.AcceptTypes); - } - - if (metadata.MaxSize !== null && typeof metadata.MaxSize !== 'undefined') { - element.setMaxSize(metadata.MaxSize); - } - - this.initBindingToProperty(params, 'LabelText'); - - // Привязка данных односторонняя т.к.: - // 1. по значению из источника данных - сформировать URL изображения. - // 2. при выборе в элементе файла на загрузку - добавить выбранный файл в очередь на загрузку - - var converter = new FileBoxValueConverter(element); - - var data = this.applyMetadata_editorBaseBuilder(params, { - mode: InfinniUI.BindingModes.toElement, - converter: converter - }); - - var binding = data.valueBinding; - - if (binding) { - var ds = binding.getSource(); - - params.element.onPropertyChanged('file', function (context, args) { - var file = args.newValue; - - if (file === null) { - ds.setProperty(binding.getSourceProperty(), null) - } else if (file instanceof File) { - ds.setProperty(binding.getSourceProperty(), args.newValue) - } - }) - } - - } - - }, editorBaseBuilderMixin); +/** + * + * @constructor + * @augments ElementBuilder + * @mixes editorBaseBuilderMixin + */ +function FileBoxBuilder() { + _.superClass(FileBoxBuilder, this); + this.initialize_editorBaseBuilder(); +} + +window.InfinniUI.FileBoxBuilder = FileBoxBuilder; + +_.inherit(FileBoxBuilder, ElementBuilder); + +_.extend(FileBoxBuilder.prototype, { + + createElement: function (params) { + return new FileBox(params.parent); + }, + + applyMetadata: function (params) { + ElementBuilder.prototype.applyMetadata.call(this, params); + + var element = params.element; + var metadata = params.metadata; + + if (Array.isArray(metadata.AcceptTypes)) { + element.setAcceptTypes(metadata.AcceptTypes); + } + + if (metadata.MaxSize !== null && typeof metadata.MaxSize !== 'undefined') { + element.setMaxSize(metadata.MaxSize); + } + + this.initBindingToProperty(params, 'LabelText'); + + // Привязка данных односторонняя т.к.: + // 1. по значению из источника данных - сформировать URL изображения. + // 2. при выборе в элементе файла на загрузку - добавить выбранный файл в очередь на загрузку + + var converter = new FileBoxValueConverter(element); + + var data = this.applyMetadata_editorBaseBuilder(params, { + mode: InfinniUI.BindingModes.toElement, + converter: converter + }); + + var binding = data.valueBinding; + + if (binding) { + var ds = binding.getSource(); + + params.element.onPropertyChanged('file', function (context, args) { + var file = args.newValue; + + if (file === null) { + ds.setProperty(binding.getSourceProperty(), null) + } else if (file instanceof File) { + ds.setProperty(binding.getSourceProperty(), args.newValue) + } + }) + } + + } + + }, editorBaseBuilderMixin); //####app/elements/fileBox/fileBoxValueConverter.js -function FileBoxValueConverter (element) { - this._element = element; -} +function FileBoxValueConverter (element) { + this._element = element; +} + +window.InfinniUI.FileBoxValueConverter = FileBoxValueConverter; + +FileBoxValueConverter.prototype.toElement = function (context, args) { + var value = args.value; + var binding = args.binding; + var ds = binding.getSource(); + var fileProvider = ds.getFileProvider(); + var url = null; + //Формируем ссылку для получения файла + + if (value) { + if (fileProvider && InfinniUI.BlobUtils.isFileInfo(value)) { + url = fileProvider.getFileUrl(null, null, InfinniUI.BlobUtils.getContentId(value)); + this._element + .setFileName(InfinniUI.BlobUtils.getName(value)) + .setFileSize(InfinniUI.BlobUtils.getSize(value)) + .setFileTime(InfinniUI.BlobUtils.getTime(value)) + .setFileType(InfinniUI.BlobUtils.getType(value)); + + } else if (typeof value === 'string') { + //@TODO Добавить проверку на валидность URI + url = value; + } else { + //Native File instance from FileAPI + url = value; + } + + } + + return url; +}; -FileBoxValueConverter.prototype.toElement = function (context, args) { - var value = args.value; - var binding = args.binding; - var ds = binding.getSource(); - var fileProvider = ds.getFileProvider(); - var url = null; - //Формируем ссылку для получения файла - - if (value) { - if (fileProvider && InfinniUI.BlobUtils.isFileInfo(value)) { - url = fileProvider.getFileUrl(null, null, InfinniUI.BlobUtils.getContentId(value)); - this._element - .setFileName(InfinniUI.BlobUtils.getName(value)) - .setFileSize(InfinniUI.BlobUtils.getSize(value)) - .setFileTime(InfinniUI.BlobUtils.getTime(value)) - .setFileType(InfinniUI.BlobUtils.getType(value)); - - } else if (typeof value === 'string') { - //@TODO Добавить проверку на валидность URI - url = value; - } else { - //Native File instance from FileAPI - url = value; - } - - } - - return url; -}; //####app/elements/form/form.js /** * @@ -24048,63 +24350,63 @@ _.extend(FormBuilder.prototype, { }); //####app/elements/frame/frame.js -/** - * - * @constructor - * @augments Element - * @mixes editorBaseMixin - */ -function Frame() { - _.superClass(Frame, this); - this.initialize_editorBase(); -} - -window.InfinniUI.Frame = Frame; - -_.inherit(Frame, Element); - -_.extend(Frame.prototype, { - - createControl: function () { - return new FrameControl(); - } - - }, - editorBaseMixin -); +/** + * + * @constructor + * @augments Element + * @mixes editorBaseMixin + */ +function Frame() { + _.superClass(Frame, this); + this.initialize_editorBase(); +} + +window.InfinniUI.Frame = Frame; + +_.inherit(Frame, Element); + +_.extend(Frame.prototype, { + + createControl: function () { + return new FrameControl(); + } + + }, + editorBaseMixin +); //####app/elements/frame/frameBuilder.js -/** - * - * @constructor - * @augments TextEditorBaseBuilder - * @mixes displayFormatBuilderMixin - * @mixes editorBaseBuilderMixin - */ -function FrameBuilder() { - _.superClass(TextEditorBaseBuilder, this); - this.initialize_editorBaseBuilder(); -} - -window.InfinniUI.FrameBuilder = FrameBuilder; - -_.inherit(FrameBuilder, TextEditorBaseBuilder); - -_.extend(FrameBuilder.prototype, { - applyMetadata: function(params){ - var element = params.element; - ElementBuilder.prototype.applyMetadata.call(this, params); - this.applyMetadata_editorBaseBuilder(params); - }, - - createElement: function(params){ - var element = new Frame(params.parent); - return element; - } - - }, - editorBaseBuilderMixin -); +/** + * + * @constructor + * @augments TextEditorBaseBuilder + * @mixes displayFormatBuilderMixin + * @mixes editorBaseBuilderMixin + */ +function FrameBuilder() { + _.superClass(TextEditorBaseBuilder, this); + this.initialize_editorBaseBuilder(); +} + +window.InfinniUI.FrameBuilder = FrameBuilder; + +_.inherit(FrameBuilder, TextEditorBaseBuilder); + +_.extend(FrameBuilder.prototype, { + applyMetadata: function(params){ + var element = params.element; + ElementBuilder.prototype.applyMetadata.call(this, params); + this.applyMetadata_editorBaseBuilder(params); + }, + + createElement: function(params){ + var element = new Frame(params.parent); + return element; + } + + }, + editorBaseBuilderMixin +); //####app/elements/gridPanel/gridPanel.js /** @@ -24214,166 +24516,166 @@ _.extend(IconBuilder.prototype, { }); //####app/elements/imageBox/imageBox.js -/** - * - * @param parent - * @augments Element - * @mixes editorBaseMixin - * @constructor - */ -function ImageBox(parent) { - _.superClass(ImageBox, this, parent); - - this.initialize_editorBase(); -} - -window.InfinniUI.ImageBox = ImageBox; - -_.inherit(ImageBox, Element); - -_.extend(ImageBox.prototype, { - getFile: function () { - return this.control.get('file'); - }, - - createControl: function () { - return new ImageBoxControl(); - }, - - /** - * @description Возвращает максимальный размер данных в байтах - * @returns {number} - */ - getMaxSize: function () { - return this.control.get('maxSize'); - }, - - /** - * @description Устанавливает максимальный размер данных в байтах - * @param {number} value - */ - setMaxSize: function (value) { - this.control.set('maxSize', value); - }, - - /** - * @description Возвращает коллекцию допустимых форматов данных - * @returns {Collection} - */ - getAcceptTypes: function () { - return this.control.get('acceptTypes'); - }, - - /** - * @description Недокументированный! - * @param {Array} types - */ - setAcceptTypes: function (types) { - var collection = this.getAcceptTypes(); - if (Array.isArray(types)) { - collection.set(types) - } - } - - //setUrl: function (value) { - // this.control.set('url', value); - //}, - // - //getUrl: function () { - // return this.control.get('url'); - //} - -}, editorBaseMixin); +/** + * + * @param parent + * @augments Element + * @mixes editorBaseMixin + * @constructor + */ +function ImageBox(parent) { + _.superClass(ImageBox, this, parent); + + this.initialize_editorBase(); +} + +window.InfinniUI.ImageBox = ImageBox; + +_.inherit(ImageBox, Element); + +_.extend(ImageBox.prototype, { + getFile: function () { + return this.control.get('file'); + }, + + createControl: function () { + return new ImageBoxControl(); + }, + + /** + * @description Возвращает максимальный размер данных в байтах + * @returns {number} + */ + getMaxSize: function () { + return this.control.get('maxSize'); + }, + + /** + * @description Устанавливает максимальный размер данных в байтах + * @param {number} value + */ + setMaxSize: function (value) { + this.control.set('maxSize', value); + }, + + /** + * @description Возвращает коллекцию допустимых форматов данных + * @returns {Collection} + */ + getAcceptTypes: function () { + return this.control.get('acceptTypes'); + }, + + /** + * @description Недокументированный! + * @param {Array} types + */ + setAcceptTypes: function (types) { + var collection = this.getAcceptTypes(); + if (Array.isArray(types)) { + collection.set(types) + } + } + + //setUrl: function (value) { + // this.control.set('url', value); + //}, + // + //getUrl: function () { + // return this.control.get('url'); + //} + +}, editorBaseMixin); //####app/elements/imageBox/imageBoxBuilder.js -/** - * - * @constructor - * @augments ElementBuilder - * @mixes editorBaseBuilderMixin - */ -function ImageBoxBuilder() { - _.superClass(ImageBoxBuilder, this); - this.initialize_editorBaseBuilder(); -} - -window.InfinniUI.ImageBoxBuilder = ImageBoxBuilder; - -_.inherit(ImageBoxBuilder, ElementBuilder); - -_.extend(ImageBoxBuilder.prototype, { - - createElement: function (params) { - return new ImageBox(params.parent); - }, - - applyMetadata: function (params) { - ElementBuilder.prototype.applyMetadata.call(this, params); - - var element = params.element; - var metadata = params.metadata; - - if (Array.isArray(metadata.AcceptTypes)) { - element.setAcceptTypes(metadata.AcceptTypes); - } - - if (metadata.MaxSize !== null && typeof metadata.MaxSize !== 'undefined') { - element.setMaxSize(metadata.MaxSize); - } - - // Привязка данных односторонняя т.к.: - // 1. по значению из источника данных - сформировать URL изображения. - // 2. при выборе в элементе файла на загрузку - добавить выбранный файл в очередь на загрузку - - var converter = new ImageBoxValueConverter(element); - - var data = this.applyMetadata_editorBaseBuilder(params, { - mode: InfinniUI.BindingModes.toElement, - converter: converter - }); - - var binding = data.valueBinding; - if (binding) { - var ds = binding.getSource(); - - params.element.onPropertyChanged('file', function (context, args) { - var file = args.newValue; - - if (file instanceof File || file === null) { - ds.setProperty(binding.getSourceProperty(), args.newValue) - } - }); - } - - } - -}, editorBaseBuilderMixin); - -//####app/elements/imageBox/imageBoxValueConverter.js -function ImageBoxValueConverter (element) { - this._element = element; -} - -ImageBoxValueConverter.prototype.toElement = function (context, args) { - var value = args.value; - var binding = args.binding; - var ds = binding.getSource(); - var fileProvider = ds.getFileProvider(); - var url = null; - //Формируем URL изображения - - if (value) { - if (fileProvider && InfinniUI.BlobUtils.isFileInfo(value)) { - url = fileProvider.getFileUrl(null, null, InfinniUI.BlobUtils.getContentId(value)); - } else if (typeof value === 'string') { - //@TODO Добавить проверку на валидность URI - url = value; - } else { - //Native File instance from FileAPI - url = value; - } - } - return url; +/** + * + * @constructor + * @augments ElementBuilder + * @mixes editorBaseBuilderMixin + */ +function ImageBoxBuilder() { + _.superClass(ImageBoxBuilder, this); + this.initialize_editorBaseBuilder(); +} + +window.InfinniUI.ImageBoxBuilder = ImageBoxBuilder; + +_.inherit(ImageBoxBuilder, ElementBuilder); + +_.extend(ImageBoxBuilder.prototype, { + + createElement: function (params) { + return new ImageBox(params.parent); + }, + + applyMetadata: function (params) { + ElementBuilder.prototype.applyMetadata.call(this, params); + + var element = params.element; + var metadata = params.metadata; + + if (Array.isArray(metadata.AcceptTypes)) { + element.setAcceptTypes(metadata.AcceptTypes); + } + + if (metadata.MaxSize !== null && typeof metadata.MaxSize !== 'undefined') { + element.setMaxSize(metadata.MaxSize); + } + + // Привязка данных односторонняя т.к.: + // 1. по значению из источника данных - сформировать URL изображения. + // 2. при выборе в элементе файла на загрузку - добавить выбранный файл в очередь на загрузку + + var converter = new ImageBoxValueConverter(element); + + var data = this.applyMetadata_editorBaseBuilder(params, { + mode: InfinniUI.BindingModes.toElement, + converter: converter + }); + + var binding = data.valueBinding; + if (binding) { + var ds = binding.getSource(); + + params.element.onPropertyChanged('file', function (context, args) { + var file = args.newValue; + + if (file instanceof File || file === null) { + ds.setProperty(binding.getSourceProperty(), args.newValue) + } + }); + } + + } + +}, editorBaseBuilderMixin); + +//####app/elements/imageBox/imageBoxValueConverter.js +function ImageBoxValueConverter (element) { + this._element = element; +} + +ImageBoxValueConverter.prototype.toElement = function (context, args) { + var value = args.value; + var binding = args.binding; + var ds = binding.getSource(); + var fileProvider = ds.getFileProvider(); + var url = null; + //Формируем URL изображения + + if (value) { + if (fileProvider && InfinniUI.BlobUtils.isFileInfo(value)) { + url = fileProvider.getFileUrl(null, null, InfinniUI.BlobUtils.getContentId(value)); + } else if (typeof value === 'string') { + //@TODO Добавить проверку на валидность URI + url = value; + } else { + //Native File instance from FileAPI + url = value; + } + } + return url; }; //####app/elements/indeterminateCheckBox/indeterminateCheckBox.js /** @@ -24731,137 +25033,137 @@ _.extend(MenuBarBuilder.prototype, }); //####app/elements/numericBox/numericBox.js -/** - * - * @param parent - * @constructor - * @augments TextEditorBase - */ -function NumericBox(parent) { - _.superClass(NumericBox, this, parent); -} - -window.InfinniUI.NumericBox = NumericBox; - -_.inherit(NumericBox, TextEditorBase); - -NumericBox.prototype.createControl = function (parent) { - return new NumericBoxControl(parent); -}; - -NumericBox.prototype.getMinValue = function () { - return this.control.get('minValue'); -}; - -NumericBox.prototype.setMinValue = function (value) { - this.control.set('minValue', value); -}; - -NumericBox.prototype.getMaxValue = function () { - return this.control.get('maxValue'); -}; - -NumericBox.prototype.setMaxValue = function (value) { - this.control.set('maxValue', value); -}; - -NumericBox.prototype.getIncrement = function () { - return this.control.get('increment'); -}; - -NumericBox.prototype.setIncrement = function (value) { - this.control.set('increment', value); -}; - -/** - * @public - * @description Устанваливает начальное значение - * @param {Number} value - */ -NumericBox.prototype.setStartValue = function (value) { - this.control.set('startValue', value); -}; - -NumericBox.prototype.validateValue = function (value) { - var error, - min = this.getMinValue(), - max = this.getMaxValue(); - - value = this.convertValue(value); - - if (value === null || typeof value === 'undefined') { - return error; - } - - if (!_.isNumber(value)) { - error = 'Значение должно быть числом'; - } else if (_.isNumber(min)) { - if (_.isNumber(max)) { - if (value < min || value > max) { - error = 'Значение должно быть от ' + min + ' до ' + max; - } - } else { - if (value < min) { - error = 'Значение должно быть больше ' + min; - } - } - } else { - if (_.isNumber(max)) { - if (value > max) { - error = 'Значение должно быть меьше ' + max; - } - } - } - - return error; -}; - -NumericBox.prototype.convertValue = function (value) { - var val = (value === null || value === '' || typeof value === 'undefined') ? null : +value; - - return _.isNumber(val) ? val : null; -}; - -/** - * @public - * @description Возвращает начальное значение - * @returns {Number} - */ -NumericBox.prototype.getStartValue = function () { - return this.control.get('startValue'); -}; +/** + * + * @param parent + * @constructor + * @augments TextEditorBase + */ +function NumericBox(parent) { + _.superClass(NumericBox, this, parent); +} + +window.InfinniUI.NumericBox = NumericBox; + +_.inherit(NumericBox, TextEditorBase); + +NumericBox.prototype.createControl = function (parent) { + return new NumericBoxControl(parent); +}; + +NumericBox.prototype.getMinValue = function () { + return this.control.get('minValue'); +}; + +NumericBox.prototype.setMinValue = function (value) { + this.control.set('minValue', value); +}; + +NumericBox.prototype.getMaxValue = function () { + return this.control.get('maxValue'); +}; + +NumericBox.prototype.setMaxValue = function (value) { + this.control.set('maxValue', value); +}; + +NumericBox.prototype.getIncrement = function () { + return this.control.get('increment'); +}; + +NumericBox.prototype.setIncrement = function (value) { + this.control.set('increment', value); +}; + +/** + * @public + * @description Устанваливает начальное значение + * @param {Number} value + */ +NumericBox.prototype.setStartValue = function (value) { + this.control.set('startValue', value); +}; + +NumericBox.prototype.validateValue = function (value) { + var error, + min = this.getMinValue(), + max = this.getMaxValue(); + + value = this.convertValue(value); + + if (value === null || typeof value === 'undefined') { + return error; + } + + if (!_.isNumber(value)) { + error = 'Значение должно быть числом'; + } else if (_.isNumber(min)) { + if (_.isNumber(max)) { + if (value < min || value > max) { + error = 'Значение должно быть от ' + min + ' до ' + max; + } + } else { + if (value < min) { + error = 'Значение должно быть больше ' + min; + } + } + } else { + if (_.isNumber(max)) { + if (value > max) { + error = 'Значение должно быть меьше ' + max; + } + } + } + + return error; +}; + +NumericBox.prototype.convertValue = function (value) { + var val = (value === null || value === '' || typeof value === 'undefined') ? null : +value; + + return _.isNumber(val) ? val : null; +}; + +/** + * @public + * @description Возвращает начальное значение + * @returns {Number} + */ +NumericBox.prototype.getStartValue = function () { + return this.control.get('startValue'); +}; //####app/elements/numericBox/numericBoxBuilder.js -/** - * - * @constructor - * @augments TextEditorBaseBuilder - */ -function NumericBoxBuilder() { - _.superClass(NumericBoxBuilder, this); -} - -window.InfinniUI.NumericBoxBuilder = NumericBoxBuilder; - -_.inherit(NumericBoxBuilder, TextEditorBaseBuilder); - -NumericBoxBuilder.prototype.createElement = function (params) { - return new NumericBox(params.parent); -}; - -NumericBoxBuilder.prototype.applyMetadata = function (params) { - TextEditorBaseBuilder.prototype.applyMetadata.call(this, params); - - /** @type NumericBox **/ - var element = params.element; - var metadata = params.metadata; - - element.setMinValue(metadata.MinValue); - element.setMaxValue(metadata.MaxValue); - element.setIncrement(metadata.Increment); - element.setStartValue(metadata.StartValue); -}; - +/** + * + * @constructor + * @augments TextEditorBaseBuilder + */ +function NumericBoxBuilder() { + _.superClass(NumericBoxBuilder, this); +} + +window.InfinniUI.NumericBoxBuilder = NumericBoxBuilder; + +_.inherit(NumericBoxBuilder, TextEditorBaseBuilder); + +NumericBoxBuilder.prototype.createElement = function (params) { + return new NumericBox(params.parent); +}; + +NumericBoxBuilder.prototype.applyMetadata = function (params) { + TextEditorBaseBuilder.prototype.applyMetadata.call(this, params); + + /** @type NumericBox **/ + var element = params.element; + var metadata = params.metadata; + + element.setMinValue(metadata.MinValue); + element.setMaxValue(metadata.MaxValue); + element.setIncrement(metadata.Increment); + element.setStartValue(metadata.StartValue); +}; + //####app/elements/panel/panel.js /** @@ -25153,159 +25455,159 @@ _.extend(PanelBuilder.prototype, /** @lends PanelBuilder.prototype*/ { }); //####app/elements/passwordBox/passwordBox.js -/** - * - * @constructor - * @augments Element - * @mixes editorBaseMixin - * @mixes labelTextElementMixin - */ -function PasswordBox(parent) { - _.superClass(PasswordBox, this, parent); - this.initialize_editorBase(); -} - -window.InfinniUI.PasswordBox = PasswordBox; - -_.inherit(PasswordBox, Element); - -_.extend(PasswordBox.prototype, /* @lends PasswordBox.prototype */ { - - setAutocomplete: function (value) { - if (typeof value === 'undefined' || value === null) { - return; - } - this.control.set('autocomplete', !!value); - }, - - getAutocomplete: function () { - return this.control.get('autocomplete'); - }, - - createControl: function () { - return new PasswordBoxControl(); - }, - - getRawValue: function () { - return this.control.get('rawValue'); - } - - }, - editorBaseMixin, - labelTextElementMixin -); +/** + * + * @constructor + * @augments Element + * @mixes editorBaseMixin + * @mixes labelTextElementMixin + */ +function PasswordBox(parent) { + _.superClass(PasswordBox, this, parent); + this.initialize_editorBase(); +} + +window.InfinniUI.PasswordBox = PasswordBox; + +_.inherit(PasswordBox, Element); + +_.extend(PasswordBox.prototype, /* @lends PasswordBox.prototype */ { + + setAutocomplete: function (value) { + if (typeof value === 'undefined' || value === null) { + return; + } + this.control.set('autocomplete', !!value); + }, + + getAutocomplete: function () { + return this.control.get('autocomplete'); + }, + + createControl: function () { + return new PasswordBoxControl(); + }, + + getRawValue: function () { + return this.control.get('rawValue'); + } + + }, + editorBaseMixin, + labelTextElementMixin +); //####app/elements/passwordBox/passwordBoxBuilder.js -/** - * @constructor - * @augments ElementBuilder - * @mixes editorBaseBuilderMixin - */ -function PasswordBoxBuilder() { - _.superClass(PasswordBoxBuilder, this); - this.initialize_editorBaseBuilder(); -} - -window.InfinniUI.PasswordBoxBuilder = PasswordBoxBuilder; - -_.inherit(PasswordBoxBuilder, ElementBuilder); - -_.extend(PasswordBoxBuilder.prototype, /** @lends PasswordBoxBuilder.prototype */ { - - applyMetadata: function (params) { - ElementBuilder.prototype.applyMetadata.call(this, params); - this.applyMetadata_editorBaseBuilder(params); - - var metadata = params.metadata, - element = params.element; - - this.initBindingToProperty(params, 'LabelText'); - element.setAutocomplete(metadata.Autocomplete); - }, - - createElement: function (params) { - var element = new PasswordBox(params.parent); - return element; - } - - }, - editorBaseBuilderMixin -); +/** + * @constructor + * @augments ElementBuilder + * @mixes editorBaseBuilderMixin + */ +function PasswordBoxBuilder() { + _.superClass(PasswordBoxBuilder, this); + this.initialize_editorBaseBuilder(); +} + +window.InfinniUI.PasswordBoxBuilder = PasswordBoxBuilder; + +_.inherit(PasswordBoxBuilder, ElementBuilder); + +_.extend(PasswordBoxBuilder.prototype, /** @lends PasswordBoxBuilder.prototype */ { + + applyMetadata: function (params) { + ElementBuilder.prototype.applyMetadata.call(this, params); + this.applyMetadata_editorBaseBuilder(params); + + var metadata = params.metadata, + element = params.element; + + this.initBindingToProperty(params, 'LabelText'); + element.setAutocomplete(metadata.Autocomplete); + }, + + createElement: function (params) { + var element = new PasswordBox(params.parent); + return element; + } + + }, + editorBaseBuilderMixin +); //####app/elements/popupButton/popupButton.js -/** - * @class - * @constructor - * @augments Container - * @augments Button - */ -function PopupButton(parent, viewMode) { - _.superClass(PopupButton, this, parent, viewMode); - this.buttonInit(); -} - -window.InfinniUI.PopupButton = PopupButton; - -_.inherit(PopupButton, Container); - -_.extend(PopupButton.prototype, { - - createControl: function (viewMode) { - return new PopupButtonControl(viewMode); - } - -}, buttonMixin); +/** + * @class + * @constructor + * @augments Container + * @augments Button + */ +function PopupButton(parent, viewMode) { + _.superClass(PopupButton, this, parent, viewMode); + this.buttonInit(); +} + +window.InfinniUI.PopupButton = PopupButton; + +_.inherit(PopupButton, Container); + +_.extend(PopupButton.prototype, { + + createControl: function (viewMode) { + return new PopupButtonControl(viewMode); + } + +}, buttonMixin); //####app/elements/popupButton/popupButtonBuilder.js -/** - * @constructor - * @augments ContainerBuilder - */ -function PopupButtonBuilder() { - _.superClass(PopupButtonBuilder, this); -} - -window.InfinniUI.PopupButtonBuilder = PopupButtonBuilder; - -_.inherit(PopupButtonBuilder, ContainerBuilder); - -_.extend(PopupButtonBuilder.prototype, /** @lends PopupButtonBuilder.prototype */{ - - createElement: function (params) { - var viewMode = this.detectViewMode(params); - return new PopupButton(params.parent, viewMode); - }, - - detectViewMode: function(params){ - var viewMode = params.metadata['ViewMode']; - var el = params.parent; - var exit = false; - - if(!viewMode){ - while(!exit){ - if(el){ - if(el instanceof MenuBar){ - viewMode = 'forMenu'; - exit = true; - }else{ - el = el.parent; - } - }else{ - exit = true; - } - } - - } - - return viewMode - }, - - applyMetadata: function (params) { - ContainerBuilder.prototype.applyMetadata.call(this, params); - this.applyButtonMetadata.call(this, params); - } - -}, buttonBuilderMixin); +/** + * @constructor + * @augments ContainerBuilder + */ +function PopupButtonBuilder() { + _.superClass(PopupButtonBuilder, this); +} + +window.InfinniUI.PopupButtonBuilder = PopupButtonBuilder; + +_.inherit(PopupButtonBuilder, ContainerBuilder); + +_.extend(PopupButtonBuilder.prototype, /** @lends PopupButtonBuilder.prototype */{ + + createElement: function (params) { + var viewMode = this.detectViewMode(params); + return new PopupButton(params.parent, viewMode); + }, + + detectViewMode: function(params){ + var viewMode = params.metadata['ViewMode']; + var el = params.parent; + var exit = false; + + if(!viewMode){ + while(!exit){ + if(el){ + if(el instanceof MenuBar){ + viewMode = 'forMenu'; + exit = true; + }else{ + el = el.parent; + } + }else{ + exit = true; + } + } + + } + + return viewMode + }, + + applyMetadata: function (params) { + ContainerBuilder.prototype.applyMetadata.call(this, params); + this.applyButtonMetadata.call(this, params); + } + +}, buttonBuilderMixin); //####app/elements/radioGroup/radioGroupBuilder.js function RadioGroupBuilder() { @@ -25659,242 +25961,350 @@ _.extend(TablePanelBuilder.prototype, }); //####app/elements/toggleButton/toggleButton.js -/** - * - * @param parent - * @constructor - * @augment Element - */ -function ToggleButton(parent) { - _.superClass(ToggleButton, this, parent); - this.initialize_editorBase(); -} - -window.InfinniUI.ToggleButton = ToggleButton; - -_.inherit(ToggleButton, Element); - - -_.extend(ToggleButton.prototype, { - - createControl: function (parent) { - return new ToggleButtonControl(parent); - }, - - getTextOn: function () { - return this.control.get('textOn'); - }, - - setTextOn: function (value) { - return this.control.set('textOn', value ? value : ''); - }, - - getTextOff: function () { - return this.control.get('textOff'); - }, - - setTextOff: function (value) { - return this.control.set('textOff', value ? value : ''); - } -}, editorBaseMixin); +/** + * + * @param parent + * @constructor + * @augment Element + */ +function ToggleButton(parent) { + _.superClass(ToggleButton, this, parent); + this.initialize_editorBase(); +} + +window.InfinniUI.ToggleButton = ToggleButton; + +_.inherit(ToggleButton, Element); + + +_.extend(ToggleButton.prototype, { + + createControl: function (parent) { + return new ToggleButtonControl(parent); + }, + + getTextOn: function () { + return this.control.get('textOn'); + }, + + setTextOn: function (value) { + return this.control.set('textOn', value ? value : ''); + }, + + getTextOff: function () { + return this.control.get('textOff'); + }, + + setTextOff: function (value) { + return this.control.set('textOff', value ? value : ''); + } +}, editorBaseMixin); //####app/elements/toggleButton/toggleButtonBuilder.js -/** - * - * @constructor - * @augments ElementBuilder - */ -function ToggleButtonBuilder() { - _.superClass(ToggleButtonBuilder, this); - this.initialize_editorBaseBuilder(); -} - -window.InfinniUI.ToggleButtonBuilder = ToggleButtonBuilder; - -_.inherit(ToggleButtonBuilder, ElementBuilder); - - -_.extend(ToggleButtonBuilder.prototype, { - createElement: function (params) { - return new ToggleButton(params.parent); - }, - - applyMetadata: function (params) { - ElementBuilder.prototype.applyMetadata.call(this, params); - this.applyMetadata_editorBaseBuilder(params); - - /** @type {ToggleButton} */ - var element = params.element; - /** @type {ToggleButtonMetadata} */ - var metadata = params.metadata; - - element.setTextOff(metadata.TextOff); - element.setTextOn(metadata.TextOn); - } -}, editorBaseBuilderMixin); - -/** - * @typedef {Object} ToggleButtonMetadata - * @property {String} TextOn - * @property {String} TextOff - */ +/** + * + * @constructor + * @augments ElementBuilder + */ +function ToggleButtonBuilder() { + _.superClass(ToggleButtonBuilder, this); + this.initialize_editorBaseBuilder(); +} + +window.InfinniUI.ToggleButtonBuilder = ToggleButtonBuilder; + +_.inherit(ToggleButtonBuilder, ElementBuilder); + + +_.extend(ToggleButtonBuilder.prototype, { + createElement: function (params) { + return new ToggleButton(params.parent); + }, + + applyMetadata: function (params) { + ElementBuilder.prototype.applyMetadata.call(this, params); + this.applyMetadata_editorBaseBuilder(params); + + /** @type {ToggleButton} */ + var element = params.element; + /** @type {ToggleButtonMetadata} */ + var metadata = params.metadata; + + element.setTextOff(metadata.TextOff); + element.setTextOn(metadata.TextOn); + } +}, editorBaseBuilderMixin); + +/** + * @typedef {Object} ToggleButtonMetadata + * @property {String} TextOn + * @property {String} TextOff + */ //####app/elements/toolBar/toolBar.js -/** - * - * @param parent - * @constructor - * @augments Container - */ -var ToolBar = function (parent) { - _.superClass(ToolBar, this, parent); -}; - -window.InfinniUI.ToolBar = ToolBar; - -_.inherit(ToolBar, Container); - -ToolBar.prototype.createControl = function () { - return new ToolBarControl(); -}; +/** + * + * @param parent + * @constructor + * @augments Container + */ +var ToolBar = function (parent) { + _.superClass(ToolBar, this, parent); +}; + +window.InfinniUI.ToolBar = ToolBar; + +_.inherit(ToolBar, Container); + +ToolBar.prototype.createControl = function () { + return new ToolBarControl(); +}; //####app/elements/toolBar/toolBarBuilder.js -/** - * - * @constructor - * @augments ContainerBuilder - */ -function ToolBarBuilder() { - _.superClass(ToolBarBuilder, this); -} - -window.InfinniUI.ToolBarBuilder = ToolBarBuilder; +/** + * + * @constructor + * @augments ContainerBuilder + */ +function ToolBarBuilder() { + _.superClass(ToolBarBuilder, this); +} + +window.InfinniUI.ToolBarBuilder = ToolBarBuilder; + +_.inherit(ToolBarBuilder, ContainerBuilder); + +_.extend(ToolBarBuilder.prototype, /** @lends ToolBarBuilder.prototype */{ + + createElement: function (params) { + return new ToolBar(params.parent); + } + +}); + +//####app/elements/tooltip/tooltip.js +var Tooltip = function (parent) { + _.superClass( Icon, this, parent ); +}; + +_.inherit(Tooltip, Element); + + +_.extend(Tooltip.prototype, { -_.inherit(ToolBarBuilder, ContainerBuilder); - -_.extend(ToolBarBuilder.prototype, /** @lends ToolBarBuilder.prototype */{ + createControl: function () { + return new InfinniUI.TooltipControl(); + }, - createElement: function (params) { - return new ToolBar(params.parent); + setContent: function (content) { + this.control.set('content', content); } + }); -//####app/elements/treeView/treeView.js -/** - * @param parent - * @constructor - */ -function TreeView(parent) { - _.superClass(TreeView, this, parent); -} -window.InfinniUI.TreeView = TreeView; +InfinniUI.Tooltip = Tooltip; -_.inherit(TreeView, ListEditorBase); +//####app/elements/tooltip/tooltipBuilder.js +function TooltipBuilder() { + _.superClass( TooltipBuilder, this ); +} -TreeView.prototype.createControl = function () { - return new TreeViewControl(); -}; +InfinniUI.TooltipBuilder = TooltipBuilder; -/** - * - * @returns Function} - */ -TreeView.prototype.getKeySelector = function () { - return this.control.get('keySelector'); -}; +_.inherit( TooltipBuilder, ElementBuilder ); -/** - * - * @param {Function} value - */ -TreeView.prototype.setKeySelector = function (value) { - this.control.set('keySelector', value); -}; +_.extend( TooltipBuilder.prototype, { -/** - * - * @returns {Function} - */ -TreeView.prototype.getParentSelector = function () { - return this.control.get('parentSelector'); -}; + createElement: function( params ) { + return new InfinniUI.Tooltip(); + }, -/** - * - * @param {Function} value - */ -TreeView.prototype.setParentSelector = function (value) { - this.control.set('parentSelector', value); -}; + normalizeMetadata: function( metadata ) { + if( typeof metadata === 'string' ) { + metadata = { + Text: metadata + } + } -//####app/elements/treeView/treeViewBuilder.js -function TreeViewBuilder() { - _.superClass(TreeViewBuilder, this); -} + return metadata; + }, -window.InfinniUI.TreeViewBuilder = TreeViewBuilder; + applyMetadata: function( params ) { + var tooltip = params.element; -_.inherit(TreeViewBuilder, ListEditorBaseBuilder); + params.metadata = this.normalizeMetadata( params.metadata ); -_.extend(TreeViewBuilder.prototype, /** @lends TreeViewBuilder.prototype */{ + ElementBuilder.prototype.applyMetadata.call( this, params ); + tooltip.setContent( this.buildContent( params.metadata, params ) ); - createElement: function (params) { - return new TreeView(params.parent); - }, + var exchange = InfinniUI.global.messageBus; - applyMetadata: function (params) { - var data = ListEditorBaseBuilder.prototype.applyMetadata.call(this, params); + exchange.send(messageTypes.onToolTipInit, {element: params.parent, content: tooltip}); + params.parent.onRemove(function () { + exchange.send(messageTypes.onToolTipDestroy, {element: params.parent}); + }); - this._initKeySelector(params); - this._initParentSelector(params); }, - _initKeySelector: function (params) { - var element = params.element; - var metadata = params.metadata; - var keySelector; + buildContent: function( metadata, params ) { + var builder = params.builder; + var builderParams = { + parent: params.element, + parentView: params.parentView, + basePathOfProperty: params.basePathOfProperty + }; + var content; - if (metadata.KeySelector) { - keySelector = function (context, args) { - var scriptExecutor = new ScriptExecutor(element.getScriptsStorage()); - return scriptExecutor.executeScript(metadata.KeySelector.Name || metadata.KeySelector, args) - } - } else if (metadata.KeyProperty) { - keySelector = function (context, args) { - return InfinniUI.ObjectUtils.getPropertyValue(args.value, metadata.KeyProperty); - } + if( 'Text' in metadata ) { + content = this.buildTextContent( metadata[ 'Text' ], builder, builderParams ); } else { - keySelector = function (context, args) { - return args.value; - } + content = this.buildElementContent( metadata, builder, builderParams ); } - element.setKeySelector(keySelector); + + return content; }, - _initParentSelector: function (params) { - var element = params.element; - var metadata = params.metadata; - var parentSelector; + /** + * @protected + * @param text + * @param builder + * @param builderParams + * @return {*} + */ + buildTextContent: function( text, builder, builderParams ) { + return builder.buildType( "Label", { + "Text": text + }, builderParams ) + }, - if (metadata.ParentSelector) { - parentSelector = function (context, args) { - var scriptExecutor = new ScriptExecutor(element.getScriptsStorage()); - return scriptExecutor.executeScript(metadata.ParentSelector.Name || metadata.ParentSelector, args) - } - } else if (metadata.ParentProperty) { - parentSelector = function (context, args) { - return InfinniUI.ObjectUtils.getPropertyValue(args.value, metadata.ParentProperty); - } - } else { - parentSelector = function (context, args) { - return args.value; - } - } - element.setParentSelector(parentSelector); + /** + * @protected + * @param metadata + * @param builder + * @param builderParams + */ + buildElementContent: function( metadata, builder, builderParams ) { + return builder.build( metadata, builderParams ); } -}); + +} ); +//####app/elements/treeView/treeView.js +/** + * @param parent + * @constructor + */ +function TreeView(parent) { + _.superClass(TreeView, this, parent); +} + +window.InfinniUI.TreeView = TreeView; + +_.inherit(TreeView, ListEditorBase); + +TreeView.prototype.createControl = function () { + return new TreeViewControl(); +}; + +/** + * + * @returns Function} + */ +TreeView.prototype.getKeySelector = function () { + return this.control.get('keySelector'); +}; + +/** + * + * @param {Function} value + */ +TreeView.prototype.setKeySelector = function (value) { + this.control.set('keySelector', value); +}; + +/** + * + * @returns {Function} + */ +TreeView.prototype.getParentSelector = function () { + return this.control.get('parentSelector'); +}; + +/** + * + * @param {Function} value + */ +TreeView.prototype.setParentSelector = function (value) { + this.control.set('parentSelector', value); +}; + +//####app/elements/treeView/treeViewBuilder.js +function TreeViewBuilder() { + _.superClass(TreeViewBuilder, this); +} + +window.InfinniUI.TreeViewBuilder = TreeViewBuilder; + +_.inherit(TreeViewBuilder, ListEditorBaseBuilder); + +_.extend(TreeViewBuilder.prototype, /** @lends TreeViewBuilder.prototype */{ + + createElement: function (params) { + return new TreeView(params.parent); + }, + + applyMetadata: function (params) { + var data = ListEditorBaseBuilder.prototype.applyMetadata.call(this, params); + + this._initKeySelector(params); + this._initParentSelector(params); + }, + + _initKeySelector: function (params) { + var element = params.element; + var metadata = params.metadata; + var keySelector; + + if (metadata.KeySelector) { + keySelector = function (context, args) { + var scriptExecutor = new ScriptExecutor(element.getScriptsStorage()); + return scriptExecutor.executeScript(metadata.KeySelector.Name || metadata.KeySelector, args) + } + } else if (metadata.KeyProperty) { + keySelector = function (context, args) { + return InfinniUI.ObjectUtils.getPropertyValue(args.value, metadata.KeyProperty); + } + } else { + keySelector = function (context, args) { + return args.value; + } + } + element.setKeySelector(keySelector); + }, + + _initParentSelector: function (params) { + var element = params.element; + var metadata = params.metadata; + var parentSelector; + + if (metadata.ParentSelector) { + parentSelector = function (context, args) { + var scriptExecutor = new ScriptExecutor(element.getScriptsStorage()); + return scriptExecutor.executeScript(metadata.ParentSelector.Name || metadata.ParentSelector, args) + } + } else if (metadata.ParentProperty) { + parentSelector = function (context, args) { + return InfinniUI.ObjectUtils.getPropertyValue(args.value, metadata.ParentProperty); + } + } else { + parentSelector = function (context, args) { + return args.value; + } + } + element.setParentSelector(parentSelector); + } +}); //####app/elements/view/view.js /** @@ -26240,18 +26650,6 @@ _.extend(View.prototype, getFocusOnControl: function () { return this.control.get('focusOnControl'); } - -//devblockstart - ,showSelectedElementMetadata: function(){ - if(this.handlers.onSelectedElementChange){ - this.handlers.onSelectedElementChange(); - } - } - - ,onSelectedElementChange: function(handler) { - this.handlers.onSelectedElementChange = handler; - } -//devblockstop } ); @@ -26273,35 +26671,6 @@ _.extend(ViewBuilder.prototype, { return new View(params.parent); }, -//devblockstart - _getSelectedElementPath: function(metadata) { - var result; - - if( _.isArray(metadata) ){ - for (var i = 0, ii = metadata.length; i/g, function(p1, p2){ - return that.getParam(p2); + if (callback) { + callback(context, args); + } }); - }, - _replaceParamsInObject: function(obj){ - if(_.isEmpty(obj) ){ - return obj; - } - - var str = JSON.stringify(obj); - var replacedStr = this._replaceParamsInStr(str); - return JSON.parse(replacedStr); - } + createdView.open(); + }); } -); +}); -window.InfinniUI.ServerAction = ServerAction; +window.InfinniUI.SelectAction = SelectAction; -//####app/actions/serverAction/serverActionBuilder.js -function ServerActionBuilder() {} +//####app/actions/selectAction/selectActionBuilder.js +function SelectActionBuilder() {} -_.extend(ServerActionBuilder.prototype, +_.extend(SelectActionBuilder.prototype, BaseActionBuilderMixin, - BaseFallibleActionBuilderMixin, { build: function (context, args) { var builder = args.builder, metadata = args.metadata, parentView = args.parentView; - var action = new ServerAction(parentView); + var action = new SelectAction(parentView); this.applyBaseActionMetadata(action, args); - this.applyBaseFallibleActionMetadata(action, args); - - action.setProperty('origin', metadata.Origin); - action.setProperty('path', metadata.Path); - if (metadata.Data) { - action.setProperty('data', metadata.Data); - } - - if (metadata.Method) { - action.setProperty('method', metadata.Method); - } - - if (metadata.ContentType || metadata.ContentType === false) { - action.setProperty('contentType', metadata.ContentType); - } - - if(metadata.Params){ - for(var name in metadata.Params) { - - var value = metadata.Params[name]; + var linkView = builder.build(metadata['LinkView'], {parentView: parentView}); - if (typeof value != 'object') { - if (value !== undefined) { - action.setParam(name, value); - } - } else { - this._initBinding(name, value, action, parentView, builder); - } - } - } + action.setProperty('linkView', linkView); + action.setProperty('sourceSource', metadata.SourceValue.Source); + action.setProperty('sourceProperty', metadata.SourceValue.Property); + action.setProperty('destinationSource', metadata.DestinationValue.Source); + action.setProperty('destinationProperty', metadata.DestinationValue.Property); return action; - }, - - _initBinding: function (paramName, paramValue, action, parentView, builder) { - var args = { - parent: parentView, - parentView: parentView - }; - - var dataBinding = builder.buildBinding(paramValue, args); - - dataBinding.setMode(InfinniUI.BindingModes.toElement); - - dataBinding.bindElement({ - setProperty: function (name, value) { - action.setParam(name, value); - }, - - onPropertyChanged: function () { - } - - }, paramName); } } ); -window.InfinniUI.ServerActionBuilder = ServerActionBuilder; +window.InfinniUI.SelectActionBuilder = SelectActionBuilder; + +//####app/actions/serverAction/downloadExecutor.js +/** + * @description + * Для закачки контента по POST запросу используется подход: {@link http://gruffcode.com/2010/10/28/detecting-the-file-download-dialog-in-the-browser/} + * @param resultCallback + * @param successCallback + * @param failCallback + * @constructor + */ +function DownloadExecutor(resultCallback, successCallback, failCallback) { + this.guid = guid(); + this.options = { + timeout: 1 * 60 * 1000, + poll: 100 + }; + + this.resultCallback = resultCallback; + this.successCallback = successCallback; + this.failCallback = failCallback; +} + +window.InfinniUI.DownloadExecutor = DownloadExecutor; + +DownloadExecutor.prototype.config = function (options) { + _.extend(this.options, options); +}; + +DownloadExecutor.prototype.run = function (requestData) { + + var cleanup = this.cleanup.bind(this); + + var onResult = function () { + if (typeof this.resultCallback === 'function') { + this.resultCallback.apply(this, arguments); + } + }.bind(this); + + var onSuccess = function (data) { + if (typeof this.successCallback === 'function') { + this.successCallback.call(this, data); + } + onResult(data); + }.bind(this); + + var onError = function (err) { + if (typeof this.successCallback === 'function') { + this.successCallback.call(this, data); + } + onResult(err); + }; + + this.waitResponse(cleanup) + .always(function () { + cleanup(); + }) + .done(onSuccess) + .fail(onError); + + this.openWindow(requestData); +}; + +DownloadExecutor.prototype.openWindow = function (requestData) { + var windowName = this.getName("window"); + var form = document.createElement("form"); + this.form = form; + + form.setAttribute("method", requestData.method); + form.setAttribute("action", requestData.requestUrl); + form.setAttribute("target", windowName); + form.setAttribute("style", "display: none;"); + + var dataField = document.createElement("input"); + dataField.setAttribute("name", "data"); + dataField.setAttribute("value", JSON.stringify(requestData.args)); + form.appendChild(dataField); + + //Cookie которую долден вернуть сервер с отправкой запрошенного контента + var tokenField = document.createElement("input"); + tokenField.setAttribute("name", "token"); + tokenField.setAttribute("value", this.getName('token')); + form.appendChild(tokenField); + + + document.body.appendChild(form); + this.popup = window.open("about:blank", windowName); + form.submit(); +}; + +DownloadExecutor.prototype.getName = function (name) { + return name + this.guid; +}; + +DownloadExecutor.prototype.cleanup = function () { + clearInterval(this.intervalId); + clearTimeout(this.timeout); + $.removeCookie(this.getName('token')); + if (this.form) { + this.form.remove(); + this.form = null; + } + if (this.popup) { + this.popup.close(); + this.popup = null; + } +}; + +DownloadExecutor.prototype.waitResponse = function (beforeStart) { + var cookieName = this.getName('token'); + var defer = $.Deferred(beforeStart); + + //Check cookie from server's response + this.intervalId = setInterval(function () { + var cookie = $.cookie(cookieName); + if (cookie === cookieName) { + defer.resolve(); + } + }, this.options.poll); + + //Check timeout + this.timeout = setTimeout(function () { + defer.reject(); + }, this.options.timeout); + + return defer.promise(); +}; + +//####app/actions/serverAction/serverAction.js +function ServerAction(parentView) { + _.superClass(ServerAction, this, parentView); + + this.provider = window.InfinniUI.providerRegister.build('ServerActionProvider'); + + this.updateContentTypeStrategy(); + this.on('change:contentType', this.updateContentTypeStrategy); +} + +_.inherit(ServerAction, BaseAction); + +_.extend(ServerAction.prototype, + BaseFallibleActionMixin, + { + defaults: { + contentType: 'application/x-www-form-urlencoded; charset=utf-8', + method: 'GET', + data: {} + }, + + updateContentTypeStrategy: function () { + var contentType = this.getProperty('contentType'); + + if( _.isString(contentType) && contentType.includes('multipart') ){ + this.contentTypeStrategy = serverActionContentTypeStrategy['File']; + } else { + this.contentTypeStrategy = serverActionContentTypeStrategy['Object']; + } + }, + + execute: function (callback) { + var that = this, + onExecuted = function(args){ + that.onExecutedHandler(args); + + if (_.isFunction(callback)) { + callback(args); + } + }, + onSuccess = function(args) { + that.onSuccessHandler(args); + }, + onError = function(args) { + that.onErrorHandler(args); + }; + + this.contentTypeStrategy.run(this.provider, this._getRequestData(), onExecuted, onSuccess, onError); + }, + + setParam: function(name, value) { + this.setProperty('params.' + name, value); + }, + + getParam: function(name) { + return this.getProperty('params.' + name); + }, + + _getRequestData: function () { + var origin = this._replaceParamsInStr( this.getProperty('origin') ); + var path = this._replaceParamsInStr( this.getProperty('path') ); + var method = this.getProperty('method').toUpperCase(); + var contentType = this.getProperty('contentType'); + var data = this._replaceParamsInObject( this.getProperty('data') ); + + var result = {}; + result.requestUrl = origin + path; + result.method = method; + result.contentType = contentType; + + if( !_.isEmpty(data) ){ + if( method == 'GET') { + result.requestUrl = result.requestUrl + '?' + stringUtils.joinDataForQuery(data); + } else { + result.args = ( _.isString(contentType) && contentType.includes('application/json')) ? JSON.stringify(data) : data; + } + } + + return result; + }, + + _replaceParamsInStr: function(str, escape){ + + if(!str || !_.isString(str)){ + return str; + } + + var that = this; + + + var matched = str.match(/^<%([\s\S]+?)%>$/); + + if (matched) { + return this.getParam(matched[1]); + } + + return str.replace(/<%([\s\S]+?)%>/g, function(p1, p2){ + var val = that.getParam(p2); + + if (escape && _.isString(val)) { + val = val.replace(/"/g,'\\"'); + } + return val; + }); + }, + + _compileData: function (data) { + var res; + + if (Array.isArray(data)) { + res = Array.map(function (item) { + if (_.isObject(item) || Array.isArray(item)) { + this._compileData(item); + } + }, this); + } else if (_.isObject(data)) { + res = {}; + Object.keys(data).forEach(function (name) { + var parsedName = this._replaceParamsInStr(name); + + res[parsedName] = this._compileData(data[name]); + }, this); + } else { + res = this._replaceParamsInStr(data, true); + } + + return res; + }, + _replaceParamsInObject: function(obj){ + if(_.isEmpty(obj) ){ + return obj; + } + + + return this._compileData(obj); + } + } +); + +window.InfinniUI.ServerAction = ServerAction; + +//####app/actions/serverAction/serverActionBuilder.js +function ServerActionBuilder() {} + +_.extend(ServerActionBuilder.prototype, + BaseActionBuilderMixin, + BaseFallibleActionBuilderMixin, + { + build: function (context, args) { + var builder = args.builder, + metadata = args.metadata, + parentView = args.parentView; + + var action = new ServerAction(parentView); + + this.applyBaseActionMetadata(action, args); + this.applyBaseFallibleActionMetadata(action, args); + + action.setProperty('origin', metadata.Origin || InfinniUI.config.serverUrl.replace(/\/$/, '')); + action.setProperty('path', metadata.Path); + + if (metadata.Data) { + action.setProperty('data', metadata.Data); + } + + if (metadata.Method) { + action.setProperty('method', metadata.Method); + } + + if (metadata.ContentType || metadata.ContentType === false) { + action.setProperty('contentType', metadata.ContentType); + } + + if(metadata.Params){ + for(var name in metadata.Params) { + + var value = metadata.Params[name]; + + if (Array.isArray(value) || value === null || typeof value != 'object') { + if (value !== undefined) { + action.setParam(name, value); + } + } else { + this._initBinding(name, value, action, parentView, builder); + } + } + } + + return action; + }, + + _initBinding: function (paramName, paramValue, action, parentView, builder) { + var args = { + parent: parentView, + parentView: parentView + }; + + var dataBinding = builder.buildBinding(paramValue, args); + + dataBinding.setMode(InfinniUI.BindingModes.toElement); + + dataBinding.bindElement({ + setProperty: function (name, value) { + action.setParam(name, value); + }, + + onPropertyChanged: function () { + } + + }, paramName); + } + } +); + +window.InfinniUI.ServerActionBuilder = ServerActionBuilder; //####app/actions/serverAction/serverActionContentTypeStrategy.js -var serverActionContentTypeStrategy = { - "File": { - run: function (provider, params, callback, onSuccess, onError) { - provider.download(params, callback, onSuccess, onError); - } - }, - "Object": { - run: function (provider, params, callback, onSuccess, onError) { - provider.request(params, callback, onSuccess, onError); - } - } +var serverActionContentTypeStrategy = { + "File": { + run: function (provider, params, callback, onSuccess, onError) { + provider.download(params, callback, onSuccess, onError); + } + }, + "Object": { + run: function (provider, params, callback, onSuccess, onError) { + provider.request(params, callback, onSuccess, onError); + } + } }; //####app/actions/updateAction/updateAction.js function UpdateAction(parentView){ @@ -28260,6 +28653,8 @@ _.extend(ApplicationBuilder.prototype, { builder.register('MenuBar', new MenuBarBuilder()); builder.register('DataGrid', new DataGridBuilder()); + builder.register('DataGridRow', new DataGridRowBuilder()); + builder.register('DataGridColumn', new DataGridColumnBuilder()); builder.register('ListBox', new ListBoxBuilder()); @@ -28327,6 +28722,8 @@ _.extend(ApplicationBuilder.prototype, { builder.register('Divider', new DividerBuilder()); builder.register('ContextMenu', new ContextMenuBuilder()); + builder.register('ToolTip', new InfinniUI.TooltipBuilder()); + var registerQueue = ApplicationBuilder.registerQueue; for(var i = 0, ii = registerQueue.length; i 12){ - hoursIndex -= 12; - } - return hoursIndex.toString(); - }, 'h': function(date){ var hoursIndex = date.getHours(); if(hoursIndex > 12){ hoursIndex -= 12; + } else if (hoursIndex === 0) { + hoursIndex = 12; } return hoursIndex.toString(); }, @@ -30793,12 +31194,56 @@ var DateTimeMaskPartStrategy = (function () { var regExpFullYear = /^\d{1,4}$/; var regExpYear = /^\d{1,2}$/; var regExpHour24 = /^(?:[2][0-3]|[01]?[0-9]?)$/; + var regExpHour12 = /^(?:0?\d|1[0-2])$/; var regExp60 = /^[0-5]?[0-9]$/; + function filledDay(value) { + if (value === null || typeof value === 'undefined') { + return false; + } + + var val = parseInt(value, 10); + return [4,5,6,7,8,9].indexOf(val) !== -1 || value.length === 2; + } + + function filledMonth(value) { + if (value === null || typeof value === 'undefined') { + return false; + } + + var val = parseInt(value, 10); + return [2,3,4,5,6,7,8,9].indexOf(val) !== -1 || value.length === 2; + } + + function filledHours(value) { + if (value === null || typeof value === 'undefined') { + return false; + } + + return parseInt(value, 10) > 2 || value.length === 2; + } + + function filledMinutes(value) { + if (value === null || typeof value === 'undefined') { + return false; + } + + return parseInt(value, 10) > 5 || value.length === 2; + } + + function filledSeconds(value) { + if (value === null || typeof value === 'undefined') { + return false; + } + + return parseInt(value, 10) > 5 || value.length === 2; + } + + return { 'd': { init: function () { - this.width = 2; + this.width = 1; this.min = 1; this.max = 31; }, @@ -30808,6 +31253,7 @@ var DateTimeMaskPartStrategy = (function () { validator: function (value) { return this.rangeValidator(value); }, + filled: filledDay, prev: function (value) { return this.getPrevIntValue(value); }, @@ -30834,6 +31280,7 @@ var DateTimeMaskPartStrategy = (function () { validator: function (value) { return this.rangeValidator(value); }, + filled: filledDay, prev: function (value) { return this.getPrevIntValue(value); }, @@ -30850,7 +31297,7 @@ var DateTimeMaskPartStrategy = (function () { }, 'M': { init: function () { - this.width = 2; + this.width = 1; this.min = 1; this.max = 12; }, @@ -30860,6 +31307,7 @@ var DateTimeMaskPartStrategy = (function () { validator: function (value) { return this.rangeValidator(value); }, + filled: filledMonth, prev: function (value) { return this.getPrevIntValue(value); }, @@ -30886,6 +31334,7 @@ var DateTimeMaskPartStrategy = (function () { validator: function (value) { return this.rangeValidator(value); }, + filled: filledMonth, prev: function (value) { return this.getPrevIntValue(value); }, @@ -30984,22 +31433,50 @@ var DateTimeMaskPartStrategy = (function () { return this.padNumber(value); }, apply: function (value, part) { - value.setFullYear(part); + value.setFullYear(part); + return value; + } + }, + 'H': { + init: function () { + this.width = 1; + this.min = 0; + this.max = 23; + }, + match: function (value) { + return regExpHour24.test(value); + }, + validator: function (value) { + return this.rangeValidator(value); + }, + filled: filledHours, + prev: function (value) { + return this.getPrevIntValue(value); + }, + next: function (value) { + return this.getNextIntValue(value); + }, + format: function (value) { + return this.padNumber(value); + }, + apply: function (value, part) { + value.setHours(part); return value; } }, - 'H': { + 'h': { init: function () { - this.width = 2; - this.min = 0; - this.max = 23; + this.width = 1; + this.min = 1; + this.max = 12; }, match: function (value) { - return regExpHour24.test(value); + return regExpHour12.test(value); }, validator: function (value) { return this.rangeValidator(value); }, + filled: filledHours, prev: function (value) { return this.getPrevIntValue(value); }, @@ -31026,6 +31503,7 @@ var DateTimeMaskPartStrategy = (function () { validator: function (value) { return this.rangeValidator(value); }, + filled: filledHours, prev: function (value) { return this.getPrevIntValue(value); }, @@ -31042,7 +31520,7 @@ var DateTimeMaskPartStrategy = (function () { }, 'm': { init: function () { - this.width = 2; + this.width = 1; this.min = 0; this.max = 59; }, @@ -31052,6 +31530,7 @@ var DateTimeMaskPartStrategy = (function () { validator: function (value) { return this.rangeValidator(value); }, + filled: filledMinutes, prev: function (value) { return this.getPrevIntValue(value); }, @@ -31078,6 +31557,7 @@ var DateTimeMaskPartStrategy = (function () { validator: function (value) { return this.rangeValidator(value); }, + filled: filledMinutes, prev: function (value) { return this.getPrevIntValue(value); }, @@ -31094,7 +31574,7 @@ var DateTimeMaskPartStrategy = (function () { }, 's': { init: function () { - this.width = 2; + this.width = 1; this.min = 0; this.max = 59; }, @@ -31104,6 +31584,7 @@ var DateTimeMaskPartStrategy = (function () { validator: function (value) { return this.rangeValidator(value); }, + filled: filledSeconds, prev: function (value) { return this.getPrevIntValue(value); }, @@ -31130,6 +31611,7 @@ var DateTimeMaskPartStrategy = (function () { validator: function (value) { return this.rangeValidator(value); }, + filled: filledSeconds, prev: function (value) { return this.getPrevIntValue(value); }, @@ -31196,6 +31678,44 @@ var DateTimeMaskPartStrategy = (function () { if (index !== -1) { value.setMonth(index); } + return value; + } + }, + 'tt': { + init: function () { + // this.min = 0; + // this.max = 1; + this.width = 2; + }, + match: function() { + return false; + }, + prev: function (value) { + var newValue = this.getPrevMonthValue('tt', value); + + return (newValue === value) ? this.getNextMonthValue('tt', value): newValue; + }, + next: function (value) { + var newValue = this.getNextMonthValue('tt', value); + return (newValue === value) ? this.getPrevMonthValue('tt', value): newValue; + }, + apply: function (value, part) { + if (value instanceof Date) { + var hours = value.getHours(); + var culture = this.getCurrentCulture(); + var formatInfo = culture.dateTimeFormatInfo; + + if (hours >= 12) { + hours = hours - 12; + } + + if (part === formatInfo.pmDesignator) { + hours += 12; + } + + value.setHours(hours); + } + return value; } } @@ -31215,6 +31735,14 @@ _.extend(DateTimeMaskPart.prototype, { }, + filled: function (value) { + if (value === null || typeof value === 'undefined') { + return false; + } + + return value.length === this.width; + }, + match: function (value) { return true; }, @@ -31290,9 +31818,15 @@ _.extend(DateTimeMaskPart.prototype, { return value; }, + getCurrentCulture: function () { + var culture = new Culture(InfinniUI.config.lang); + + return culture; + }, + getListForMask: function (mask) { //@TODO Получать культуру из контекста! - var culture = new Culture(InfinniUI.config.lang); + var culture = this.getCurrentCulture(); var formatInfo = culture.dateTimeFormatInfo; var list; @@ -31310,6 +31844,9 @@ _.extend(DateTimeMaskPart.prototype, { case 'ddd': list = formatInfo.abbreviatedDayNames; break; + case 'tt': + list = [formatInfo.amDesignator, formatInfo.pmDesignator]; + break; } return list; @@ -31679,27 +32216,25 @@ _.extend(DateTimeEditMask.prototype, { if (data !== null) { item = data.item; - index = position - data.left; + index = position - data.left; //Позиция внутри текущего шаблона ввода маски - if (index > item.text.length) { + if (index > item.text.length) { //Если превышение по правой границе - в конец + position = data.left + item.text.length; + index = item.text.length; + } else if (index < 0) { //Если превышение по левой границе - в начало шаблона position = data.left; + index = 0; } mask = this.masks[item.mask]; - newpos = position - item.position; - if(newpos < 0) newpos = 0; + text = item.text.slice(0, index) + char + item.text.slice(index); - if(item.text.slice(newpos, newpos+1)) { - text = [item.text.slice(0, newpos), char, item.text.slice(newpos+1)].join(''); - }else{ - text = [item.text.slice(0, data.index), char, item.text.slice(data.index)].join(''); - } if(mask.match(text)) { item.text = text; position = this.moveToNextChar(position); - if (mask.width === newpos+1) { + if (mask.filled(text)) { position = this.getNextItemMask(position); } } else { //Нажатая кнопка не подходит под маску @@ -32016,7 +32551,9 @@ _.extend(DateTimeEditMask.prototype, { 's': new DateTimeMaskPart('s'), 'ss': new DateTimeMaskPart('ss'), 'MMM': new DateTimeMaskPart('MMM'), - 'MMMM': new DateTimeMaskPart('MMMM') + 'MMMM': new DateTimeMaskPart('MMMM'), + 'h': new DateTimeMaskPart('h'), + 'tt': new DateTimeMaskPart('tt') } }); @@ -33127,7 +33664,7 @@ _.extend(NumberEditMask.prototype, { var itemTemplate = this.getItemTemplate(); var item = itemTemplate.item; var text = item.text; - var val = item.value.toString(); + var val = (item.value === null || typeof item.value === 'undefined') ? '' : item.value.toString(); var endLength = len + position; if(!char)char = ""; @@ -33453,37 +33990,37 @@ function RegexEditMaskBuilder () { window.InfinniUI.RegexEditMaskBuilder = RegexEditMaskBuilder; //####app/linkView/openMode/strategy/_mixins/openModeAutoFocusMixin.js -var openModeAutoFocusMixin = { - - applyAutoFocus: function () { - var view = this.view; - var focusOnControl = view && view.getFocusOnControl(); - - if (!focusOnControl) { - return; - } - - var focusInterval = setInterval(function () { - var elements = view.findAllChildrenByName(focusOnControl); - if (Array.isArray(elements) && elements.length > 0) { - var element = elements[0]; - if (!jQuery.contains(document, element.control.controlView.el)) { - return; - } - - element.setFocus && element.setFocus(); - clearFocusInterval(); - } - }, 1000 / 3); - - setTimeout(clearFocusInterval, 3000); - - function clearFocusInterval() { - clearInterval(focusInterval); - } - - } - +var openModeAutoFocusMixin = { + + applyAutoFocus: function () { + var view = this.view; + var focusOnControl = view && view.getFocusOnControl(); + + if (!focusOnControl) { + return; + } + + var focusInterval = setInterval(function () { + var elements = view.findAllChildrenByName(focusOnControl); + if (Array.isArray(elements) && elements.length > 0) { + var element = elements[0]; + if (!jQuery.contains(document, element.control.controlView.el)) { + return; + } + + element.setFocus && element.setFocus(); + clearFocusInterval(); + } + }, 1000 / 3); + + setTimeout(clearFocusInterval, 3000); + + function clearFocusInterval() { + clearInterval(focusInterval); + } + + } + }; //####app/linkView/inlineViewBuilder.js function InlineViewBuilder() { @@ -33933,135 +34470,6 @@ _.extend(OpenModeDialogStrategy.prototype, { } }); -//####app/localizations/culture.js -function Culture(name){ - this.name = name; - this.caption = InfinniUI.localizations[name].caption; - this.dateTimeFormatInfo = InfinniUI.localizations[name].dateTimeFormatInfo; - this.numberFormatInfo = InfinniUI.localizations[name].numberFormatInfo; -} - -window.InfinniUI.global.culture = new Culture(InfinniUI.config.lang); -window.InfinniUI.Culture = Culture; - -//####app/localizations/dateTimeFormatInfo.js -InfinniUI.localizations['ru-RU'].dateTimeFormatInfo = { - monthNames: [ "Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь" ], - abbreviatedMonthNames: ["янв","фев","мар","апр","май","июн","июл","авг","сен","окт","ноя","дек"], - dayNames: [ "воскресенье","понедельник","вторник","среда","четверг","пятница","суббота" ], - abbreviatedDayNames: [ "Вс","Пн","Вт","Ср","Чт","Пт","Сб" ], - dateSeparator: '.', - timeSeparator: ':', - amDesignator: '', - pmDesignator: '', - firstDayOfWeek: 1 -}; - -InfinniUI.localizations['en-US'].dateTimeFormatInfo = { - monthNames: [ "January","February","March","April","May","June","July","August","September","October","November","December" ], - abbreviatedMonthNames: ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"], - dayNames: ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"], - abbreviatedDayNames: ["Sun", "Mon","Tue","Wed","Thu","Fri","Sat"], - dateSeparator: '/', - timeSeparator: ':', - amDesignator: 'AM', - pmDesignator: 'PM', - firstDayOfWeek: 0 -}; -//####app/localizations/localized.js -var localized = InfinniUI.localizations [InfinniUI.config.lang]; -//####app/localizations/numberFormatInfo.js -InfinniUI.localizations['ru-RU'].numberFormatInfo = { - numberDecimalDigits: 2, - numberDecimalSeparator: ',', - numberGroupSeparator: ' ', - numberNegativePattern: '-n', - numberPositivePattern: 'n', - - percentDecimalDigits: 2, - percentDecimalSeparator: ',', - percentGroupSeparator: ' ', - percentSymbol: '%', - percentNegativePattern: '-p%', - percentPositivePattern: 'p%', - - currencyDecimalDigits: 2, - currencyDecimalSeparator: ',', - currencyGroupSeparator: ' ', - currencySymbol: 'р.', - currencyNegativePattern: '-c$', - currencyPositivePattern: 'c$', - - negativeInfinitySymbol: '-бесконечность', - positiveInfinitySymbol: 'бесконечность', - NaNSymbol: 'NaN' -}; - -InfinniUI.localizations['en-US'].numberFormatInfo = { - numberDecimalDigits: 2, - numberDecimalSeparator: '.', - numberGroupSeparator: ',', - numberNegativePattern: '-n', - numberPositivePattern: 'n', - - percentDecimalDigits: 2, - percentDecimalSeparator: '.', - percentGroupSeparator: ',', - percentSymbol: '%', - percentNegativePattern: '-p %', - percentPositivePattern: 'p %', - - currencyDecimalDigits: 2, - currencyDecimalSeparator: '.', - currencyGroupSeparator: ',', - currencySymbol: '$', - currencyNegativePattern: '($c)', - currencyPositivePattern: '$c', - - negativeInfinitySymbol: '-Infinity', - positiveInfinitySymbol: 'Infinity', - NaNSymbol: 'NaN' -}; -//####app/localizations/patternDateFormats.js -InfinniUI.localizations['ru-RU'].patternDateFormats = { - f: 'dd MMMM yyyy г. HH:mm', - F: 'dd MMMM yyyy г. HH:mm:ss', - - g: 'dd.MM.yyyy HH:mm', - G: 'dd.MM.yyyy HH:mm:ss', - - d: 'dd.MM.yyyy', - D: 'dd MMMM yyyy г.', - - t: 'H:mm', - T: 'HH:mm:ss', - - y: 'MMMM yyyy', Y: 'MMMM yyyy', - m: 'MMMM yy', M: 'MMMM yy', - - s: 'yyyy-MM-ddTHH:mm:ss', - u: 'yyyy-MM-dd HH:mm:ssZ' -}; - -InfinniUI.localizations['en-US'].patternDateFormats = { - f: 'dddd, MMMM dd, yyyy h:%m tt', - F: 'dddd, MMMM dd, yyyy h:%m:%s tt', - - g: 'M/%d/yyyy h:%m tt', - G: 'M/%d/yyyy h:%m:%s tt', - - d: 'M/%d/yyyy', - D: 'dddd, MMMM dd, yyyy', - - t: 'h:%m tt', - T: 'h:%m:%s tt', - - y: 'MMMM, yyyy', Y: 'MMMM, yyyy', - m: 'MMMM yy', M: 'MMMM yy', - - s: 'yyyy-MM-ddTHH:mm:ss', - u: 'yyyy-MM-dd HH:mm:ssZ' -}; //####app/script/scriptBuilder.js /** * @@ -34160,8 +34568,8 @@ InfinniUI.ModalWindowService = (function () { if (modalQueue.length != 0) { var previous = modalQueue[modalQueue.length - 1]; - previous.modal.hide(); - previous.background.hide(); + previous.modal.addClass('invisible'); + previous.background.addClass('invisible'); } modalQueue.push(obj); @@ -34174,8 +34582,8 @@ InfinniUI.ModalWindowService = (function () { if (i == length - 1 && i != 0) { var previous = modalQueue[i - 1]; - previous.modal.show(); - previous.background.show(); + previous.modal.removeClass('invisible'); + previous.background.removeClass('invisible'); notifyLayoutChange(); } @@ -34193,18 +34601,20 @@ InfinniUI.ModalWindowService = (function () { } })(); -//####app/services/notificationSubsription.js -var notificationSubsription = (function() { +//####app/services/notificationSubscription.js +var notificationSubscription = (function() { var subscription = {}, hubProxy, + hubName, connection, onSuccessCb, onErrorCb, isConnected = false; - var setUpConnection = function(hubName, onSuccess, onError) { - onSuccessCb = onSuccess; - onErrorCb = onError; + var setUpConnection = function(newHubName, onSuccess, onError) { + onSuccessCb = onSuccess || onSuccessCb; + onErrorCb = onError || onErrorCb; + hubName = newHubName || hubName; connection = $.hubConnection(window.InfinniUI.config.serverUrl); hubProxy = connection.createHubProxy(hubName); @@ -34291,11 +34701,20 @@ var notificationSubsription = (function() { }; var stopConnection = function() { - isConnected = false; + if( hubProxy ) { + isConnected = false; + + eventSwitcher('off'); + hubProxy = null; + connection.stop(); + } + }; - eventSwitcher('off'); - hubProxy = null; - connection.stop(); + var reconnection = function() { + if( connection && hubProxy ) { + stopConnection(); + } + setUpConnection(); }; var checkHandlers = function() { @@ -34304,125 +34723,141 @@ var notificationSubsription = (function() { } }; + var on = function(eventName, callback) { + if( !connection ) { + console.error('Необходимо сначала установить соединение с сервером'); + } + if( connection[eventName] ) { + connection[eventName](callback); + } + }; + + var isDisconnected = function() { + return $.connection.isDisconnecting(connection); + }; + return { startConnection: setUpConnection, + reconnection: reconnection, subscribe: subscribe, unsubscribe: unsubscribe, - stopConnection: stopConnection + stopConnection: stopConnection, + on: on, + isDisconnected: isDisconnected }; })(); -InfinniUI.global.notificationSubsription = notificationSubsription; +InfinniUI.global.notificationSubscription = notificationSubscription; //####app/services/notifyService.js -/** - * @description Отображает всплывающие сообщения на событие onNotifyUser. - * Используется плдагин http://codeseven.github.io/toastr/ - */ -InfinniUI.NotifyService = (function () { - - var exchange = window.InfinniUI.global.messageBus; - - exchange.subscribe(messageTypes.onNotifyUser, function (context, args) { - var - messageText = args.value.messageText, - messageType = args.value.messageType || 'info'; - - var type; - - switch (messageType) { - case 'success': - case 'error': - case 'warning': - case 'info': - type = messageType; - break; - default: - type = 'info'; - } - - if (typeof toastr !== 'undefined') { - toastr[type](messageText); - } - - }); +/** + * @description Отображает всплывающие сообщения на событие onNotifyUser. + * Используется плдагин http://codeseven.github.io/toastr/ + */ +InfinniUI.NotifyService = (function () { + + var exchange = window.InfinniUI.global.messageBus; + + exchange.subscribe(messageTypes.onNotifyUser, function (context, args) { + var + messageText = args.value.messageText, + messageType = args.value.messageType || 'info'; + + var type; + + switch (messageType) { + case 'success': + case 'error': + case 'warning': + case 'info': + type = messageType; + break; + default: + type = 'info'; + } + + if (typeof toastr !== 'undefined') { + toastr[type](messageText); + } + + }); })(); //####app/services/ajaxLoaderIndicator/ajaxLoaderIndicator.js -var AjaxLoaderIndicator = function ($target, config) { - var defaults = { - delay: 50 - }; - - var options = _.defaults({}, config, defaults); - - var model = new AjaxLoaderIndicatorModel({}, options); - var ajaxLoaderIndicator = new AjaxLoaderIndicatorView({model: model}); - - - var $indicator = ajaxLoaderIndicator.render().$el; - $target.append($indicator); -}; - +var AjaxLoaderIndicator = function ($target, config) { + var defaults = { + delay: 50 + }; + + var options = _.defaults({}, config, defaults); + + var model = new AjaxLoaderIndicatorModel({}, options); + var ajaxLoaderIndicator = new AjaxLoaderIndicatorView({model: model}); + + + var $indicator = ajaxLoaderIndicator.render().$el; + $target.append($indicator); +}; + //####app/services/ajaxLoaderIndicator/ajaxLoaderIndicatorModel.js -var AjaxLoaderIndicatorModel = Backbone.Model.extend({ - - defaults: { - requests: 0, - progress: false - }, - - initialize: function (attributes, options) { - var exchange = window.InfinniUI.global.messageBus; - - exchange.subscribe(messageTypes.onDataLoaded, this.onDataLoaded.bind(this)); - exchange.subscribe(messageTypes.onDataLoading, this.onDataLoading.bind(this)); - - var onRequestsChanged = (options.delay > 0) ? _.debounce(this.onRequestsChanged.bind(this), 50) : - this.onRequestsChanged.bind(this); - - this.on('change:requests', onRequestsChanged); - }, - - onDataLoading: function () { - var requests = this.get('requests'); - this.set('requests', requests + 1); - }, - - onDataLoaded: function () { - var requests = this.get('requests'); - this.set('requests', requests - 1); - }, - - onRequestsChanged: function (model, value) { - this.set('progress', value > 0); - } - +var AjaxLoaderIndicatorModel = Backbone.Model.extend({ + + defaults: { + requests: 0, + progress: false + }, + + initialize: function (attributes, options) { + var exchange = window.InfinniUI.global.messageBus; + + exchange.subscribe(messageTypes.onDataLoaded, this.onDataLoaded.bind(this)); + exchange.subscribe(messageTypes.onDataLoading, this.onDataLoading.bind(this)); + + var onRequestsChanged = (options.delay > 0) ? _.debounce(this.onRequestsChanged.bind(this), 50) : + this.onRequestsChanged.bind(this); + + this.on('change:requests', onRequestsChanged); + }, + + onDataLoading: function () { + var requests = this.get('requests'); + this.set('requests', requests + 1); + }, + + onDataLoaded: function () { + var requests = this.get('requests'); + this.set('requests', requests - 1); + }, + + onRequestsChanged: function (model, value) { + this.set('progress', value > 0); + } + }); //####app/services/ajaxLoaderIndicator/ajaxLoaderIndicatorView.js -var AjaxLoaderIndicatorView = Backbone.View.extend({ - - className: 'pl-ajaxloader', - - template: InfinniUI.Template["services/ajaxLoaderIndicator/template/template.tpl.html"], - - hiddenClassName: 'hidden', - - initialize: function () { - this.listenTo(this.model, 'change:progress', this.updateProgress); - }, - - render: function () { - this.$el.html(this.template()); - this.updateProgress(); - return this; - }, - - updateProgress: function () { - var progress = this.model.get('progress'); - this.$el.toggleClass(this.hiddenClassName, !progress); - } - +var AjaxLoaderIndicatorView = Backbone.View.extend({ + + className: 'pl-ajaxloader', + + template: InfinniUI.Template["services/ajaxLoaderIndicator/template/template.tpl.html"], + + hiddenClassName: 'hidden', + + initialize: function () { + this.listenTo(this.model, 'change:progress', this.updateProgress); + }, + + render: function () { + this.$el.html(this.template()); + this.updateProgress(); + return this; + }, + + updateProgress: function () { + var progress = this.model.get('progress'); + this.$el.toggleClass(this.hiddenClassName, !progress); + } + }); //####app/services/contextMenuService/contextMenuService.js InfinniUI.ContextMenuService = (function () { @@ -34618,7 +35053,7 @@ var routerService = (function(myRoutes) { } } routerObj.routes[myRoutes[i].Path.slice(1)] = myRoutes[i].Name; // remove first slash from myRoutes[i].Path for backbone - routerObj[myRoutes[i].Name] = myFunc(myRoutes[i].Name, myRoutes[i].Action); + routerObj[myRoutes[i].Name] = onRouteSelectHandler(myRoutes[i].Name, myRoutes[i].Action); } return routerObj; }; @@ -34636,54 +35071,111 @@ var routerService = (function(myRoutes) { } }; - var myFunc = function(name, callback) { + var onRouteSelectHandler = function(name, script) { return function() { - var params = Array.prototype.slice.call(arguments); - new ScriptExecutor({getContext: function() {return 'No context';}}).executeScript(callback, { name: name, params: params }); + var params = _.extend(Array.prototype.slice.call(arguments), + { + routeParams: routerService._params + }); + + new ScriptExecutor({getContext: function() {return routerService._context || "No context";}}).executeScript(script, { name: name, params: params }); }; }; var routerObj = parseRouteForBackbone(myRoutes); var startRouter = function() { - var Router = Backbone.Router.extend(routerObj); - InfinniUI.AppRouter = new Router(); + if( !InfinniUI.AppRouter ) { + var Router = Backbone.Router.extend(routerObj); + InfinniUI.AppRouter = new Router(); - Backbone.history = Backbone.history || new Backbone.History({}); - Backbone.history.start(InfinniUI.config.HistoryAPI); + Backbone.history = Backbone.history || new Backbone.History({}); + Backbone.history.start(InfinniUI.config.HistoryAPI); + } else { + console.log("Попытка повторно запустить routerService"); + } }; - return { - getLinkByName: getLinkByName, - startRouter: startRouter + var setContext = function(context) { + this._context = context; }; -})(InfinniUI.config.Routes); -window.InfinniUI.RouterService = routerService; + var setParams = function(params) { + this._params = params; + }; -//####app/services/toolTipService/toolTipService.js -InfinniUI.ToolTipService = (function () { + var addParams = function(params) { + this._params = _.extend( this._params||{} ,params); + }; - var exchange = window.InfinniUI.global.messageBus; + var routerService = { + getLinkByName: getLinkByName, + startRouter: startRouter, + setContext: setContext, + setParams: setParams, + addParams: addParams + }; - exchange.subscribe(messageTypes.onToolTip.name, function (context, args) { - var message = args.value; - showToolTip(getSourceElement(message.source), message.content); - }); + return routerService; +})(InfinniUI.config.Routes); - function getSourceElement(source) { - return source.control.controlView.$el - } - function showToolTip($element, content) { - $element - .tooltip({ - html: true, - title:content, - placement: 'auto top', - container: 'body' +window.InfinniUI.RouterService = routerService; - }) - .tooltip('show'); - } -})(); +//####app/services/toolTipService/toolTipService.js +InfinniUI.ToolTipService = (function() { + + var TOOLTIP_PLACEMENT = 'auto top'; + var TOOLTIP_CONTAINER = 'body'; + var TOOLTIP_TRIGGER = 'hover'; + + var exchange = window.InfinniUI.global.messageBus; + + exchange.subscribe( messageTypes.onToolTipInit.name, initToolTip ); + + exchange.subscribe( messageTypes.onToolTipDestroy.name, destroyToolTip ); + + function destroyToolTip( context, args ) { + var element = extractElementFromArgs( args ); + var $element = element.control.controlView.$el; + + $element.tooltip( 'destroy' ); + } + + function initToolTip( context, args ) { + var element = extractElementFromArgs( args ); + var content = extractContentFromArgs( args ); + var $element = element.control.controlView.$el; + + var options = { + html: true, + title: function() { + return content.render(); + }, + placement: TOOLTIP_PLACEMENT, + container: TOOLTIP_CONTAINER, + trigger: TOOLTIP_TRIGGER + }; + + $element.tooltip( options ); + } + + /** + * + * @param {Object} args + * @returns InfinniUI.Element + */ + function extractContentFromArgs( args ) { + return args.value.content; + } + + /** + * + * @param {Object} args + * @returns InfinniUI.Element + */ + function extractElementFromArgs( args ) { + return args.value.element; + } + +})(); })(); \ No newline at end of file diff --git a/out/platform.min.js b/out/platform.min.js index 4c3d98c..a783951 100644 --- a/out/platform.min.js +++ b/out/platform.min.js @@ -1,15 +1,15 @@ -;(function(){"use strict";function Collection(e,t,n){function i(e,t){return et?1:0}Array.isArray(e)||(e=[]),this._items=e.map(function(e,t){return this.createCollectionItem(e,t)},this),this._idProperty=t,this._comparator=n||i,this.events=new CollectionEventManager}function CollectionEventManager(){}function BasePathOfProperty(e,t,n){this.isRelativeProperty(e)?this.basePathOfProperty=n.basePathOfProperty+this.excludeFirstChar(e):this.basePathOfProperty=e,n?(this.indexesInParentLists=n.indexesInParentLists?n.indexesInParentLists.slice():[],this.indexesInParentLists.push(t),this.parentBasePath=n):void 0!==t&&null!==t&&(this.indexesInParentLists=[t],this.basePathOfProperty+=t)}function EventsManager(){this.handlers={}}function HashMap(){this._keys=[],this._values=[]}function hiddenScreen(){this.middleElement=$("
").css({position:"absolute",top:"-10000px"})}function Logger(e){this.messages=[],this.setLevel(e||LOG_LEVEL.debug),this.showMessages=!0}function guid(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random()|0,n="x"==e?t:3&t|8;return n.toString(16)})}function MessageBus(e){function t(e){return"object"==typeof e&&"undefined"!=typeof e.name&&(e=e.name),e}var n={};this.send=function(i,o){if(i=t(i),n[i]){var r;e&&e.getContext&&(r=e.getContext()),_.each(n[i],function(e){e(r,{value:o})})}},this.subscribe=function(e,i){e=t(e),n[e]||(n[e]=[]),n[e].push(i)},this.unsubscribeByType=function(e){e=t(e),n[e]&&delete n[e]},this.getView=function(){return e}}function ContainerControl(e){_.superClass(ContainerControl,this,e)}function ListEditorBaseControl(e){_.superClass(ListEditorBaseControl,this,e),this.initialize_editorBaseControl()}function TextEditorBaseControl(e){_.superClass(TextEditorBaseControl,this,e),this.initialize_editorBaseControl()}function EventManager(){this.handlers={}}function TextEditorModelBaseModeStrategy(){}function TextEditorModelDisplayModeStrategy(){TextEditorModelBaseModeStrategy.call(this)}function TextEditorModelEditModeStrategy(){TextEditorModelBaseModeStrategy.call(this)}function TextBoxControl(e){_.superClass(TextBoxControl,this,e)}function DateTimePickerControl(e){_.superClass(DateTimePickerControl,this,e)}function DatePickerControl(e){_.superClass(DatePickerControl,this,e)}function TimePickerControl(e){_.superClass(TimePickerControl,this,e)}function getUserInfo(e){var t=new AuthenticationProvider(InfinniUI.config.serverUrl);t.getCurrentUser(function(t){e.model.set("result",t)},function(e){showObject("#signInInternalResult",e)})}function refreshUserInfo(){var e=new AuthenticationProvider(InfinniUI.config.serverUrl);e.getCurrentUser(function(e){InfinniUI.user.onReadyDeferred.resolve(e)},function(e){InfinniUI.user.onReadyDeferred.resolve(null)})}function changePassword(){var e=new AuthenticationProvider(InfinniUI.config.serverUrl);e.changePassword($("#oldPassword").val(),$("#newPassword").val(),function(e){refreshUserInfo()},function(e){showObject("#changePasswordResult",e)})}function changeProfile(){var e=new AuthenticationProvider(InfinniUI.config.serverUrl);e.changeProfile($("#displayName").val(),$("#description").val(),function(e){refreshUserInfo()},function(e){showObject("#changeProfileResult",e)})}function changeActiveRole(){var e=new AuthenticationProvider(InfinniUI.config.serverUrl);e.changeActiveRole($("#activeRole").val(),function(e){refreshUserInfo()},function(e){showObject("#сhangeActiveRoleResult",e)})}function getLinkExternalLoginForm(){var e=new AuthenticationProvider(InfinniUI.config.serverUrl);e.getLinkExternalLoginForm(getAbsoluteUri("/Home/SignInSuccess"),getAbsoluteUri("/Home/SignInFailure"),function(e){$("#linkExternalLoginForm").append(e)},function(e){showObject("#linkExternalLoginResult",e)})}function unlinkExternalLogin(e,t){var n=new AuthenticationProvider(InfinniUI.config.serverUrl);n.unlinkExternalLogin(e,t,function(e){refreshUserInfo()},function(e){showObject("#unlinkExternalLoginResult",e)})}function signOut(e){var t=new AuthenticationProvider(InfinniUI.config.serverUrl);onSuccessSignOut(getHomePageContext()),t.signOut(function(t){window.getCurrentUserName=function(){return null},e.model.set("result",null),location.reload()},function(e){showObject("#getCurrentUserResult",e.responseJSON)})}function setUserInfo(e){if(null!==e.Logins&&void 0!==e.Logins)for(var t=$("#externalLogins"),n=0;n-1&&toastr.error("Неверный логин или пароль","Ошибка!"),showObject("#signInInternalResult",e)})}function getSignInExternalForm(){var e=new AuthenticationProvider(InfinniUI.config.serverUrl);e.getSignInExternalForm(getAbsoluteUri("/Home/SignInSuccess"),getAbsoluteUri("/Home/SignInFailure"),function(e){$("#signInExternalForm").append(e)},function(e){showObject("#signInExternalResult",e)})}function getAbsoluteUri(e){return location.protocol+"//"+location.host+e}function showObject(e,t){var n=formatObject(t);$(e).text(n)}function formatObject(e){return JSON.stringify(e,null,4)}function AuthenticationProvider(e){this.baseAddress=e}function ButtonControl(e){_.superClass(ButtonControl,this,e)}function ButtonEditControl(e){_.superClass(ButtonEditControl,this,e)}function ComboBoxBaseViewStrategy(e){this.dropdownView=e}function ComboBoxGroupViewStrategy(e){ComboBoxBaseViewStrategy.call(this,e)}function ComboBoxPlainViewStrategy(e){ComboBoxBaseViewStrategy.call(this,e)}function DataGridControl(){_.superClass(DataGridControl,this)}function DataGridRowControl(){_.superClass(DataGridRowControl,this)}function DataNavigationButtonFactory(e){this._dataNavigation=e}function DataNavigationControl(e){_.superClass(DataNavigationControl,this,e)}function ListBoxViewGroupStrategy(e){this.listbox=e}function ListBoxViewPlainStrategy(e){this.listbox=e}function ListBoxControl(e){_.superClass(ListBoxControl,this,e)}function PopupButtonControl(e){_.superClass(PopupButtonControl,this,e)}function StackPanelControl(e){_.superClass(StackPanelControl,this,e)}function StackPanelViewGroupStrategy(e){this.stackPanel=e}function StackPanelViewPlainStrategy(e){this.stackPanel=e}function TablePanelControl(e){_.superClass(TablePanelControl,this,e)}function CellControl(e){_.superClass(CellControl,this,e)}function RowControl(e){_.superClass(RowControl,this,e)}function TabPanelControl(e){_.superClass(TabPanelControl,this,e)}function TabPageControl(e){_.superClass(TabPageControl,this,e)}function TreeViewControl(){_.superClass(TreeViewControl,this)}function CheckBoxControl(e){_.superClass(CheckBoxControl,this,e),this.initialize_editorBaseControl()}function ComboBoxControl(e){_.superClass(ListBoxControl,this,e)}function ContextMenuControl(){_.superClass(ContextMenuControl,this)}function DividerControl(e){_.superClass(DividerControl,this,e)}function FileBoxControl(e){_.superClass(FileBoxControl,this,e),this.initialize_editorBaseControl()}function FormControl(e){_.superClass(FormControl,this,e)}function GridPanelControl(e){_.superClass(GridPanelControl,this,e)}function IconControl(){_.superClass(IconControl,this)}function ImageBoxControl(e){_.superClass(ImageBoxControl,this,e),this.initialize_editorBaseControl()}function IndeterminateCheckBoxControl(e){_.superClass(IndeterminateCheckBoxControl,this,e),this.initialize_editorBaseControl()}function LinkElementControl(){_.superClass(LinkElementControl,this)}function MenuBarControl(e){_.superClass(MenuBarControl,this,e)}function NumericBoxControl(e){_.superClass(NumericBoxControl,this,e)}function PanelControl(e){_.superClass(PanelControl,this,e)}function ScrollPanelControl(e){_.superClass(ScrollPanelControl,this,e)}function ToggleButtonControl(e){_.superClass(ToggleButtonControl,this,e),this.initialize_editorBaseControl()}function ToolBarControl(e){_.superClass(ToolBarControl,this,e)}function ViewControl(e){_.superClass(ViewControl,this,e)}function Container(e,t){_.superClass(Container,this,e,t)}function ContainerBuilder(){_.superClass(ContainerBuilder,this)}function ListEditorBase(e,t){_.superClass(ListEditorBase,this,e,t),this.initialize_editorBase()}function ListEditorBaseBuilder(){_.superClass(ListEditorBaseBuilder,this),this.initialize_editorBaseBuilder()}function TextEditorBase(e){_.superClass(TextEditorBase,this,e),this.initialize_editorBase()}function TextEditorBaseBuilder(){_.superClass(TextEditorBaseBuilder,this),this.initialize_editorBaseBuilder()}function ListBox(e,t){_.superClass(ListBox,this,e,t)}function ListBoxBuilder(){_.superClass(ListBoxBuilder,this)}function TextBox(e){_.superClass(TextBox,this,e)}function TextBoxBuilder(){_.superClass(TextBoxBuilder,this)}function DateTimePicker(e){_.superClass(DateTimePicker,this,e)}function DateTimePickerBuilder(){_.superClass(DateTimePickerBuilder,this)}function DatePicker(e){_.superClass(DatePicker,this,e),this.setMode("DatePicker"),this.setTimeZone()}function DatePickerBuilder(){_.superClass(DatePickerBuilder,this)}function TimePicker(e){_.superClass(TimePicker,this,e),this.setMode("TimePicker"),this.setTimeZone()}function TimePickerBuilder(){_.superClass(TimePickerBuilder,this)}function StackPanel(e,t){_.superClass(StackPanel,this,e,t)}function StackPanelBuilder(){_.superClass(StackPanelBuilder,this)}function Button(e,t){_.superClass(Button,this,e,t),this.buttonInit()}function ButtonBuilder(){_.superClass(ButtonBuilder,this)}function ButtonEdit(e){_.superClass(ButtonEdit,this,e)}function ButtonEditBuilder(){_.superClass(ButtonEditBuilder,this)}function CheckBox(e){_.superClass(CheckBox,this,e),this.initialize_editorBase()}function CheckBoxBuilder(){_.superClass(CheckBoxBuilder,this),this.initialize_editorBaseBuilder()}function ComboBox(e){_.superClass(ComboBox,this,e)}function ComboBoxBuilder(){_.superClass(ComboBoxBuilder,this)}function ContextMenu(e){_.superClass(ContextMenu,this,e)}function ContextMenuBuilder(){_.superClass(ContextMenuBuilder,this)}function DataGrid(e){_.superClass(DataGrid,this,e)}function DataGridBuilder(){_.superClass(DataGridBuilder,this),this.columnBuilder=new DataGridColumnBuilder}function DataGridColumn(){this._values=Object.create(null)}function DataGridColumnBuilder(){}function DataNavigation(e){_.superClass(DataNavigation,this,e)}function DataNavigationBuilder(){_.superClass(DataNavigationBuilder,this)}function Divider(e){_.superClass(Divider,this,e)}function DividerBuilder(){_.superClass(DividerBuilder,this)}function ExtensionPanel(e){_.superClass(ExtensionPanel,this,e)}function ExtensionPanelBuilder(){}function FileBox(e){_.superClass(FileBox,this,e),this.initialize_editorBase()}function FileBoxBuilder(){_.superClass(FileBoxBuilder,this),this.initialize_editorBaseBuilder()}function FileBoxValueConverter(e){this._element=e}function Form(e){_.superClass(Form,this,e)}function FormBuilder(){_.superClass(FormBuilder,this)}function Frame(){_.superClass(Frame,this),this.initialize_editorBase()}function FrameBuilder(){_.superClass(TextEditorBaseBuilder,this),this.initialize_editorBaseBuilder()}function GridPanel(e){_.superClass(GridPanel,this,e)}function GridPanelBuilder(){_.superClass(GridPanelBuilder,this)}function Icon(e){_.superClass(Icon,this,e)}function IconBuilder(){_.superClass(ButtonBuilder,this)}function ImageBox(e){_.superClass(ImageBox,this,e),this.initialize_editorBase()}function ImageBoxBuilder(){_.superClass(ImageBoxBuilder,this),this.initialize_editorBaseBuilder()}function ImageBoxValueConverter(e){this._element=e}function IndeterminateCheckBox(e){_.superClass(IndeterminateCheckBox,this,e),this.initialize_editorBase()}function IndeterminateCheckBoxBuilder(){_.superClass(IndeterminateCheckBoxBuilder,this),this.initialize_editorBaseBuilder()}function Label(e,t){_.superClass(Label,this,e,t),this.initialize_editorBase()}function LabelBuilder(){_.superClass(TextEditorBaseBuilder,this),this.initialize_editorBaseBuilder()}function Link(e){_.superClass(Link,this,e)}function LinkBuilder(){_.superClass(LinkBuilder,this)}function MenuBar(e){_.superClass(MenuBar,this,e)}function MenuBarBuilder(){_.superClass(MenuBarBuilder,this)}function NumericBox(e){_.superClass(NumericBox,this,e)}function NumericBoxBuilder(){_.superClass(NumericBoxBuilder,this)}function Panel(e){_.superClass(Panel,this,e)}function PanelBuilder(){_.superClass(PanelBuilder,this)}function PasswordBox(e){_.superClass(PasswordBox,this,e),this.initialize_editorBase()}function PasswordBoxBuilder(){_.superClass(PasswordBoxBuilder,this),this.initialize_editorBaseBuilder()}function PopupButton(e,t){_.superClass(PopupButton,this,e,t),this.buttonInit()}function PopupButtonBuilder(){_.superClass(PopupButtonBuilder,this)}function RadioGroupBuilder(){_.superClass(RadioGroupBuilder,this)}function ScrollPanel(e){_.superClass(ScrollPanel,this,e)}function ScrollPanelBuilder(){_.superClass(ScrollPanelBuilder,this)}function TabPanel(e){_.superClass(TabPanel,this,e)}function TabPanelBuilder(){_.superClass(TabPanelBuilder,this)}function TablePanel(e){_.superClass(TablePanel,this,e)}function TablePanelBuilder(){_.superClass(TablePanelBuilder,this)}function ToggleButton(e){_.superClass(ToggleButton,this,e),this.initialize_editorBase()}function ToggleButtonBuilder(){_.superClass(ToggleButtonBuilder,this),this.initialize_editorBaseBuilder()}function ToolBarBuilder(){_.superClass(ToolBarBuilder,this)}function TreeView(e){_.superClass(TreeView,this,e)}function TreeViewBuilder(){_.superClass(TreeViewBuilder,this)}function View(e){_.superClass(View,this,e);var t=this;this.eventManager=new EventManager,this.openStrategy=new OpenModeDefaultStrategy,this.openStrategy.setView(this),this.members={},this.membersDeferreds={},this.handlers={onBeforeLoaded:$.Deferred(),onLoaded:$.Deferred(),onSelectedElementChange:null},this._initContext();var n=this.getView();n&&(n.onClosing&&n.onClosing(function(e,n){if(!t.isRemoved)return t.eventManager.trigger("onClosing",t.getContext(),t._getScriptArgs())}),n.onClosed&&n.onClosed(function(e,n){t.close(null,null,!0)})),this.control.get("dataSources").onChange(function(){t._initDataSourceHandlers()})}function ViewBuilder(){_.superClass(ViewBuilder,this)}function ViewPanel(e){_.superClass(ViewPanel,this,e)}function ViewPanelBuilder(){}function DataGridRow(){_.superClass(DataGridRow,this),this._transformRowProperties({rowBackground:"background",rowForeground:"foreground",rowTextStyle:"textStyle",rowStyle:"style"})}function TabPage(e){_.superClass(TabPage,this,e),this.events=new EventsManager;var t=this;this.control.on("close",function(){t.close()})}function TabPageBuilder(){_.superClass(TabPageBuilder,this)}function Cell(e){_.superClass(Cell,this,e)}function CellBuilder(){_.superClass(CellBuilder,this)}function Row(e){_.superClass(Row,this,e)}function RowBuilder(){_.superClass(RowBuilder,this)}function BaseAction(e){this.parentView=e,this._properties=Object.create(null),_.defaults(this._properties,this.defaults),this.initDefaultValues()}function BaseEditAction(e){_.superClass(BaseEditAction,this,e)}function AcceptAction(e){_.superClass(AcceptAction,this,e)}function AcceptActionBuilder(){}function AddAction(e){_.superClass(AddAction,this,e)}function AddActionBuilder(){}function CancelAction(e){_.superClass(CancelAction,this,e)}function CancelActionBuilder(){}function DeleteAction(e){_.superClass(DeleteAction,this,e)}function DeleteActionBuilder(){}function EditAction(e){_.superClass(EditAction,this,e)}function EditActionBuilder(){}function OpenAction(e){_.superClass(OpenAction,this,e)}function OpenActionBuilder(){}function RouteToAction(){_.superClass(RouteToAction,this),this.href=""}function RouteToActionBuilder(){}function SaveAction(e){_.superClass(SaveAction,this,e)}function SaveActionBuilder(){}function SelectAction(e){_.superClass(SelectAction,this,e)}function SelectActionBuilder(){}function DownloadExecutor(e,t,n){this.guid=guid(),this.options={timeout:6e4,poll:100},this.resultCallback=e,this.successCallback=t,this.failCallback=n}function ServerAction(e){_.superClass(ServerAction,this,e),this.provider=window.InfinniUI.providerRegister.build("ServerActionProvider"),this.updateContentTypeStrategy(),this.on("change:contentType",this.updateContentTypeStrategy)}function ServerActionBuilder(){}function UpdateAction(e){_.superClass(UpdateAction,this,e)}function UpdateActionBuilder(){}function ApplicationBuilder(){this.builder||(this.builder=new Builder,this.registerElementBuilders()),window.InfinniUI.global.factory=this}function Builder(){var e=[];this.appView=null,this.register=function(t,n){e[t]=n},this.buildType=function(t,n,i){if(i=i||{},void 0===e[t])return null;var o=_.extend({builder:this,metadata:n},i),r=i.parentView?i.parentView.getContext():{};return e[t].build(r,o)},this.build=function(e,t){var n,i,o=null;t=t||{};for(var r in e){n=r;break}return"undefined"==typeof n||null===n?console.error("Builder: Не переданы метаданные"):(i=e[n],o=this.buildType(n,i,t)),o},this.buildMany=function(e,t){var n=[];if(e)for(var i=0;i0;return e.forEach(function(e){var n=this.createCollectionItem(e,t.length);t.push(n)},this),n&&this.events.onAdd(e),n},Collection.prototype.insert=function(e,t){var n=this.createCollectionItem(t,e);return this._items.splice(e,0,n),this.events.onAdd([t],e),!0},Collection.prototype.insertAll=function(e,t){if(!Array.isArray(t))return!1;var n=this._items,i=t.length>0;return t.forEach(function(t,i){var o=e+i,r=this.createCollectionItem(t,o);n.splice(o,0,r)},this),i&&this.events.onAdd(t,e),i},Collection.prototype.reset=function(e){var t,n;return!!Array.isArray(e)&&(t=this._items.length!==e.length,n=e.map(function(e,n){return t||(t=!this.isEqual(e,this.getCollectionItemValue(n))),this.createCollectionItem(e,n)},this),this._items.length=0,Array.prototype.push.apply(this._items,n),t&&this.events.onReset(),t)},Collection.prototype.set=function(e,t){var n=this._items;if(!Array.isArray(e))return!1;var i=n.length!==e.length,o=e.slice();return o.forEach(function(e,t){t=this._items.length)return!1;var t=this.getCollectionItemValue(e);return this._items.splice(e,1),this.events.onRemove([t],e),!0},Collection.prototype.removeAll=function(e){if(!Array.isArray(e))return!1;var t,n=this._items,i=[];if(e.forEach(function(e){i=n.filter(function(t){return this.isEqual(e,this.getItemValue(t))},this),i.forEach(function(e){var t=n.indexOf(e);n.splice(t,1)})},this),t=i.length>0){var o=i.map(function(e){return this.getItemValue(e)},this);this.events.onRemove(o)}return t},Collection.prototype.removeRange=function(e,t){var n,i=this._items;if(e>=i.length)return!1;"undefined"==typeof t&&(t=i.length-e);var o=i.splice(e,t);if(n=o.length>0){var r=o.map(function(e){return this.getItemValue(e)},this);this.events.onRemove(r,e)}return n},Collection.prototype.removeEvery=function(e,t){if("function"!=typeof e)return!1;var n,i=this._items,o=i.filter(function(n,i){var o=this.getItemValue(n);return e.call(t,o,i,this)},this);if(o.forEach(function(e){var t=i.indexOf(e);i.splice(t,1)}),n=o.length>0){var r=o.map(function(e){return this.getItemValue(e)},this);this.events.onRemove(r)}return n},Collection.prototype.clear=function(){var e=this._items,t=e.length>0,n=e.map(function(e){return this.getItemValue(e)},this);return e.length=0,t&&this.events.onRemove(n,0),t},Collection.prototype.getById=function(e){if(!this.hasIdProperty)return!1;for(var t,n,i=this._items,o=0;o=n.length)return-1;for(var o=t;o>0;o-=1){var r=this.getItemValue(n[o]);if(this.isEqual(e,r)){i=o;break}}return i},Collection.prototype.findIndex=function(e,t){if("function"!=typeof e)return!1;var n=this._items,i=-1,o=n.some(function(n,o){var r=this.getItemValue(n);return i=o,e.call(t,r,o,this)},this);return o?i:-1},Collection.prototype.contains=function(e,t){t=t||0;for(var n=!1,i=this._items,o=t;o=i.length||e===t)return!1;n=i.splice(e,1).pop(),e>t?i.splice(t,0,n):i.splice(t-1,0,n);var o=i[e]!==n;if(o){var r=this.getItemValue(n);this.events.onMove([r],[r],e,t)}return o},Collection.prototype.sort=function(e){"function"!=typeof e&&(e=this._comparator);var t=this._items,n=this,i=t.slice(),o=!1;t.sort(function(t,i){return e(n.getItemValue(t),n.getItemValue(i))});for(var r=0;r0?"-":"+",c=[p(Math.floor(u/60),2),p(u%60,2)].join(":");return o+"T"+r+"."+l+d+c}function u(e){var t,n=null;return e&&e.constructor===String?t=new Date(e):e&&e.constructor===Date&&(t=e),t&&(t.setUTCHours(0,0,0,0),n=t.getTime()/1e3),n}function d(e){var t,n,i=null;return e&&e.constructor===String?t=new Date(e):e&&e.constructor===Date&&(t=e),t&&(n=new Date(0),n.setUTCHours(t.getUTCHours(),t.getUTCMinutes(),t.getUTCSeconds(),t.getUTCMilliseconds()),i=n.getTime()/1e3),i}function c(e){var t;return t=typeof e===Date?new Date(e.getTime()):"number"==typeof e?new Date(1e3*e):"undefined"==typeof e||null===e?null:r(e)}function h(){return f}function p(e,t){var n=""+e,i="";return n.length0&&setTimeout(function(){i.whenReady(e,t,n-1)},510)}};window.InfinniUI.ObjectUtils=function(){function e(e,t){if(null!==e&&void 0!==e&&null!==t&&void 0!==t){for(var n=e,r=t.length,l=0;l=0?o(n,u):a(n,s)}return n}return e}function t(e,t,n){for(var s=e,u=t.length-1,d=t[0],c=i(d),h=0;h=0?o(s,c):a(s,d),m=t[h+1],f=i(m);f>=0?($.isArray(p)||(p=[]),r(s,c,p)):($.isPlainObject(p)||(p={}),l(s,d,p)),s=p,d=m,c=f}c>=0?r(s,c,n):l(s,d,n)}function n(e){return _.isEmpty(e)?null:e.split(".")}function i(e){var t=-1;if("$"===e)t=0;else{var n=parseInt(e);isNaN(n)||(t=n)}return t}function o(e,t){return null!==e&&void 0!==e&&"[object Array]"===Object.prototype.toString.call(e)&&t>=0&&t=0&&t1&&(","===t[0].slice(-1)||")"===t[0].slice(-1))&&(t[0]=t[0].slice(0,-1)),t[0].length>1&&"'"===t[0].slice(0,1)&&(t[0]=t[0].slice(1,-1)),t[0].search(/tmpRE/)!==-1&&(t[0]=t[0].slice(1,-1).split(","),t[0][0]=r),m.push(t);for(;t=d.exec(e);)m.push(t);return m.sort(function(e,t){return e.index-t.index}),m},n=function(e){for(var t,n,i,o,r=[],a=[],l=[],s=0,u=0,d=e.length;ue[o].range[0]&&t[n].indexe[n].range[0]&&e[t].range[1]e[t].range[0]){e[n].children.unshift(e[t]),e.splice(t,1),t-=1;break}e[n].children.push(e[t]),e.splice(t,1),t-=1;break}return e[0]};return e.buildUpFilterTree=function(e){var r;return r=t(e),r=n(r),r=i(r[0],r[1]),o(r)},e}(),filterItems.filterMethods=function(){var e={};return e.eq=function(e,t,n){for(var i,o,r=[],a=InfinniUI.ObjectUtils,l=0,s=t.length;le[1]&&i.push(t[l]);o===i.length&&r.push(t[l])}else a.getPropertyValue(t[l],e[0])>e[1]&&r.push(t[l]);return r},e.gte=function(e,t,n){for(var i,o,r=[],a=InfinniUI.ObjectUtils,l=0,s=t.length;l=e[1]&&i.push(t[l]);o===i.length&&r.push(t[l])}else a.getPropertyValue(t[l],e[0])>=e[1]&&r.push(t[l]);return r},e.lt=function(e,t,n){for(var i,o,r=[],a=InfinniUI.ObjectUtils,l=0,s=t.length;le[1]){o.push(t[a]);break}}return o},e.anyGte=function(e,t,n){for(var i,o=[],r=InfinniUI.ObjectUtils,a=0,l=t.length;a=e[1]){o.push(t[a]);break}}return o},e.anyLt=function(e,t,n){for(var i,o=[],r=InfinniUI.ObjectUtils,a=0,l=t.length;ae[1]&&o.push(t[a]);return o},e.sizeGte=function(e,t,n){for(var i,o=[],r=InfinniUI.ObjectUtils,a=0,l=t.length;a=e[1]&&o.push(t[a]);return o},e.sizeLt=function(e,t,n){for(var i,o=[],r=InfinniUI.ObjectUtils,a=0,l=t.length;a=this.KeyCode.NUMPAD_0&&e<=this.KeyCode.NUMPAD_9)n=e-48;else switch(e){case 110:n=this.KeyCode.DELETE;break;case 107:n=this.KeyCode.PLUS;break;case 109:n=this.KeyCode.MINUS;break;case 106:n=this.KeyCode.ASTERISK;break;case 111:n=this.KeyCode.SLASH;break;case 188:n=44;break;case 173:n=45;break;case 190:n=46;break;case 191:n=47;break;case 192:n=96;break;case 219:n=91;break;case 220:n=92;break;case 221:n=93;break;case 222:n=39;break;default:n=e}t=String.fromCharCode(n)}return t}};var layoutManager={windowHeight:0,clientHeight:0,exchange:null,times:[],setOuterHeight:function(e,t,n){var i=0;"border-top-width,border-bottom-width,padding-top,padding-bottom,margin-top,margin-bottom".split(",").forEach(function(t){i+=parseInt(e.css(t))});var o=t-i;return n&&(o+=n),e.height(o),o},getModalSelector:function(){return".modal-scrollable"},getSelector:function(){return".verticalAlignmentStretch:not(:hidden)"},buildTree:function(e,t,n,i,o){var e=_.where(o,{parent:t}),r=this;return{isElement:_.indexOf(i,t)!==-1,element:t,$element:n,child:_.map(e,function(t){return r.buildTree(e,t.element,t.$element,i,o)})}},formTree:function(e,t,n){for(var i,o,r,a=[],l=0,s=e.length;l0&&this.goThroughTree(e,n))},goThroughTree:function(e,t){var n=this;e.$element.parentsUntil(".modal").length&&e.$element.attr("data-height-original",e.element.style.height);var i=e.$element.children(":not(:hidden):not(.modal-scrollable):not(.modal-backdrop):not(.pl-dropdown-container)"),o=_.chain(i).filter(function(e){var t=$(e).css("position");return["absolute","fixed"].indexOf(t)===-1}).groupBy("offsetTop").value(),r=[];_.each(o,function(t,n){var i=[];_.each(t,function(t){var n=_.find(e.child,function(e){return e.element===t});n&&i.push(n)}),r.push(i.length?0:_.reduce(t,function(e,t){return Math.max(e,$(t).outerHeight(!0))},0)),o[n]=i},this);var a=_.reduce(r,function(e,t){return e+t},0),l=_.reduce(o,function(e,t){return t.length?e+1:e},0),s=Math.floor((t-a)/l);_.each(o,function(e){0!==e.length&&_.each(e,function(e){n.defineWay(e,s)},this)},this)},resize:function(e,t){var n=Date.now(),i=$(e),o=(this.setOuterHeight(i,t),i.find(this.getSelector()));if(0!==o.length){var r=this.formTree(o,e,i);this.defineWay(r,t);var a=Date.now();this.timeWatcher(a-n)}},timeWatcher:function(e){e>=20&&this.times.push(e)},getTimes:function(){return this.times},resizeView:function(e,t){var n=$("#page-content",e),i=this.setOuterHeight(n,t);this.resize(n.get(0),i)},resizeDialog:function(){var e=this;$(this.getModalSelector()).each(function(t,n){e._resizeDialog($(n)),e.resetDialogHeight($(n))})},resetDialogHeight:function(e){if(e.children()){var t=e.children(),n=$(".modal-header",t),i=$(".modal-body",t),o=$(this.getSelector(),e);o.parentsUntil(".modal").css("height","auto"),t.css("top",(this.windowHeight-n.outerHeight(!0)-i.outerHeight(!0))/2),e.children(".modal:not(.messagebox)").height(i.outerHeight(!0)+n.outerHeight(!0))}},_resizeDialog:function(e){var t=10,n=e.children();n.css("margin-top",0);var i=$(".modal-header",n),o=$(".modal-body",n),r=i.outerHeight(!0);o.css("max-height",this.windowHeight-r),n.css("margin-top",0);var a=$(this.getSelector(),e);if(0!==a.length){var l=this.setOuterHeight(e,this.windowHeight-2*t),s=this.setOuterHeight(n,l)-i.outerHeight();this.resize(o[0],s)}},init:function(e){return window.InfinniUI.config.disableLayoutManager!==!0&&(e=e||document,$("#page-content").addClass("page-content-overflow-hidden"),this.windowHeight=$(window).height(),this.onChangeLayout(e),void(null===this.exchange&&(this.exchange=window.InfinniUI.global.messageBus,this.exchange.subscribe("OnChangeLayout",_.debounce(this.onChangeLayout.bind(this),42)))))},onChangeLayout:function(e){_.isEmpty(e)&&(e=document);var t=this.windowHeight-$("#page-top:not(:hidden)",e).outerHeight()-$("#page-bottom:not(:hidden)",e).outerHeight()-$("#menu-area:not(:hidden)",e).outerHeight();this.resizeView(e,t),this.resizeDialog()}};window.InfinniUI.LayoutManager=layoutManager;var LOG_LEVEL={debug:1,info:2,warn:3,error:4,trace:5};_.extend(Logger.prototype,{getLevel:function(){return this.level},setLevel:function(e){this.level=e},addMessage:function(e,t){this.messages.push({type:e,message:t})},debug:function(e){this.level>LOG_LEVEL.debug||(this.showMessages&&console.debug(e.message||e),this.addMessage(LOG_LEVEL.debug,e))},info:function(e){this.level>LOG_LEVEL.info||(this.showMessages&&console.info(e.message||e),this.addMessage(LOG_LEVEL.info,e))},warn:function(e){this.level>LOG_LEVEL.warn||(this.showMessages&&console.warn(e.message||e),this.addMessage(LOG_LEVEL.warn,e))},error:function(e){this.level>LOG_LEVEL.error||(this.showMessages&&console.error(e.message||e),this.addMessage(LOG_LEVEL.error,e))},trace:function(e){this.level>LOG_LEVEL.trace||(this.showMessages&&console.error(e.message||e),this.addMessage(LOG_LEVEL.trace,e))}}),window.InfinniUI.global.logger=new Logger,InfinniUI.Metadata=InfinniUI.Metadata||{},InfinniUI.Metadata.isValidValue=function(e,t){var n=!1;for(var i in t)if(t[i]===e){n=!0;break}return n},InfinniUI.Metadata.isBindingMetadata=function(e){return $.isPlainObject(e)&&"Source"in e},Number.isInteger=Number.isInteger||function(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e},String.prototype.includes||(String.prototype.includes=function(){return String.prototype.indexOf.apply(this,arguments)!==-1});var stringUtils={format:function(e,t){return e.replace(/{(\d+)}/g,function(e,n){return"undefined"!=typeof t[n]?t[n]:e})},formatProperty:function(e,t){if(!t||0==t.length||""==e)return e;for(var n=e.split("."),i=t.length-1,o=n.length-1;o>=0;o--)"#"==n[o]&&i>=0?(n[o]=t[i],i--):("$"==n[o]||stringUtils.isNumeric(n[o]))&&i--;return n.join(".")},padLeft:function(e,t,n){"undefined"!=typeof n&&null!==n||(n=" ");var i=String(e);return i.length0&&(e=location.href.indexOf(n),e>0&&(t=location.href.substr(0,e))),t&&history.pushState(null,null,t)},setParameter:function(e,t){var n=location.search,i=_.isEmpty(n)?stringUtils.format("?{0}={1}",[e,t]):stringUtils.format("{0}&{1}={2}",[n,e,t]),o=stringUtils.format("{0}//{1}{2}{3}{4}",[location.protocol,location.host,location.pathname,i,location.hash]);history.pushState(null,null,o)},deleteParameter:function(e){function t(e){var t=[];return _.mapObject(e,function(e,n){var i=stringUtils.format("{0}={1}",[n,e]);t.push(i)}),_.isEmpty(t)?"":"?"+t.join("&")}var n=urlManager.getParams();delete n[e];var i=t(n),o=stringUtils.format("{0}//{1}{2}{3}{4}",[location.protocol,location.host,location.pathname,i,location.hash]);history.pushState(null,null,o)}};window.InfinniUI.UrlManager=urlManager,window.InfinniUI.global.messageBus=new MessageBus,window.messageTypes={onViewBuildError:{name:"onViewBuildError"},onViewCreated:{name:"onViewCreated"},onChangeLayout:{name:"OnChangeLayout"},onNotifyUser:{name:"onNotifyUser"},onToolTip:{name:"onToolTip"},onContextMenu:{name:"onContextMenu"},onOpenContextMenu:{name:"onOpenContextMenu"},onDataLoading:{name:"onDataLoading"},onDataLoaded:{name:"onDataLoaded"}};var ajaxRequestMixin=function(e){function t(e,t){var n;return"function"==typeof e&&(n=e.apply(null,Array.prototype.slice.call(t))),n}return{onBeforeRequest:function(n){return function(){return e.send(messageTypes.onDataLoading,{}),t(n,arguments)}},onSuccessRequest:function(n){return function(){return e.send(messageTypes.onDataLoaded,{success:!0}),t(n,arguments)}},onErrorRequest:function(n){return function(){return e.send(messageTypes.onDataLoaded,{success:!1}),t(n,arguments)}}}}(window.InfinniUI.global.messageBus),bindUIElementsMixin={bindUIElements:function(){if(this.ui={},"undefined"!=typeof this.UI)for(var e in this.UI)this.UI.hasOwnProperty(e)&&(this.ui[e]=this.$(this.UI[e]))}},eventHandlerMixin={addEventHandler:function(e,t){if(this.initEventHandlerMixin(),null===e||"undefined"==typeof e)return!1;if(null===t||"undefined"==typeof t)return!1;"undefined"==typeof this.eventHandlers[e]&&(this.eventHandlers[e]=[]);var n=this.eventHandlers[e];n.indexOf(t)===-1&&n.push(t)},callEventHandler:function(e){if("undefined"!=typeof this.eventHandlers&&null!==e&&"undefined"!=typeof e){var t=this.eventHandlers[e];if("undefined"!=typeof t){var n,i=Array.prototype.slice.call(arguments,1),o=i.pop();"function"==typeof o&&(n=o),o=i.pop(),_.each(t,function(e){var t=e.apply(void 0,o);"undefined"!=typeof n&&n(t)})}}},initEventHandlerMixin:function(){"undefined"==typeof this.eventHandlers&&(this.eventHandlers={})}},Control=function(e){this.controlModel=this.createControlModel(),this.controlView=this.createControlView(this.controlModel,e),this.initHandlers()};_.extend(Control.prototype,{createControlModel:function(){throw"Не перегружен абстрактный метод Control.createControlModel()"},createControlView:function(e,t){throw"Не перегружен абстрактный метод Control.createControlView()"},initHandlers:function(){this.controlView.on("onLoaded",function(){this.controlModel.set("isLoaded",!0)},this)},set:function(e,t){this.controlModel.set(e,t)},get:function(e){return this.controlModel.get(e)},on:function(e,t){return this.controlModel.on(e,t)},render:function(){return this.controlView.render().$el},getChildElements:function(){return[]},onLoaded:function(e){this.controlModel.on("change:isLoaded",function(t){t&&e()})},isLoaded:function(){return this.controlModel.get("isLoaded")},onBeforeClick:function(e){this.controlView.on("beforeClick",e)},onClick:function(e){this.controlView.$el.on("click",e)},onDoubleClick:function(e){this.controlView.$el.on("dblclick",e)},onMouseDown:function(e){this.controlView.$el.on("mousedown",e)},onMouseUp:function(e){this.controlView.$el.on("mouseup",e)},onMouseEnter:function(e){this.controlView.$el.on("mouseenter",e)},onMouseLeave:function(e){this.controlView.$el.on("mouseleave",e)},onMouseMove:function(e){this.controlView.$el.on("mousemove",e)},onMouseWheel:function(e){this.controlView.$el.on("mousewheel DOMMouseScroll",e)},onKeyDown:function(e){this.controlView.$el.on("keydown",e)},onKeyUp:function(e){this.controlView.$el.on("keyup",e)},remove:function(){this.controlView.remove()},setFocus:function(){this.controlView.setFocus()}}),InfinniUI.Control=Control;var ControlModel=Backbone.Model.extend({defaults:{text:null,name:null,enabled:!0,parentEnabled:!0,visible:!0,textHorizontalAlignment:InfinniUI.TextHorizontalAlignment.left,horizontalAlignment:"Stretch",verticalAlignment:"Top",textStyle:null,background:null,foreground:null,isLoaded:!1,validationState:"success",validationMessage:"",focusable:!0,focused:!1},initialize:function(){this.set("guid",guid(),{silent:!0}),this.on("change:focused",function(e,t){this.trigger(t?"OnGotFocus":"OnLostFocus")})},set:function(e,t,n){var i,o=this.defaults;if(null==e)return this;"object"==typeof e?(i=e,n=t):(i={})[e]=t;for(var r in i)"undefined"!=typeof i[r]&&null!==i[r]||r in o&&(i[r]=o[r]);return Backbone.Model.prototype.set.call(this,i,n)}});InfinniUI.ControlModel=ControlModel;var ControlView=Backbone.View.extend({initialize:function(){this.wasRendered=!1,this.once("render",this.initHandlersForProperties,this),this._initDomHandlers()},classNameFocused:"pl-focused",_initDomHandlers:function(){var e=this,t=this.$el;t[0].addEventListener("click",function(t){e.trigger("beforeClick",null,{value:t})},!0)},initHandlersForProperties:function(){this.listenTo(this.model,"change:visible",this.updateVisible),this.listenTo(this.model,"change:horizontalAlignment",this.updateHorizontalAlignment),this.listenTo(this.model,"change:textHorizontalAlignment",this.updateTextHorizontalAlignment),this.listenTo(this.model,"change:verticalAlignment",this.updateVerticalAlignment),this.listenTo(this.model,"change:enabled",this.updateEnabled),this.listenTo(this.model,"change:name",this.updateName),this.listenTo(this.model,"change:style",this.updateStyle),this.listenTo(this.model,"change:text",this.updateText),this.listenTo(this.model,"change:textStyle",this.updateTextStyle),this.listenTo(this.model,"change:background",this.updateBackground),this.listenTo(this.model,"change:foreground",this.updateForeground),this.listenTo(this.model,"change:validationState",this.updateValidationState),this.listenTo(this.model,"change:focusable",this.updateFocusable),this.listenTo(this.model,"change:focused",this.updateFocused),this.initFocusHandlers()},initFocusHandlers:function(){function e(e){o.set("focused",!0)}function t(e){i.isControlElement(e.relatedTarget)?o.set("focused",!0):o.set("focused",!1)}var n=this.$el,i=(this.el,this),o=this.model;n.on("focusin",e).on("focusout",t)},isControlElement:function(e){return this.el===e||$.contains(this.el,e)},updateProperties:function(){this.updateVisible(),this.updateTextHorizontalAlignment(),this.updateHorizontalAlignment(),this.updateVerticalAlignment(),this.updateEnabled(),this.updateName(),this.updateText(),this.updateStyle(),this.updateTextStyle(),this.updateBackground(),this.updateForeground(),this.updateValidationState(),this.updateFocusable(),this.updateFocused(),this.updateViewMode()},updateFocusable:function(){},getElementForFocus:function(){return this.$el},updateFocused:function(){var e=this.model.get("focused");if(e){var t=this.getElementForFocus();t&&t.length}this.$el.toggleClass(this.classNameFocused,e)},onFocusHandler:function(e){},updateVisible:function(){var e=this.model.get("visible");this.$el.toggleClass("hidden",!e),this.onUpdateVisible()},onUpdateVisible:function(){this.updateLayout()},updateLayout:function(){var e=window.InfinniUI.global.messageBus;e.send("OnChangeLayout",{})},updateEnabled:function(){var e=this.model.get("enabled");this.$el.toggleClass("pl-disabled",!e)},updateVerticalAlignment:function(){this.switchClass("verticalAlignment",this.model.get("verticalAlignment"),this.$el,!1)},updateTextHorizontalAlignment:function(){this.switchClass("pl-text-horizontal",this.model.get("textHorizontalAlignment"))},updateHorizontalAlignment:function(){this.switchClass("pl-horizontal",this.model.get("horizontalAlignment"))},updateName:function(){var e=this.model.get("name"),t=this.$el.attr("data-pl-name");e!=t&&"string"==typeof e&&this.$el.attr("data-pl-name",e)},updateText:function(){},updateTextStyle:function(){var e=this.model.get("textStyle");this.currentTextStyle&&this.$el.removeClass(this.valueToTextClassName(this.currentTextStyle)),e&&this.$el.addClass(this.valueToTextClassName(e)),this.currentTextStyle=e},updateBackground:function(){var e=this.model.get("background");this.currentBackground&&this.$el.removeClass(this.valueToBackgroundClassName(this.currentBackground)),e&&this.$el.addClass(this.valueToBackgroundClassName(e)),this.currentBackground=e},updateForeground:function(){var e=this.model.get("foreground");this.currentForeground&&this.$el.removeClass(this.valueToForegroundClassName(this.currentForeground)),e&&this.$el.addClass(this.valueToForegroundClassName(e)),this.currentForeground=e},updateStyle:function(){var e=this.model.get("style");this.currentStyle&&this.$el.removeClass(this.currentStyle),e&&this.$el.addClass(e),this.currentStyle=e},updateViewMode:function(){"FormGroup"==this.viewMode&&this.$el.addClass("pl-form-group")},updateValidationState:function(){var e=this.model.get("validationState"),t=this.model.get("validationMessage");switch(e){case"success":this.$el.removeClass("has-warning has-error"),this.hideErrorMessage();break;case"warning":this.$el.removeClass("has-error").addClass("has-warning"),this.showErrorMessage(t);break;case"error":this.$el.removeClass("has-warning").addClass("has-error"),this.showErrorMessage(t)}},showErrorMessage:function(e){var t=$(_.template('')({message:e}));this.hideErrorMessage(),this.$el.find(".form-control:first").before(t),t.tooltip({container:"body"})},hideErrorMessage:function(){this.$el.find(".error-icn").remove()},rerender:function(){this.wasRendered&&this.render()},prerenderingActions:function(){this.wasRendered=!0},postrenderingActions:function(e){this.delegateEvents(),e=void 0===e||e,e&&this.trigger("onLoaded")},switchClass:function(e,t,n,i){"undefined"==typeof i?i="-":i===!1&&(i="");var o=e+i,r=new RegExp("(^|\\s)"+o+"\\S+","ig"),a=n||this.$el;a.removeClass(function(e,t){return(t.match(r)||[]).join(" ")}).addClass(o+t)},valueToBackgroundClassName:function(e){return"pl-"+e.toLowerCase()+"-bg"},valueToForegroundClassName:function(e){return"pl-"+e.toLowerCase()+"-fg"},valueToTextClassName:function(e){return"pl-"+e.toLowerCase()},renderTemplate:function(e){var t=this.getData();this.$el.html(e(t)),this.bindUIElements()},getData:function(){var e=this.model;return{name:e.get("name"),text:e.get("text"),focusable:e.get("focusable"),focused:e.get("focused"),enabled:e.get("enabled"),visible:e.get("visible"),horizontalAlignment:e.get("horizontalAlignment"),verticalAlignment:e.get("verticalAlignment"),textHorizontalAlignment:e.get("textHorizontalAlignment"),textVerticalAlignment:e.get("textVerticalAlignment"),textStyle:e.get("textStyle"),foreground:e.get("foreground"),background:e.get("background")}},setFocus:function(){this.$el.focus()}});_.extend(ControlView.prototype,bindUIElementsMixin,eventHandlerMixin),InfinniUI.ControlView=ControlView;var buttonControlMixin={click:function(){this.controlView.$el.click()}};_.inherit(ContainerControl,Control),_.extend(ContainerControl.prototype,{});var ContainerModel=ControlModel.extend({defaults:_.defaults({itemTemplate:null},ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments)),this.set("items",new Collection)}}),ContainerView=ControlView.extend({initialize:function(e){ControlView.prototype.initialize.call(this,e),this.childElements=[],this.listenTo(this.model,"change:groupValueSelector",this.updateGrouping),this.updateGrouping()},updateGrouping:function(){throw"ContainerView.updateGrouping В потомке ContainerView не реализовано обновление группировок."},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this);var e=this;this.model.get("items").onChange(function(t){switch(t.action){case"replace":break;default:e.rerender()}})},removeChildElements:function(){for(var e=0,t=this.childElements.length;e0?t.deleteSelectedText(this.getCaretPosition(),this.getSelectionLength(),o):t.setCharAt(o,this.getCaretPosition(),this.getSelectionLength()),this.model.setText(t.getText()),n!==!1&&this.setCaretPosition(n)}}}},onKeyupHandler:function(e){this.trigger("onKeyDown",{keyCode:e.which,value:this.model.getValue()})},onClickHandler:function(e){this.checkCurrentPosition(),e.preventDefault()},onPasteHandler:function(e){var t=e.originalEvent,n=t.clipboardData.getData("text/plain"),i=this.model.getEditMask();i&&(e.preventDefault(),this.textTyping(n))},OnDragstartHandler:function(e){var t=e.originalEvent;t.dataTransfer.effectAllowed="copy",this.$el.attr("data-dragged",!0)},OnDragendHandler:function(){this.$el.removeAttr("data-dragged",!1)},OnDragoverHandler:function(e){e.preventDefault()},OnDragenterHandler:function(e){var t=this.$el.attr("data-dragged");!t&&this.getCanChange()&&this.model.setEditMode()},OnDragleaveHandler:function(e){var t=this.$el.attr("data-dragged");t||this.model.setDisplayMode()},onDropHandler:function(e){e.preventDefault(),e.stopPropagation();var t=this.$el.attr("data-dragged");if(!t&&this.getCanChange()){var n=e.originalEvent,i=n.dataTransfer.getData("text/plain");this.textTyping(i,0),this.$el.focus()}},getCanChange:function(){var e=this.$el.prop("disabled");return e===!1},textTyping:function(e,t){var n=this.model.getEditMask(),i=e;n&&(e.split("").reduce(function(e,t){return n.setCharAt(t,e)},_.isNumber(t)?t:this.getCaretPosition()),i=n.getText()),this.model.setText(i)},checkCurrentPosition:function(e){if(this.canCaretPosition()){var t=this.model.getEditMask();if(t){"undefined"==typeof e&&(e=this.getCaretPosition());var n=0===e?t.moveToPrevChar(0):t.moveToNextChar(e-1);n!==e&&this.setCaretPosition(n)}}},getSelectionLength:function(){var e=this.el,t=0;if(this.canCaretPosition()){var n=parseInt(e.selectionStart,10),i=parseInt(e.selectionEnd,10);isNaN(n)||isNaN(i)||(t=i-n)}return t},canCaretPosition:function(){return/text|password|search|tel|url/.test(this.el.type)},setCaretPosition:function(e){if(_.isNumber(e)&&this.canCaretPosition()){var t=this.el;"undefined"!=typeof t.selectionStart&&t.setSelectionRange(e,e)}},getCaretPosition:function(){var e=this.el,t=0;return this.canCaretPosition()&&(t=e.selectionStart),t},initialize:function(){this.applyAutocomplete(),this.listenTo(this.model,"change:mode",this.onChangeModeHandler),this.listenTo(this.model,"change:text",this.onChangeTextHandler),this.listenTo(this.model,"invalid",this.onInvalidHandler)},applyAutocomplete:function(){var e=this.model.getEditMask();e&&this.$el.attr("autocomplete","off")},onInvalidHandler:function(e,t){this.$el.toggleClass(this.classNameError,!0)},onFocusinHandler:function(){this.model.setEditMode(),setTimeout(this.setCaretPosition.bind(this,0),4)},onFocusoutHandler:function(){this.model.setDisplayMode()},onChangeModeHandler:function(e,t){this.checkCurrentPosition()},onChangeTextHandler:function(e,t){var n=this.$el,i=this.getCaretPosition();n.toggleClass(this.classNameError,!1),n.val()!==t&&n.val(t);var o=this.model.getEditMask();o&&n.is(":focus")&&this.checkCurrentPosition(i)}});TextEditorModelBaseModeStrategy.prototype.updateText=function(e){},TextEditorModelBaseModeStrategy.prototype.setText=function(e,t,n){},TextEditorModelBaseModeStrategy.prototype.onChangeTextHandler=function(e,t,n){},TextEditorModelDisplayModeStrategy.prototype=Object.create(TextEditorModelBaseModeStrategy.prototype),TextEditorModelDisplayModeStrategy.prototype.constructor=TextEditorModelDisplayModeStrategy,TextEditorModelDisplayModeStrategy.prototype.updateText=function(e){var t,n=e.getDisplayFormat(),i=e.get("value");t=_.isFunction(n)?n.call(null,null,{value:i}):i,e.set("text",t)},TextEditorModelDisplayModeStrategy.prototype.setText=function(e,t,n){n&&e.set("text",t,{ui:n})},TextEditorModelDisplayModeStrategy.prototype.onChangeTextHandler=function(e,t,n){if(n.ui){var i=e.convertValue(t);e.set("value",i,{ui:n.ui})}e.applyChanges()},TextEditorModelEditModeStrategy.prototype=Object.create(TextEditorModelBaseModeStrategy.prototype),TextEditorModelEditModeStrategy.prototype.constructor=TextEditorModelBaseModeStrategy, -TextEditorModelEditModeStrategy.prototype.updateText=function(e){var t,n=e.getEditMask(),i=e.get("value");n?(n.reset(i),t=n.getText()):t=i,"undefined"==typeof t||null===t?e.set("text",""):e.set("text",t.toString())},TextEditorModelEditModeStrategy.prototype.setText=function(e,t,n){e.set("text",t,{ui:n})},TextEditorModelEditModeStrategy.prototype.onChangeTextHandler=function(e,t,n){var i=e.getEditMask(),o=i?i.getData():t;e.set("value",e.convertValue(o),{silent:!!i,ui:n.ui})},_.inherit(TextBoxControl,TextEditorBaseControl),_.extend(TextBoxControl.prototype,{createControlModel:function(){return new TextBoxModel},createControlView:function(e){return new TextBoxView({model:e})}});var TextBoxModel=TextEditorBaseModel.extend({defaults:_.extend({},TextEditorBaseModel.prototype.defaults,{multiline:!1,inputType:"text"}),initialize:function(){TextEditorBaseModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),TextBoxView=TextEditorBaseView.extend({template:{oneline:InfinniUI.Template["controls/textBox/template/oneline.tpl.html"],multiline:InfinniUI.Template["controls/textBox/template/multiline.tpl.html"]},className:"pl-textbox form-group",UI:_.extend({},TextEditorBaseView.prototype.UI),events:_.extend({},TextEditorBaseView.prototype.events,{}),initHandlersForProperties:function(){TextEditorBaseView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:multiline",this.updateMultiline),this.listenTo(this.model,"change:lineCount",this.updateLineCount)},updateProperties:function(){TextEditorBaseView.prototype.updateProperties.call(this),this.updateLineCount()},updateMultiline:function(){this.rerender()},updateLineCount:function(){var e=this.model.get("lineCount");this.ui.editor.attr("rows",e)},render:function(){this.prerenderingActions();var e=this.model,t=e.get("multiline")?this.template.multiline:this.template.oneline;return this.renderTemplate(t),this.renderTextBoxEditor(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},getData:function(){var e=TextEditorBaseView.prototype.getData.call(this),t=this.model;return _.extend(e,{multiline:t.get("multiline"),lineCount:t.get("lineCount")})},renderTextBoxEditor:function(){this.renderControlEditor()}}),dateTimePickerModeDate={getTemplate:function(){return InfinniUI.Template["controls/dateTimePicker/template/date.tpl.html"]},onClickDropdownHandler:function(e){var t=this.model,n=new SelectDate({model:t});n.render(),$("body").append(n.$el),n.updatePosition(this.el),this.listenTo(n,"date",function(e){t.set("value",this.convertValue(e))})},convertValue:function(e){return InfinniUI.DateUtils.toISO8601(e,{timezoneOffset:this.model.get("timeZone")})}},dateTimePickerModeDateTime={getTemplate:function(){return InfinniUI.Template["controls/dateTimePicker/template/dateTime.tpl.html"]},onClickDropdownHandler:function(e){var t=this.model,n=new SelectDateTime({model:t});n.render(),$("body").append(n.$el),n.updatePosition(this.el),this.listenTo(n,"date",function(e){t.set("value",this.convertValue(e))})},convertValue:function(e){return InfinniUI.DateUtils.toISO8601(e,{timezoneOffset:this.model.get("timeZone")})}},dateTimePickerModeTime={getTemplate:function(){return InfinniUI.Template["controls/dateTimePicker/template/time.tpl.html"]},onClickDropdownHandler:function(e){var t=this.model,n=new SelectTime({model:t});n.render(),$("body").append(n.$el),n.updatePosition(this.el),this.listenTo(n,"date",function(e){t.set("value",this.convertValue(e))})},convertValue:function(e){return InfinniUI.DateUtils.toISO8601(e,{timezoneOffset:this.model.get("timeZone")})}},SelectComponent=Backbone.View.extend({modelClass:Backbone.Model,initialize:function(e){var t=this.modelClass;return this.model=new t({today:e.today||new Date,value:e.value,date:e.value||e.today,max:e.max,min:e.min}),this.render(),this},show:function(){this.$el.css("display","block")},hide:function(){this.$el.css("display","none")},setDate:function(e){this.model.setDate(e)}});_.extend(SelectComponent.prototype,bindUIElementsMixin);var SelectComponentModel=Backbone.Model.extend({defaults:function(){var e=new Date;return{today:e,todayMonth:e.getMonth(),todayDay:e.getDate(),todayYear:e.getFullYear(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}},initialize:function(){this.updateDateParts(),this.on("change:date",this.onChangeDateHandler,this)},updateDateParts:function(){var e=this.get("date");e instanceof Date?this.set({year:e.getFullYear(),month:e.getMonth(),day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}):this.set({year:null,month:null,day:null,hour:null,minute:null,second:null,millisecond:null})},onChangeDateHandler:function(e,t){"undefined"!=typeof t&&null!==t?e.set({year:moment(t).year(),month:moment(t).month(),day:moment(t).date(),hour:moment(t).hour(),minute:moment(t).minute(),second:moment(t).second(),millisecond:moment(t).millisecond()}):e.set({year:null,month:null,day:null,hour:null,minute:null,second:null,millisecond:null})},updateDatePart:function(e,t,n){var i=this.get("date"),o=InfinniUI.DateUtils.createDate(i)||this.get("today"),r=this.toJSON();switch(e){case"hour":case"minute":case"second":o.setHours(r.hour,r.minute,r.second);break;case"year":case"month":case"day":o.setFullYear(r.year,r.month,r.day)}this.set("date",o)},checkRange:function(e,t){var n=this.get("min"),i=this.get("max");return InfinniUI.DateUtils.checkRangeDate(e,n,i,t)},keepDateInRange:function(){if(!this.isValid()){var e=InfinniUI.DateUtils.getNearestDate(this.get("date"),this.get("min"),this.get("max"));this.set("date",e)}},setDate:function(e){if("undefined"==typeof e||null===e){var t=this.get("value"),n=this.get("date");e=t||n}e instanceof Date&&(e=new Date(e.getTime())),this.set("date",e)}}),SelectDaysModel=SelectComponentModel.extend({initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:year",this.updateDatePart.bind(this,"year")),this.on("change:month",this.updateDatePart.bind(this,"month")),this.on("change:day",this.updateDatePart.bind(this,"day"))},today:function(){this.set({year:this.get("todayYear"),month:this.get("todayMonth")})},nextMonth:function(){var e=this.get("month"),t=this.get("year");this.set({month:11===e?0:e+1,year:11===e?t+1:t}),this.keepDateInRange()},prevMonth:function(){var e=this.get("month"),t=this.get("year");this.set({month:0===e?11:e-1,year:0===e?t-1:t}),this.keepDateInRange()}}),SelectDays=SelectComponent.extend({modelClass:SelectDaysModel,template:InfinniUI.Template["controls/dateTimePicker/template/date/days.tpl.html"],UI:{headerDays:".weekdays-head .day",calendarDays:".day-calendar",year:".years-year",month:".years-month"},events:{"click .years":"onYearsClickHandler","click .btn-month-prev":"prevMonth","click .btn-month-next":"nextMonth","click .today-date":"showToday",'click .day-calendar:not(".day-unavailable")':"useDay","click .time":"showTime"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.fillLegend(),this.fillCalendar(),this.renderMonth(),this.renderYear(),this.initOnChangeHandlers()},initOnChangeHandlers:function(){this.listenTo(this.model,"change:month",this.onChangeMonthHandler),this.listenTo(this.model,"change:year",this.onChangeYearHandler),this.listenTo(this.model,"change:day",this.onChangeDayHandler)},renderMonth:function(){var e=this.model.get("month"),t=localized.dateTimeFormatInfo;this.ui.month.text(t.monthNames[e])},renderYear:function(){var e=this.model.get("year");this.ui.year.text(e)},onChangeMonthHandler:function(e,t){this.renderMonth(),this.fillCalendar()},onChangeYearHandler:function(e,t){this.renderYear(),this.fillCalendar()},fillLegend:function(){function e(e,t){e.toggleClass("day-weekend",0===t||6===t)}var t=localized.dateTimeFormatInfo,n=t.firstDayOfWeek,i=t.abbreviatedDayNames.map(function(e,t){return t});n>0&&(i=i.splice(n).concat(i)),this.ui.headerDays.each(function(n,o){var r=$(o),a=i[n];r.text(t.abbreviatedDayNames[a]),e(r,a)}),this.ui.calendarDays.each(function(t,n){var o=$(n),r=i[t%7];e(o,r)})},fillCalendar:function(){function e(e,t){e.toggleClass("day-inactive",!t)}function t(e,t){var n=t.getMonth()===o.get("todayMonth")&&t.getFullYear()===o.get("todayYear")&&t.getDate()===o.get("todayDay");e.toggleClass("day-today",n)}function n(e,t){var n=!1;r&&(n=moment(r).isSame(t,"day")),e.toggleClass("day-selected",n)}function i(e,t){e.toggleClass("day-unavailable",!o.checkRange(t,"day"))}var o=this.model,r=o.get("value"),a=o.get("month"),l=o.get("year"),s=(o.get("day"),o.get("min"),o.get("max"),new Date(l,a)),u=s.getDay(),d=localized.dateTimeFormatInfo,c=d.firstDayOfWeek,h=[0,1,2,3,4,5,6];Array.prototype.push.apply(h,h.splice(0,c));var p=new Date(l,a,1-h.indexOf(u)),m=p.getFullYear(),f=p.getMonth(),g=p.getDate();this.ui.calendarDays.each(function(o,r){var l=$(r),s=new Date(m,f,g+o);l.text(s.getDate()),l.attr("data-date",s),e(l,s.getMonth()===a),t(l,s),n(l,s),i(l,s)})},onYearsClickHandler:function(e){var t=this.model.get("date");this.trigger("year",t)},prevMonth:function(){this.model.prevMonth()},nextMonth:function(){this.model.nextMonth()},showToday:function(){this.today()},today:function(){this.model.today()},showTime:function(){this.trigger("time",this.model.get("date"))},useDay:function(e){var t=$(e.target),n=new Date(t.attr("data-date"));this.model.set({year:n.getFullYear(),month:n.getMonth(),day:n.getDate()}),this.trigger("date",this.model.get("date"))}}),SelectHoursModel=SelectComponentModel.extend({initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:hour",this.updateDatePart.bind(this,"hour"))}}),SelectHours=SelectComponent.extend({modelClass:SelectHoursModel,template:InfinniUI.Template["controls/dateTimePicker/template/time/hours.tpl.html"],events:{"click .hour:not('.hour-unavailable')":"useHour"},UI:{hour:".hour"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.fillHoursTable(),this.initOnChangeHandlers()},fillHoursTable:function(){function e(e,t){e.toggleClass("hour-selected",o.getHours()===t)}function t(e,t){var n=moment(r).isSame(t,"hour");e.toggleClass("hour-today",n)}function n(e,t){var n=moment(i.get("date")).hour(t);e.toggleClass("hour-unavailable",!i.checkRange(n,"hour"))}var i=this.model,o=i.get("date")||i.get("today"),r=new Date;this.ui.hour.each(function(i,o){var r=$(o),a=stringUtils.padLeft(i,2,"0");r.attr("data-hour",i),r.text(a),t(r,i),e(r,i),n(r,i)})},initOnChangeHandlers:function(){this.listenTo(this.model,"change:date",this.fillHoursTable)},useHour:function(e){var t=$(e.target),n=this.model,i=n.get("date"),o=parseInt(t.attr("data-hour"),10),r=InfinniUI.DateUtils.cloneDate(i);r.setHours(o),n.set("date",r),this.trigger("hour",r)}}),SelectMinutesModel=SelectComponentModel.extend({initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:minute",this.updateDatePart.bind(this,"minute"))}}),SelectMinutes=SelectComponent.extend({modelClass:SelectMinutesModel,template:InfinniUI.Template["controls/dateTimePicker/template/time/minutes.tpl.html"],events:{"click .minute:not('.minute-unavailable')":"useMinute"},UI:{minute:".minute"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.fillMinutesTable(),this.initOnChangeHandlers()},fillMinutesTable:function(){function e(e,t){e.toggleClass("minute-selected",t===i)}function t(e,t){var i=moment(n.get("date")).minute(t);e.toggleClass("minute-unavailable",!n.checkRange(i,"minute"))}var n=this.model,i=n.get("minute");this.ui.minute.each(function(n,i){var o=$(i),r=o.attr("data-minute");e(o,parseInt(r,10)),t(o,parseInt(r,10))})},initOnChangeHandlers:function(){this.listenTo(this.model,"change:date",this.fillMinutesTable)},useMinute:function(e){var t=$(e.target),n=this.model,i=n.get("date"),o=parseInt(t.attr("data-minute"),10),r=InfinniUI.DateUtils.cloneDate(i);r.setMinutes(o),this.trigger("minute",r)}}),SelectMonthsModel=SelectComponentModel.extend({initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:month",this.updateDatePart.bind(this,"month")),this.on("change:year",this.updateDatePart.bind(this,"year"))},nextYear:function(){var e=this.get("year");this.set("year",e+1),this.keepDateInRange()},prevYear:function(){var e=this.get("year");this.set("year",e-1),this.keepDateInRange()},today:function(){this.set({month:this.get("todayMonth"),year:this.get("todayYear")})}}),SelectMonths=SelectComponent.extend({modelClass:SelectMonthsModel,template:InfinniUI.Template["controls/dateTimePicker/template/date/months.tpl.html"],events:{"click .btn-year-prev":"prevYear","click .btn-year-next":"nextYear","click .month:not('.month-unavailable')":"useMonth","click .year":"selectYear","click .today-month":"showToday"},UI:{month:".month",year:".year"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.fillMonthsTable(),this.initOnChangeHandlers()},fillMonthsTable:function(){function e(e,t){var n=moment([i.get("year"),t]),o=i.get("today");e.toggleClass("month-today",moment(n).isSame(o,"month"))}function t(e,t){var n=moment([i.get("year"),t]),o=i.get("value");e.toggleClass("month-selected",moment(n).isSame(o,"month"))}function n(e,t){var n=moment([i.get("year"),t]);e.toggleClass("month-unavailable",!i.checkRange(n,"month"))}this.ui.year.text(this.model.get("year"));var i=this.model,o=localized.dateTimeFormatInfo;i.get("todayMonth"),i.get("month");this.ui.month.each(function(i,r){var a=$(r);a.text(o.abbreviatedMonthNames[i]),a.attr("data-month",i),e(a,i),t(a,i),n(a,i)})},initOnChangeHandlers:function(){this.listenTo(this.model,"change:year",this.fillMonthsTable)},prevYear:function(){this.model.prevYear()},nextYear:function(){this.model.nextYear()},useMonth:function(e){var t=$(e.target),n=this.model;n.set({year:parseInt(n.get("year"),10),month:parseInt(t.attr("data-month"),10)}),this.trigger("month",n.get("date"))},selectYear:function(){var e=this.model;this.trigger("year",e.get("data"))},showToday:function(){this.today()},today:function(){this.model.today()}}),SelectSecondsModel=SelectComponentModel.extend({initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:second",this.updateDatePart.bind(this,"second"))}}),SelectSeconds=SelectComponent.extend({modelClass:SelectSecondsModel,template:InfinniUI.Template["controls/dateTimePicker/template/time/seconds.tpl.html"],events:{"click .second:not('.second-unavailable')":"useSecond"},UI:{second:".second"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.fillSecondsTable(),this.initOnChangeHandlers()},fillSecondsTable:function(){function e(e,t){e.toggleClass("second-selected",t===i)}function t(e,t){var i=moment(n.get("date")).seconds(t);e.toggleClass("second-unavailable",!n.checkRange(i))}var n=this.model,i=n.get("second");this.ui.second.each(function(n,i){var o=$(i),r=o.attr("data-second");e(o,parseInt(r,10)),t(o,parseInt(r,10))})},initOnChangeHandlers:function(){this.listenTo(this.model,"change:date",this.fillSecondsTable)},useSecond:function(e){var t=$(e.target),n=this.model,i=n.get("date"),o=parseInt(t.attr("data-second"),10),r=InfinniUI.DateUtils.cloneDate(i);r.setSeconds(o),this.trigger("second",r)}}),SelectTimesModel=SelectComponentModel.extend({initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:hour",this.updateDatePart.bind(this,"hour")),this.on("change:minute",this.updateDatePart.bind(this,"minute")),this.on("change:second",this.updateDatePart.bind(this,"second")),this.on("change:millisecond",this.updateDatePart.bind(this,"millisecond"))},nextHour:function(){var e=this.get("hour");e+=1,e>23||(this.set("hour",e),this.keepDateInRange())},prevHour:function(){var e=this.get("hour");e-=1,e<0||(this.set("hour",e),this.keepDateInRange())},nextMinute:function(){var e=this.get("minute");e+=1,e>=60||(this.set("minute",e),this.keepDateInRange())},prevMinute:function(){var e=this.get("minute");e-=1,e<0||(this.set("minute",e),this.keepDateInRange())},nextSecond:function(){var e=this.get("second");e+=1,e>=60||(this.set("second",e),this.keepDateInRange())},prevSecond:function(){var e=this.get("second");e-=1,e<0||(this.set("second",e),this.keepDateInRange())},validate:function(e,t){var n=InfinniUI.DateUtils.cloneDate(e.date);if(n.setHours(e.hour,e.minute,e.second,e.millisecond),!this.checkRange(n))return"Out of range"}}),SelectTimes=SelectComponent.extend({modelClass:SelectTimesModel,template:InfinniUI.Template["controls/dateTimePicker/template/time/time.tpl.html"],events:{"click .time-spin-down.time-spin-hour":"prevHour","click .time-spin-up.time-spin-hour":"nextHour","click .time-spin-down.time-spin-minute":"prevMinute","click .time-spin-up.time-spin-minute":"nextMinute","click .time-spin-down.time-spin-second":"prevSecond","click .time-spin-up.time-spin-second":"nextSecond","click .time-segment-hour":"selectHour","click .time-segment-minute":"selectMinute","click .time-segment-second":"selectSecond","click .days":"selectDay"},UI:{month:".month",year:".year",hour:".time-segment-hour",minute:".time-segment-minute",second:".time-segment-second"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.updateHour(),this.updateMinute(),this.updateSecond(),this.initOnChangeHandlers()},selectHour:function(){var e=this.model,t=e.get("date"),n=e.get("hour"),i=e.get("minute"),o=e.get("second");t.setHours(n,i,o),this.trigger("hour",t)},selectMinute:function(){var e=this.model,t=e.get("date"),n=e.get("hour"),i=e.get("minute"),o=e.get("second");t.setHours(n,i,o),this.trigger("minute",t)},selectSecond:function(){var e=this.model,t=e.get("date"),n=e.get("hour"),i=e.get("minute"),o=e.get("second");t.setHours(n,i,o),this.trigger("second",t)},initOnChangeHandlers:function(){this.listenTo(this.model,"change:hour",this.updateHour),this.listenTo(this.model,"change:minute",this.updateMinute),this.listenTo(this.model,"change:second",this.updateSecond),this.listenTo(this.model,"change:date",this.useTime)},updateHour:function(){var e=this.model.get("hour");this.ui.hour.text(stringUtils.padLeft(e,2,"0"))},updateMinute:function(){var e=this.model.get("minute");this.ui.minute.text(stringUtils.padLeft(e,2,"0"))},updateSecond:function(){var e=this.model.get("second");this.ui.second.text(stringUtils.padLeft(e,2,"0"))},prevHour:function(){this.model.prevHour()},nextHour:function(){this.model.nextHour()},prevMinute:function(){this.model.prevMinute()},nextMinute:function(){this.model.nextMinute()},prevSecond:function(){this.model.prevSecond()},nextSecond:function(){this.model.nextSecond()},useTime:function(){var e=this.model.get("date");this.trigger("date",e)},selectDay:function(){var e=this.model.get("date");this.trigger("day",e)}}),SelectYearsModel=SelectComponentModel.extend({defaults:function(){var e=SelectComponentModel.prototype.defaults.call(this);return _.defaults({pageSize:20,page:0},e)},initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:year",this.updateDatePart.bind(this,"year")),this.on("change:year",this.onChangeYearHandler)},prevPage:function(){var e=this.get("page");this.set("page",e-1)},nextPage:function(){var e=this.get("page");this.set("page",e+1)},resetPage:function(){this.set("page",0)},onChangeYearHandler:function(e,t){this.keepDateInRange(),e.set("page",0)}}),SelectYears=SelectComponent.extend({modelClass:SelectYearsModel,template:InfinniUI.Template["controls/dateTimePicker/template/date/years.tpl.html"],events:{"click .btn-year-prev":"prevPage","click .btn-year-next":"nextPage","click .today-year":"showTodayYear",'click .year:not(".year-unavailable")':"useYear"},UI:{years:".year",yearBegin:".year-begin",yearEnd:".year-end"},initOnChangeHandlers:function(){this.listenTo(this.model,"change:page",this.fillYearsTable),this.listenTo(this.model,"change:year",this.fillYearsTable)},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.fillYearsTable(),this.initOnChangeHandlers()},fillYearsTable:function(){function e(e,t){e.toggleClass("year-today",t===l)}function t(e,t){e.toggleClass("year-selected",t===a)}function n(e,t){var n=moment([t]);e.toggleClass("year-unavailable",!i.checkRange(n,"year"))}var i=this.model,o=i.get("page"),r=i.get("pageSize"),a=i.get("year"),l=i.get("todayYear"),s=Math.ceil(a-r/2)+o*r;this.ui.years.each(function(i,o){var r=$(o),a=s+i;r.text(a),r.attr("data-year",a),e(r,a),t(r,a),n(r,a)}),this.ui.yearBegin.text(s),this.ui.yearEnd.text(s+r-1)},prevPage:function(){this.model.prevPage()},nextPage:function(){this.model.nextPage()},showTodayYear:function(){this.today()},today:function(){this.model.resetPage()},useYear:function(e){var t=$(e.target),n=this.model;n.set({year:parseInt(t.attr("data-year"),10)}),this.trigger("year",n.get("date"))}});window.InfinniUI.DateTimePickerControl=DateTimePickerControl,_.inherit(DateTimePickerControl,TextEditorBaseControl),_.extend(DateTimePickerControl.prototype,{createControlModel:function(){return new DateTimePickerModel},createControlView:function(e){return new DateTimePickerView({model:e})}});var DateTimePickerModel=TextEditorBaseModel.extend({defaults:_.extend({},TextEditorBaseModel.prototype.defaults,{mode:"Date"}),initialize:function(){TextEditorBaseModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments)),this.set("today",new Date),this.set("timeZone",InfinniUI.DateUtils.getDefaultTimeZone())},validate:function(e,t){e.minValue,e.maxValue;return InfinniUI.DateUtils.checkRangeDate(e.value,e.minValue,e.maxValue)}}),dateTimePickerStrategy=function(){return{Date:dateTimePickerModeDate,DateTime:dateTimePickerModeDateTime,Time:dateTimePickerModeTime}}(),DateTimePickerView=TextEditorBaseView.extend({className:"pl-datepicker form-group",template:InfinniUI.Template["controls/dateTimePicker/template/date.tpl.html"],UI:_.extend({},TextEditorBaseView.prototype.UI,{dropdownButton:".pl-datepicker-calendar",controlWrap:".control-wrap",editorWrap:".editor-wrap"}),events:_.extend({},TextEditorBaseView.prototype.events,{"click .pl-datepicker-calendar":"onClickDropdownHandler"}),initialize:function(){TextEditorBaseView.prototype.initialize.apply(this,Array.prototype.slice.call(arguments)),this.updateMode(),this.listenTo(this.model,"change:mode",this.updateMode)},initHandlersForProperties:function(){TextEditorBaseView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:minValue",this.updateMinValue),this.listenTo(this.model,"change:maxValue",this.updateMaxValue)},updateProperties:function(){TextEditorBaseView.prototype.updateProperties.call(this)},updateMode:function(){var e=this.model.get("mode");_.extend(this,dateTimePickerStrategy[e]),this.rerender()},updateMinValue:function(){var e=this.model.get("mode");_.extend(this,dateTimePickerStrategy[e]),this.rerender()},updateMaxValue:function(){var e=this.model.get("mode");_.extend(this,dateTimePickerStrategy[e]),this.rerender()},updateEnabled:function(){TextEditorBaseView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");this.ui.dropdownButton.prop("disabled",!e)},render:function(){return this.prerenderingActions(),this.renderTemplate(this.getTemplate()),this.updateProperties(),this.renderDateTimePickerEditor(),this.trigger("render"),this.postrenderingActions(),this},getData:function(){var e=this.model;return _.extend({},TextEditorBaseView.prototype.getData.call(this),{minValue:e.get("minValue"),maxValue:e.get("maxValue"),mode:e.get("mode")})},renderDateTimePickerEditor:function(){this.model;return this.renderControlEditor(),this},getTemplate:function(){throw new Error("Не перекрыт getTemplate")},onClickDropdownHandler:function(e){}}),SelectDate=Backbone.View.extend({className:"pl-datepicker-dropdown pl-dropdown-container",template:InfinniUI.Template["controls/dateTimePicker/template/select.date.tpl.html"],UI:{days:".days",months:".months",years:".years"},events:{"click .backdrop":"onClickBackdropHandler","click .datepicker-clear":"onClickClearValueHandler","click .today-date":"onClickTodayHandler"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.renderComponents()},renderComponents:function(){var e=this.model,t=InfinniUI.DateUtils.createDate(e.get("value")),n=InfinniUI.DateUtils.createDate(e.get("today")),i=e.get("timeZone"),o=moment(t);t=o.isValid()?o.toDate():null,t=InfinniUI.DateUtils.changeTimezoneOffset(t,i);var r={value:t,today:n||new Date,max:e.get("maxValue"),min:e.get("minValue")};r.el=this.ui.months;var a=new SelectMonths(r);r.el=this.ui.years;var l=new SelectYears(r);r.el=this.ui.days;var s=new SelectDays(r);this.months=a,this.years=l,this.days=s,this.workflow(s,a,l,t)(t)},onClickBackdropHandler:function(e){this.remove()},onClickClearValueHandler:function(){this.clearValue()},clearValue:function(){this.useValue(null)},useValue:function(e){var t=this.model,n=t.get("timeZone"),i=t.get("minValue"),o=t.get("maxValue");InfinniUI.DateUtils.checkRangeDate(e,i,o)||(e=InfinniUI.DateUtils.getNearestDate(e,i,o)),this.trigger("date",InfinniUI.DateUtils.restoreTimezoneOffset(e,n)),this.remove()},workflow:function(e,t,n){function i(i){e.setDate(i),n.hide(),t.hide(),e.show()}function o(i){t.setDate(i),e.hide(),n.hide(),t.show()}function r(i){n.setDate(i),e.hide(),t.hide(),n.show()}return this.listenTo(e,"date",this.useValue).listenTo(e,"year",function(e){r(e)}).listenTo(n,"year",function(e){o(e)}).listenTo(t,"year",function(e){r(e)}).listenTo(t,"month",function(e){i(e)}),i},onClickTodayHandler:function(){this.useValue(new Date)},updatePosition:function(e){var t=this.getDropdownDirection(e);this.setPositionFor(e,t)},setPositionFor:function(e,t){clearInterval(this._intervalId),this.applyStyle(e,t),this._intervalId=setInterval(this.applyStyle.bind(this,e,t),100)},remove:function(){return clearInterval(this._intervalId),Backbone.View.prototype.remove.apply(this,arguments)},getDropdownDirection:function(e){var t=$(window).height(),n=e.getBoundingClientRect(),i=this.$el.height(),o="bottom";return n.bottom+i+30>t&&n.bottom>t/2&&n.top>i&&(o="top"),o},applyStyle:function(e,t){var n=e.getBoundingClientRect(),i=this.el.getBoundingClientRect(),o={position:"absolute",left:window.pageXOffset+n.right-Math.round(i.width)};"bottom"===t?o.top=window.pageYOffset+n.bottom:o.top=window.pageYOffset+n.top-this.$el.height(),this.$el.css(o)}});_.extend(SelectDate.prototype,bindUIElementsMixin);var SelectDateTime=SelectDate.extend({className:"pl-datepicker-dropdown pl-dropdown-container",template:InfinniUI.Template["controls/dateTimePicker/template/select.dateTime.tpl.html"],UI:{days:".days",months:".months",years:".years",times:".times",hours:".hours",minutes:".minutes"},onClickToggleDateHandler:function(){this.trigger("days")},onClickToggleTimeHandler:function(){this.trigger("time")},renderComponents:function(){var e=this.model,t=InfinniUI.DateUtils.createDate(e.get("value")),n=InfinniUI.DateUtils.createDate(e.get("today")),i=e.get("timeZone"),o=moment(t);t=o.isValid()?o.toDate():null,t=InfinniUI.DateUtils.changeTimezoneOffset(t,i);var r={value:t,today:n||new Date,max:e.get("maxValue"),min:e.get("minValue")};r.el=this.ui.months;var a=new SelectMonths(r);r.el=this.ui.years;var l=new SelectYears(r);r.el=this.ui.days;var s=new SelectDays(r);r.el=this.ui.times;var u=new SelectTimes(r);r.el=this.ui.hours;var d=new SelectHours(r);r.el=this.ui.minutes;var c=new SelectMinutes(r);this.workflow(s,a,l,u,d,c)(t)},useTime:function(e){var t=this.model,n=t.get("timeZone"),i=t.get("minValue"),o=t.get("maxValue");return InfinniUI.DateUtils.checkRangeDate(e,i,o)||(e=InfinniUI.DateUtils.getNearestDate(e,i,o)),this.trigger("date",InfinniUI.DateUtils.restoreTimezoneOffset(e,n)),e},workflow:function(e,t,n,i,o,r){function a(e){m.forEach(function(t){t!==e&&t.hide()}),e.show()}function l(t){e.setDate(t),a(e)}function s(e){t.setDate(e),a(t)}function u(e){n.setDate(e),a(n)}function d(e){o.setDate(e),a(o)}function c(e){r.setDate(e),a(r)}function h(e){i.setDate(e),a(i)}var p=this.useTime.bind(this),m=Array.prototype.slice.call(arguments);return this.listenTo(e,"date",this.useValue).listenTo(e,"year",function(e){u(e)}).listenTo(e,"time",function(e){h(e)}).listenTo(n,"year",function(e){s(e)}).listenTo(t,"year",function(e){u(e)}).listenTo(t,"month",function(e){l(e)}),this.listenTo(i,"hour",function(e){d(e)}).listenTo(i,"minute",function(e){c(e)}).listenTo(i,"day",function(e){l(e)}).listenTo(i,"date",function(e){p(e)}).listenTo(o,"hour",function(e){var t=p(e);h(t)}).listenTo(r,"minute",function(e){var t=p(e);h(t)}),this.on("days",function(e){l(e)}).on("time",function(e){h(e)}),l}}),SelectTime=SelectDate.extend({className:"pl-timepicker-dropdown pl-dropdown-container",template:InfinniUI.Template["controls/dateTimePicker/template/select.time.tpl.html"],UI:{times:".times",hours:".hours",minutes:".minutes",seconds:".seconds"},renderComponents:function(){var e=this.model,t=InfinniUI.DateUtils.createDate(e.get("value")),n=InfinniUI.DateUtils.createDate(e.get("today")),i=e.get("timeZone"),o=moment(t);t=o.isValid()?o.toDate():null,t=InfinniUI.DateUtils.changeTimezoneOffset(t,i);var r={value:t,today:n,max:e.get("maxValue"),min:e.get("minValue")};r.el=this.ui.times;var a=new SelectTimes(r);r.el=this.ui.hours;var l=new SelectHours(r);r.el=this.ui.minutes;var s=new SelectMinutes(r);r.el=this.ui.seconds;var u=new SelectSeconds(r);this.workflow(a,l,s,u)(t)},useTime:function(e){var t=this.model,n=t.get("timeZone"),i=t.get("minValue"),o=t.get("maxValue");return InfinniUI.DateUtils.checkRangeDate(e,i,o)||(e=InfinniUI.DateUtils.getNearestDate(e,i,o)),this.trigger("date",InfinniUI.DateUtils.restoreTimezoneOffset(e,n)),e},workflow:function(e,t,n,i){function o(e){d.forEach(function(t){t!==e&&t.hide()}),e.show()}function r(e){t.setDate(e),o(t)}function a(e){n.setDate(e),o(n)}function l(e){i.setDate(e),o(i)}function s(t){e.setDate(t),o(e)}var u=this.useTime.bind(this),d=Array.prototype.slice.call(arguments);return this.listenTo(e,"hour",function(e){r(e)}).listenTo(e,"minute",function(e){a(e)}).listenTo(e,"second",function(e){l(e)}).listenTo(e,"date",function(e){u(e)}).listenTo(t,"hour",function(e){var t=u(e);s(t)}).listenTo(n,"minute",function(e){var t=u(e);s(t)}).listenTo(i,"second",function(e){var t=u(e);s(t)}),s}});_.inherit(DatePickerControl,DateTimePickerControl),_.extend(DatePickerControl.prototype,{createControlModel:function(){return new DatePickerModel},createControlView:function(e){return new DatePickerView({model:e})}});var DatePickerModel=DateTimePickerModel.extend({initialize:function(){DateTimePickerModel.prototype.initialize.apply(this,arguments)}}),DatePickerView=DateTimePickerView.extend({});console.assert(dateTimePickerModeDate,"dateTimePickerModeDate is undefined");var dateTimePickerModeDatePicker=_.extend({},dateTimePickerModeDate,{convertValue:function(e){var t=null;return e&&e.constructor===Date&&(t=InfinniUI.DateUtils.dateToTimestamp(e)),t}});dateTimePickerStrategy.DatePicker=dateTimePickerModeDatePicker,console.assert(dateTimePickerModeTime,"dateTimePickerModeTime is undefined");var dateTimePickerModeTimePicker=_.extend({},dateTimePickerModeTime,{convertValue:function(e){var t=null;return e&&e.constructor===Date&&(t=InfinniUI.DateUtils.dateToTimestampTime(e)),t}});dateTimePickerStrategy.TimePicker=dateTimePickerModeTimePicker,_.inherit(TimePickerControl,DateTimePickerControl),_.extend(TimePickerControl.prototype,{createControlModel:function(){return new TimePickerModel},createControlView:function(e){return new TimePickerView({model:e})}});var TimePickerModel=DateTimePickerModel.extend({initialize:function(){DateTimePickerModel.prototype.initialize.apply(this,arguments);var e=new Date;e.setFullYear(1970,0,1),this.set("today",e)}}),TimePickerView=DateTimePickerView.extend({className:"pl-datepicker pl-timepicker form-group"}),StatusBarControl=function(){_.superClass(StatusBarControl,this)};_.inherit(StatusBarControl,Control),_.extend(StatusBarControl.prototype,{ -createControlModel:function(){return new StatusBarModel},createControlView:function(e){return new StatusBarView({model:e})}});var StatusBarModel=ControlModel.extend({defaults:_.defaults({},ControlModel.prototype.defaults,{time:"",date:"",result:null})}),StatusBarView=ControlView.extend({className:"pl-status-bar",events:{"click .signIn":"signInHandler","click .signOut":"signOutHandler","click .status-bar-menu":"openMenuHandler"},template:InfinniUI.Template["controls/application/statusBar/template.tpl.html"],loginTemplate:InfinniUI.Template["controls/application/statusBar/authentication/loginTemplate.tpl.html"],enterTemplate:InfinniUI.Template["controls/application/statusBar/authentication/enterTemplate.tpl.html"],successTemplate:InfinniUI.Template["controls/application/statusBar/authentication/successTemplate.tpl.html"],initialize:function(){var e=this;e.model.set("time",moment().format("HH:mm")),e.model.set("date",moment().format("D MMMM")),window.setInterval(function(){e.model.set("time",moment().format("HH:mm")),e.model.set("date",moment().format("D MMMM")),e.dateRender()},1e4),getUserInfo(this),this.listenTo(this.model,"change:result",this.render)},dateRender:function(){this.$el.find(".time").text(this.model.get("time")),this.$el.find(".date").text(this.model.get("date"))},signInHandler:function(){var e=this;this.$modal||(this.$modal=$(this.loginTemplate({})),this.$modal.appendTo("body")),this.$modal.modal("show"),this.$modal.on("hidden.bs.modal",function(){$(this).find("#password, #userName").val(""),$(this).find("#remember").attr("checked",!1)}),this.$modal.find(".post").on("click",function(){signInInternal(e)})},openMenuHandler:function(){var e=$(".app-area").find(".pl-menu"),t=e.closest(".app-area");e.length&&t.length&&($(t).is(":visible")?t.css({display:"none"}):t.css({position:"absolute",width:"100%",display:"block",overflow:"hidden"}))},signOutHandler:function(){signOut(this)},render:function(){var e,t=this.model.get("result"),n=InfinniUI.config.configName,i=$(this.template({header:n})),o=this;return window.adjustLoginResult(t).then(function(n){e=t?$(o.successTemplate({displayName:n.UserName,activeRole:n.ActiveRole,roles:_.pluck(t.Roles,"DisplayName").join(", ")})):$(o.enterTemplate({})),i.find(".page-header-inner").prepend(e),o.$el.empty().append(i)}),this.$el.find(".calendar").datepicker({todayHighlight:!0,language:"ru"}),this.$el.find(".dropdown-toggle").on("click.bs.dropdown",function(){var e=$(this).data("clicks");e?$(this).parent(".dropdown").off("hide.bs.dropdown"):$(this).parent(".dropdown").on("hide.bs.dropdown",function(){return!1}),$(this).data("clicks",!e)}),this}});jQuery(document).ready(function(){InfinniUI.config.disableGetCurrentUser!==!1&&(InfinniUI.user={onReadyDeferred:$.Deferred(),onReady:function(e){this.onReadyDeferred.done(e)}},refreshUserInfo())}),jQuery(document).ready(function(){InfinniUI.config.disableSignInExternalForm!==!1&&getSignInExternalForm()}),_.extend(AuthenticationProvider.prototype,{handlers:{onActiveRoleChanged:$.Callbacks(),onSignInInternal:$.Callbacks(),onSignOut:$.Callbacks()},getCurrentUser:function(e,t){this.sendPostRequestForServiceResult("/Auth/GetCurrentUser",{},e,t)},changePassword:function(e,t,n,i){var o={OldPassword:e,NewPassword:t};this.sendPostRequestForServiceResult("/Auth/ChangePassword",o,n,i)},changeProfile:function(e,t,n,i){var o={DisplayName:e,Description:t};this.sendPostRequestForServiceResult("/Auth/ChangeProfile",o,n,i)},changeActiveRole:function(e,t,n){var i={ActiveRole:e};this.sendPostRequestForServiceResult("/Auth/ChangeActiveRole",i,function(){var n=_.toArray(arguments);n.push(e),t&&t.apply(this,n),this.handlers.onActiveRoleChanged.fire.apply(this.handlers.onActiveRoleChanged,n)},n)},signInInternal:function(e,t,n,i,o){var r={UserName:e,Password:t,Remember:n};this.sendPostRequestForServiceResult("/Auth/SignInInternal",r,i,o)},getSignInExternalForm:function(e,t,n,i){this.getExternalLoginForm("/Auth/SignInExternal",e,t,n,i)},getLinkExternalLoginForm:function(e,t,n,i){this.getExternalLoginForm("/Auth/LinkExternalLogin",e,t,n,i)},unlinkExternalLogin:function(e,t,n,i){var o={Provider:e,ProviderKey:t};this.sendPostRequest("/Auth/UnlinkExternalLogin",o,n,i)},signOut:function(e,t){this.sendPostRequestForServiceResult("/Auth/SignOut",null,function(){InfinniUI.user.onReadyDeferred=$.Deferred(),InfinniUI.user.onReadyDeferred.resolve(null);var t=_.toArray(arguments);e&&e.apply(this,t),this.handlers.onSignOut.fire.apply(this.handlers.onSignOut,t)}.bind(this),t)},getExternalLoginForm:function(e,t,n,i,o){var r=this.baseAddress+e;this.sendPostRequest("/Auth/GetExternalProviders",{},function(e){var o=$(document.createElement("form"));o.attr("method","POST"),o.attr("action",r);var a=$(document.createElement("input"));a.attr("type","hidden"),a.attr("name","SuccessUrl"),a.attr("value",t),o.append(a);var l=$(document.createElement("input"));if(l.attr("type","hidden"),l.attr("name","FailureUrl"),l.attr("value",n),o.append(l),null!==e&&void 0!==e)for(var s=0;s0},function(){"Right"==t?e.addClass("pull-right"):e.removeClass("pull-right")})}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.Button.menuItem",MenuItemButtonView),_.inherit(ButtonEditControl,TextBoxControl),_.extend(ButtonEditControl.prototype,{createControlModel:function(){return new ButtonEditModel},createControlView:function(e){return new ButtonEditView({model:e})},onButtonClick:function(e){this.controlView.on("buttonClick",e)}});var ButtonEditModel=TextBoxModel.extend({defaults:_.defaults({showClear:!0,readOnly:!0},TextBoxModel.prototype.defaults),initialize:function(){TextBoxModel.prototype.initialize.apply(this,arguments)},clearValue:function(){var e=this.get("enabled");e&&this.set("value",null)}}),ButtonEditView=TextBoxView.extend({template:{oneline:InfinniUI.Template["controls/buttonEdit/template/textBoxInput.tpl.html"],multiline:InfinniUI.Template["controls/buttonEdit/template/textBoxArea.tpl.html"]},className:"pl-button-edit form-group",UI:_.extend({},TextBoxView.prototype.UI,{iconAction:".pl-button-edit-button__icon_action",buttonClear:".pl-button-edit-button_clear",buttons:".pl-button-edit-button"}),events:_.extend({},TextBoxView.prototype.events,{"click .pl-button-edit-button_action":"onClickButtonHandler","click .pl-button-edit-button_clear":"onClickClearHandler"}),initHandlersForProperties:function(){TextBoxView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:icon",this.updateIcon),this.listenTo(this.model,"change:showClear",this.updateShowClear),this.listenTo(this.model,"change:readOnly",this.updateReadOnly)},updateProperties:function(){TextBoxView.prototype.updateProperties.call(this),this.updateIcon(),this.updateShowClear(),this.updateReadOnly()},updateIcon:function(){var e=this.model.get("icon");this.switchClass("fa",e,this.ui.iconAction)},updateShowClear:function(){var e=this.model.get("showClear"),t=this.model.get("value");this.ui.buttonClear.toggleClass("hidden",!e||_.isEmpty(t))},updateReadOnly:function(){var e=this.model.get("readOnly");this.ui.control.prop("readonly",e)},updateEnabled:function(){var e=this.model.get("enabled");TextBoxView.prototype.updateEnabled.call(this),this.ui.buttons.toggleClass("pl-button-edit-button_disabled",!e)},updateValue:function(){TextBoxView.prototype.updateValue.call(this),this.updateShowClear()},onClickButtonHandler:function(e){var t=this.model.get("enabled");t&&this.trigger("buttonClick",e)},onClickClearHandler:function(e){this.model.clearValue()}}),ComboBoxDropdownView=Backbone.View.extend({className:"pl-dropdown-container",events:{"click .backdrop":"onClickBackdropHandler","keyup .pl-combobox-filter-text":"onKeyUpHandler","keydown .pl-combobox-filter-text":"onFilterKeyDownHandler"},UI:{items:".pl-combobox-items",filter:".pl-combobox-filter",text:".pl-combobox-filter-text",noItems:".pl-combobox-items-empty",search:".pl-combobox-items-empty > span"},initialize:function(){var e=null!=this.model.get("groupValueSelector");e?this.strategy=new ComboBoxGroupViewStrategy(this):this.strategy=new ComboBoxPlainViewStrategy(this),this.listenTo(this.model,"change:dropdown",this.onChangeDropdownHandler),this.listenTo(this.model,"change:autocompleteValue",this.onChangeSearchHandler),this.listenTo(this.model,"change:autocomplete",this.updateAutocomplete),this.listenTo(this.model,"change:selectedItem",this.onChangeSelectedItem),this.listenTo(this.strategy,"click",this.onClickItemHandler),this.listenTo(this.strategy,"mouseenter",this.onMouseEnterItemHandler),this.model.onValueChanged(this.onChangeValueHandler.bind(this));var t=this.model.get("items"),n=this;t.onChange(function(){n.renderItems()})},updateProperties:function(){this.updateAutocomplete()},render:function(){var e=this.strategy.getTemplate();return this.$el.html(e({multiSelect:this.model.get("multiSelect")})),this.bindUIElements(),this.updateProperties(),this.renderItems(),this.$el},renderItems:function(){this.$el.hide();var e=this.strategy.renderItems();this.$items=e;var t=this.model.get("items"),n=t&&0==t.length;this.ui.noItems.toggleClass("hidden",!n),this.markSelectedItems(),this.markCheckedItems(),this.trigger("itemsRendered2"),this.$el.show()},setItemsContent:function(e){var t=this.ui.items;t.empty(),t.append(e)},close:function(){this.model.set("dropdown",!1)},setSearchFocus:function(){this.ui.text.focus()},onClickBackdropHandler:function(){this.close()},onChangeValueHandler:function(){this.markCheckedItems()},markSelectedItems:function(){var e=this.model;if(Array.isArray(this.$items)){var t=(this.ui.items,this.$items),n=e.getSelectedItem();t.forEach(function(e){var t=n===e.data("pl-data-item");e.toggleClass("pl-combobox-selected",t)}),this.ensureVisibleSelectedItem()}},ensureVisibleSelectedItem:function(){function e(e,t){var n,i=e.scrollTop(),o=t.position().top,r=t.outerHeight(),a=e.innerHeight();o+r>a?n=i+o+r-a:o<0&&(n=i+o),"undefined"!=typeof n&&e.scrollTop(n)}var t=this.model;if(Array.isArray(this.$items)){var n=this.ui.items,i=this.$items,o=t.getSelectedItem();i.some(function(t){var i=o===t.data("pl-data-item");return i&&e(n,t),i})}},markCheckedItems:function(){var e=this.model,t=e.getValue();if(Array.isArray(this.$items)){var n=this.$items,i=!!e.get("multiSelect"),o=[];o=i&&Array.isArray(t)?t.map(function(t){return e.itemByValue(t)}):[e.itemByValue(t)],n.forEach(function(e){var t=o.indexOf(e.data("pl-data-item"))!==-1;e.toggleClass("pl-combobox-checked",t)})}},onChangeDropdownHandler:function(e,t){t||this.remove()},updateAutocomplete:function(){var e=this.model.get("autocomplete");this.ui.filter.toggleClass("hidden",!e)},onMouseEnterItemHandler:function(e){this.model.setSelectedItem(e)},onClickItemHandler:function(e){var t=!this.model.isDisabledItem(e);t&&(this.model.toggleItem(e),this.close())},onKeyUpHandler:function(e){var t=this.ui.text.val();this.trigger("search",t)},onKeyDownHandler:function(e){this.model;e.preventDefault(),this.onFilterKeyDownHandler(e)},onFilterKeyDownHandler:function(e){var t=this.model;switch(e.which){case 36:t.selectFirstItem();break;case 35:t.selectLastItem();break;case 38:t.selectPrevItem();break;case 40:t.selectNextItem();break;case 13:this.onClickItemHandler(t.getSelectedItem());break;case 9:this.close();break;case 27:this.close(),e.stopPropagation()}},onChangeSearchHandler:function(e,t){this.ui.search.text(t)},onChangeSelectedItem:function(e,t){this.markSelectedItems()},updatePosition:function(e){var t=this.getDropdownDirection(e);this.setPositionFor(e,t)},setPositionFor:function(e,t){clearInterval(this._intervalId),this.applyStyle(e,t),this._intervalId=setInterval(this.applyStyle.bind(this,e,t),100)},remove:function(){return clearInterval(this._intervalId),Backbone.View.prototype.remove.apply(this,arguments)},getDropdownDirection:function(e){var t=$(window).height(),n=e.getBoundingClientRect(),i=this.$el.height(),o="bottom";return n.bottom+i+30>t&&n.bottom>t/2&&(o="top"),o},applyStyle:function(e,t){var n=e.getBoundingClientRect(),i={left:window.pageXOffset+n.left,width:Math.round(n.width)-1};"bottom"===t?i.top=window.pageYOffset+n.bottom:i.top=window.pageYOffset+n.top-this.$el.height(),this.$el.css(i)}});_.extend(ComboBoxDropdownView.prototype,bindUIElementsMixin),ComboBoxBaseViewStrategy.prototype.getModelAttribute=function(e){var t=this.dropdownView.model;return t.get(e)},ComboBoxBaseViewStrategy.prototype.isEnabledItem=function(e){return!this.dropdownView.model.isDisabledItem(e)},ComboBoxBaseViewStrategy.prototype.renderItems=function(){throw new Error("Method renderItems not implemented")},ComboBoxBaseViewStrategy.prototype.getTemplate=function(){},ComboBoxBaseViewStrategy.prototype._renderItems=function(e){var t,n=this.getModelAttribute("items"),i=this.getModelAttribute("itemTemplate");return t=e.map(function(e){var t=i(void 0,{value:e,index:n.indexOf(e)}),o=t.render();return"undefined"!=typeof e&&o.data("pl-data-item",e),this.addOnClickEventListener(o,e),this.addOnHoverEventListener(o,e),t.setEnabled(this.isEnabledItem(e)),o},this)},ComboBoxBaseViewStrategy.prototype.addOnClickEventListener=function(e){var t=e[0],n=Array.prototype.slice.call(arguments,1),i=this.trigger.bind(this,"click");t.addEventListener("click",function(){i.apply(this,n)})},ComboBoxBaseViewStrategy.prototype.addOnHoverEventListener=function(e){var t=(e[0],Array.prototype.slice.call(arguments,1)),n=this.trigger.bind(this,"mouseenter");e.on("mouseenter",function(){n.apply(this,t)})},_.extend(ComboBoxBaseViewStrategy.prototype,Backbone.Events),ComboBoxGroupViewStrategy.prototype=Object.create(ComboBoxBaseViewStrategy.prototype),ComboBoxGroupViewStrategy.prototype.constructor=ComboBoxGroupViewStrategy,ComboBoxGroupViewStrategy.prototype.template=InfinniUI.Template["controls/comboBox/dropdown/template/group/template.tpl.html"],ComboBoxGroupViewStrategy.prototype.renderItems=function(){var e,t=this.getModelAttribute("items"),n=this.getModelAttribute("groupValueSelector"),i={};return t.forEach(function(e,t){var o=n(void 0,{value:e,index:t});o in i||(i[o]=[]),i[o].push(e)}),e=this.renderGroups(i)},ComboBoxGroupViewStrategy.prototype.renderGroups=function(e){var t,n=this.getModelAttribute("groupItemTemplate"),i=this.getModelAttribute("items"),o=[],r=[];for(var a in e){var l=e[a],s=n(void 0,{index:i.indexOf(l[0]),item:l[0]}),t=this._renderItems(l),u=new ComboBoxGroupView({header:s.render(),items:t});Array.prototype.push.apply(o,t),r.push(u.render())}return this.dropdownView.setItemsContent(r),o},ComboBoxGroupViewStrategy.prototype.getTemplate=function(){return this.template},ComboBoxPlainViewStrategy.prototype=Object.create(ComboBoxBaseViewStrategy.prototype),ComboBoxPlainViewStrategy.prototype.constructor=ComboBoxPlainViewStrategy,ComboBoxPlainViewStrategy.prototype.renderItems=function(){var e=[],t=this.getModelAttribute("items");return t&&(e=this._renderItems(t.toArray())),this.dropdownView.setItemsContent(e),e},ComboBoxPlainViewStrategy.prototype.template=InfinniUI.Template["controls/comboBox/dropdown/template/plain/template.tpl.html"],ComboBoxPlainViewStrategy.prototype.getTemplate=function(){return this.template};var ComboBoxGroupView=Backbone.View.extend({template:InfinniUI.Template["controls/comboBox/dropdown/group/template/template.tpl.html"],UI:{header:".pl-combobox-group__header",items:".pl-combobox-group__items"},initialize:function(e){this.options={header:e.header,items:e.items}},render:function(){var e=this.options;return this.$el.html(this.template()),this.bindUIElements(),this.ui.header.append(e.header),this.ui.items.append(e.items),this.$el}});_.extend(ComboBoxGroupView.prototype,bindUIElementsMixin);var ComboBoxValueModel=Backbone.Model.extend({}),ComboBoxValue=Backbone.View.extend({template:InfinniUI.Template["controls/comboBox/values/template/value.tpl.html"],tagName:"li",className:"pl-combobox-value",events:{"click .pl-combobox-value-remove":"onClickRemoveHandler"},UI:{item:".pl-combobox-value-item"},initialize:function(e){this.model=new ComboBoxValueModel(e)},render:function(){this.$el.html(this.template()),this.bindUIElements();var e=this.model.get("$value");return this.ui.item.append(e),this.$el},onClickRemoveHandler:function(){var e=this.model.get("value");this.trigger("remove",e)}});_.extend(ComboBoxValue.prototype,bindUIElementsMixin);var ComboBoxValuesModel=Backbone.Model.extend({defaults:{enabled:!0},initialize:function(){this.items=[]}}),ComboBoxValues=Backbone.View.extend({tagName:"ul",className:"pl-combobox-values",template:InfinniUI.Template["controls/comboBox/values/template/values.tpl.html"],events:{"keypress .pl-combobox-search-text":"onKeyPressHandler","keydown .pl-combobox-search-text":"onKeyDownHandler","keyup .pl-combobox-search-text":"onKeyUpHandler",click:"onClickHandler"},UI:{search:".pl-combobox-search",text:".pl-combobox-search-text"},initialize:function(e){this.model=new ComboBoxValuesModel(e)},render:function(){this.$el.empty(),this.$el.html(this.template()),this.bindUIElements();var e=this.model,t=e.get("items").map(function(e){var t=new ComboBoxValue({$value:e.$value,value:e.value});return this.listenTo(t,"remove",this.onRemoveValueHandler),t.render()},this);return this.ui.search.before(t),this.$el},KeyCode:{enter:13,backspace:8,left:37,right:39,home:36,end:35,tab:9},setFocus:function(){this.ui.text.focus()},onKeyPressHandler:function(e){var t=e.which;t===this.KeyCode.enter,console.log("onKeyPressHandler",e.which,this.ui.text.val())},onKeyDownHandler:function(e){var t=e.which;t===this.KeyCode.left,console.log("onKeyDownHandler",e.which,this.ui.text.val())},onKeyUpHandler:function(e){var t=this.ui.text.val();this.trigger("search",t)},onRemoveValueHandler:function(e){this.trigger("remove",e)},onClickHandler:function(e){this.setFocus()}});_.extend(ComboBoxValues.prototype,bindUIElementsMixin),_.inherit(DataGridControl,ListEditorBaseControl),_.extend(DataGridControl.prototype,{createControlModel:function(){return new DataGridModel},createControlView:function(e){return new DataGridView({model:e})},onCheckAllChanged:function(e){this.controlModel.onCheckAllChanged(e)},setEnabled:function(e){this.controlModel.set("enabled",e)},onRowClick:function(e){this.controlView.$el.on("click",".pl-datagrid__body .pl-datagrid-row",e)},onRowDoubleClick:function(e){this.controlView.$el.on("dblclick",".pl-datagrid__body .pl-datagrid-row",e)}});var DataGridModel=ListEditorBaseModel.extend({defaults:_.defaults({showSelectors:!0,checkAllVisible:!1,checkAll:!1,focusable:!1,sortedColumn:null},ListEditorBaseModel.prototype.defaults),initialize:function(){ListEditorBaseModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments)),this.initColumns()},toggleCheckAll:function(){this.set("checkAll",!this.get("checkAll"))},onCheckAllChanged:function(e){this.on("change:checkAll",function(t,n){e.call(null,{value:n})})},initColumns:function(){this.set("columns",new Collection)}}),DataGridView=ListEditorBaseView.extend({template:{grid:InfinniUI.Template["controls/dataGrid/template/dataGrid.tpl.html"],gridStretched:InfinniUI.Template["controls/dataGrid/template/dataGridStretched.tpl.html"],headerCell:InfinniUI.Template["controls/dataGrid/template/headerCell.tpl.html"],sizeCell:InfinniUI.Template["controls/dataGrid/template/sizeCell.tpl.html"]},className:"pl-datagrid",events:_.extend({},ListEditorBaseView.prototype.events,{"click .pl-datagrid-toggle_all":"onClickCheckAllHandler","click thead .pl-datagrid-row__cell":"onClickToHeaderCellHandler"}),UI:_.defaults({body:".pl-datagrid__body",head:".pl-datagrid__head",headContainer:".pl-datagrid-container_head",header:".pl-datagrid-row_header",firstRows:".pl-datagrid-row_first",toggleCell:".pl-toggle-cell",checkAll:".pl-datagrid-toggle__button",items:"tbody"},ListEditorBaseView.prototype.UI),initialize:function(e){ListEditorBaseView.prototype.initialize.call(this,e),this.rowElements=new HashMap},initHandlersForProperties:function(){ListEditorBaseView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:showSelectors",this.updateShowSelectors),this.listenTo(this.model,"change:checkAllVisible",this.updateCheckAllVisible),this.listenTo(this.model,"change:checkAll",this.updateCheckAll);var e=this.rowElements;this.model;this.model.get("items").onChange(function(t){"replace"===t.action&&t.oldItems.forEach(function(n,i){e.add(t.newItems[i],e.get(n)),e.remove(n)})})},updateProperties:function(){ListEditorBaseView.prototype.updateProperties.call(this),this.updateShowSelectors(),this.updateCheckAllVisible(),this.updateCheckAll(),this.updateDisabledItem()},updateShowSelectors:function(){var e=this.model.get("showSelectors");this.$el.toggleClass("pl-datagrid_selectors_show",e),this.$el.toggleClass("pl-datagrid_selectors_hide",!e)},updateGrouping:function(){},updateVerticalAlignment:function(){ListEditorBaseView.prototype.updateVerticalAlignment.call(this),this.switchClass("verticalAlignment",this.model.get("verticalAlignment"),this.ui.body,!1)},updateCheckAll:function(){var e=this.model.get("checkAll");this.ui.checkAll.prop("checked",e)},getHorizontalScrollBarWidth:function(){if("undefined"==typeof DataGridView.scrollbarWidth){var e=document.createElement("div"),t=document.body;e.className="modal-scrollbar-measure";var n={position:"absolute",top:"-9999px",width:"50px",height:"50px",overflow:"scroll"};for(var i in n)e.style[i]=n[i];t.appendChild(e),DataGridView.scrollbarWidth=e.offsetWidth-e.clientWidth,t.removeChild(e)}return DataGridView.scrollbarWidth},updateCheckAllVisible:function(){var e=this.model.get("checkAllVisible");this.ui.checkAll.toggleClass("hidden",!e)},updateMultiSelect:function(){ListEditorBaseView.prototype.updateMultiSelect.call(this);var e=this.model.get("multiSelect");this.$el.toggleClass("pl-datagrid_select_multi",e===!0),this.$el.toggleClass("pl-datagrid_select_single",e!==!0)},updateValue:function(){var e=this.model,t=e.get("value"),n=[],i=e.get("items");e.get("multiSelect")||void 0===t||null===t||(t=[t]),Array.isArray(t)&&(n=t.map(function(t){return e.itemIndexByValue(t)}).filter(function(e){return e!==-1})),this.rowElements.forEach(function(e,t){var o=i.indexOf(t),r=n.indexOf(o)!==-1;e.toggle(r)})},updateSelectedItem:function(){var e=this.model,t=e.get("selectedItem");this.rowElements.forEach(function(e,n){e.setSelected(n===t)})},updateDisabledItem:function(){var e,t=this.model,n=t.get("disabledItemCondition");null!=n?this.rowElements.forEach(function(i,o){e=!n(void 0,{value:o}),i.getSelected()===o&&e===!1&&t.set("selectedItem",null),i.setEnabled(e)}):this.rowElements.forEach(function(e,t){e.setEnabled(!0)})},updateEnabled:function(){var e=this.model.get("enabled");e?this.updateDisabledItem():this.disableDataGridItems()},disableDataGridItems:function(){this.model.set("selectedItem",null),this.rowElements.forEach(function(e,t){e.setEnabled(!1)})},render:function(){var e=this;this.prerenderingActions();var t=this.model.get("verticalAlignment"),n="Stretch"===t?this.template.gridStretched:this.template.grid;return this.$el.html(n()),this.bindUIElements(),this.renderHeaders(),this.renderItems(),this.trigger("render"),this.applyColumnWidth(),this.syncBodyAndHead(),this.postrenderingActions(),setTimeout(function(){e.updateProperties()},0),this},applyColumnWidth:function(){var e=this.model.get("columns"),t=!1;this.ui.firstRows.children().each(function(n,i){var o=n%(e.length+1);if(0!==o){var r=e.getByIndex(o-1),a=r&&r.getWidth();a&&($(i).css("width",a),t=!0)}}),this.$el.toggleClass("pl-datagrid_layout_fixed",t)},syncBodyAndHead:function(){var e=this.ui.head;e.css("padding-right",this.getHorizontalScrollBarWidth()+"px"),this.ui.body.off("scroll").on("scroll",this.onScrollBodyHandler.bind(this))},onScrollBodyHandler:function(){this.ui.headContainer.scrollLeft(this.ui.body.scrollLeft())},renderHeaders:function(){var e=this,t=this.model.get("columns"),n=this.template.headerCell,i=[],o=this.template.sizeCell,r=t.toArray().map(function(t){i.push(o());var r=$(n()),a=t.getHeaderTemplate(),l=t.getHeader();r.data("pl-column",t),t.getSortable()&&(r.addClass("sortable"),t.getSortDirection()&&setTimeout(function(){e.setUpColumnSort(t,r,t.getSortDirection(),!1)},0));var s;return a?(s=a(null,{value:l}),r.append(s.render())):r.append(l),r});this.ui.header.append(r),this.ui.firstRows.append(i)},renderItems:function(){var e=this.model,t=e.get("valueSelector"),n=e.get("itemTemplate"),i=e.get("items"),o=this.ui.items,r=this;this.removeRowElements(),i.forEach(function(i,a){setTimeout(function(){var l=n(void 0,{index:a,item:i});l.onBeforeClick(function(){var t=e.get("items"),n=t.getByIndex(a),i=r.rowElements.get(n);i.getEnabled()!==!1&&e.set("selectedItem",n)}),l.onToggle(function(){var n=this.model.get("enabled"),i=e.get("items");n&&e.toggleValue(t(void 0,{value:i.getByIndex(a)}))}),l.childElements=l.control.controlView.childElements,r.addRowElement(i,l);var s=l.render();o.append(s)},0)},this)},updateFocusable:function(){var e=this.model.get("focusable");this.rowElements.values.forEach(function(t){e?t.control.controlView.$el.attr("tabindex",0):t.control.controlView.$el.removeAttr("tabindex")})},addRowElement:function(e,t){this.addChildElement(t),this.rowElements.add(e,t)},removeRowElements:function(){this.removeChildElements(),this.rowElements.clear()},onClickCheckAllHandler:function(){this.model.toggleCheckAll()},onClickToHeaderCellHandler:function(e){var t=$(e.currentTarget),n=t.data("pl-column");n&&n.isSortable()&&(null===n.getSortDirection()?(this.resetSort(),this.setUpColumnSort(n,t,"asc")):"asc"===n.getSortDirection()?(this.resetSort("asc"),this.setUpColumnSort(n,t,"desc")):"desc"===n.getSortDirection()&&(this.resetSort("desc"),this.setUpColumnSort(n,t,"asc")))},setUpColumnSort:function(e,t,n,i){e.setSortDirection(n),this.model.set("sortedColumn",e),e.getIsHeaderTemplateEmpty()?t.addClass("sorted sorted-"+n):t.addClass("sorted headerTemplate-sorted-"+n),i!==!1&&e.trigger("onSort",{sortDirection:n})},resetSort:function(e){if(e){var t=this.$el.find(".sorted");t.removeClass("headerTemplate-sorted-"+e+" sorted-"+e)}else{var t=this.$el.find(".sorted");t.removeClass("sorted headerTemplate-sorted-asc headerTemplate-sorted-desc sorted-asc sorted-desc");var n=this.model.get("sortedColumn");n&&n.setSortDirection(null)}}});_.inherit(DataGridRowControl,Control),_.extend(DataGridRowControl.prototype,{onToggle:function(e){this.controlView.on("toggle",e)},createControlModel:function(){return new DataGridRowModel},createControlView:function(e){return new DataGridRowView({model:e})}});var DataGridRowModel=ControlModel.extend({}),DataGridRowView=ControlView.extend({className:"pl-datagrid-row pl-datagrid-row_data",classNameSelected:"info",tagName:"tr",events:{},template:{singleSelect:InfinniUI.Template["controls/dataGrid/dataGridRow/template/singleSelect.tpl.html"],multiSelect:InfinniUI.Template["controls/dataGrid/dataGridRow/template/multiSelect.tpl.html"],dataCell:InfinniUI.Template["controls/dataGrid/dataGridRow/template/dataCell.tpl.html"]},UI:{toggleCell:".pl-datagrid-row__cell_toggle",toggle:".pl-datagrid-toggle",toggleControl:".pl-datagrid-toggle input"},initialize:function(){ControlView.prototype.initialize.call(this),this.childElements=[],this.on("render",function(){this.ui.toggleCell.on("click",this.onToggleHandler.bind(this))},this)},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:toggle",this.updateToggle),this.listenTo(this.model,"change:selected",this.updateSelected)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),this.updateToggle(),this.updateSelected(),this.updateShowSelectors(); -},updateVerticalAlignment:function(){},render:function(){this.prerenderingActions();var e=this.$el,t=this,n=this.model.get("multiSelect")?"multiSelect":"singleSelect",i=this.template[n];e.html(i()),this.bindUIElements();var o=this.model.get("cellTemplates"),r=this.template.dataCell;return Array.isArray(o)&&o.forEach(function(n,i){var o=$(r()),a=n();o.append(a.render()),e.append(o),t.addChildElement(a)}),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},updateShowSelectors:function(){var e=this.model.get("showSelectors");this.ui.toggleCell.toggleClass("hidden",!e)},updateToggle:function(){var e=this.model.get("toggle");this.ui.toggleControl.prop("checked",!!e)},updateSelected:function(){var e=this.model.get("selected");this.$el.toggleClass(this.classNameSelected,!!e)},updateEnabled:function(){ControlView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");this.ui.toggleControl.attr("disabled",e?null:"disabled")},onToggleHandler:function(e){this.trigger("toggle")},addChildElement:function(e){this.childElements.push(e)},removeChildElements:function(){this.childElements.forEach(function(e){e.remove()}),this.childElements.length=0},remove:function(){this.removeChildElements(),ControlView.prototype.remove.call(this)}}),DataNavigationBaseButtonModel=Backbone.Model.extend({initialize:function(){this.on("change:parent",this.subscribeToParent,this)},subscribeToParent:function(){}}),DataNavigationBaseButton=Backbone.View.extend({tagName:"li",initialize:function(e){Backbone.View.prototype.initialize.call(this,e),this.once("render",function(){this.initHandlersForProperties()},this)},initHandlersForProperties:function(){},updateProperties:function(){},getData:function(){return this.model.toJSON()},setParent:function(e){this.model.set("parent",e),this.subscribeForParent(e)},render:function(){var e=this.template(this.getData());return this.$el.html(e),this.trigger("render"),this.updateProperties(),this},subscribeForParent:function(e){}}),DataNavigationNextButton=DataNavigationBaseButton.extend({template:InfinniUI.Template["controls/dataNavigation/buttons/template/next.tpl.html"],events:{click:"onClickHandler"},initialize:function(e){this.model=new DataNavigationBaseButtonModel,DataNavigationBaseButton.prototype.initialize.call(this,e)},onClickHandler:function(e){this.trigger("command","next")}}),DataNavigationPageButton=DataNavigationBaseButton.extend({template:InfinniUI.Template["controls/dataNavigation/buttons/template/page.tpl.html"],events:{click:"onClickHandler"},initialize:function(e){this.model=new DataNavigationPageButtonModel,DataNavigationBaseButton.prototype.initialize.call(this,e),this.model.set("pageNumber",e.pageNumber)},initHandlersForProperties:function(){DataNavigationBaseButton.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:isCurrent",this.updateIsCurrent)},updateProperties:function(){DataNavigationBaseButton.prototype.updateProperties.call(this),this.updateIsCurrent()},updateIsCurrent:function(){this.$el.toggleClass("active",this.model.get("isCurrent"))},onClickHandler:function(e){this.trigger("command","page",{pageNumber:this.model.get("pageNumber")})}}),DataNavigationPageButtonModel=DataNavigationBaseButtonModel.extend({defaults:{isCurrent:!1},subscribeToParent:function(){DataNavigationBaseButtonModel.prototype.subscribeToParent.call(this);var e=this.get("parent");this.listenTo(e.model,"change:pageNumber",function(){this.updateIsCurrent()}),this.updateIsCurrent()},updateIsCurrent:function(){var e=this.get("parent"),t=e.model.get("pageNumber")===this.get("pageNumber");this.set("isCurrent",t)}}),DataNavigationPrevButton=DataNavigationBaseButton.extend({template:InfinniUI.Template["controls/dataNavigation/buttons/template/prev.tpl.html"],events:{click:"onClickHandler"},initialize:function(e){this.model=new DataNavigationBaseButtonModel,DataNavigationBaseButton.prototype.initialize.call(this,e)},onClickHandler:function(e){this.trigger("command","prev")}});DataNavigationButtonFactory.prototype.buttons={prev:DataNavigationPrevButton,page:DataNavigationPageButton,next:DataNavigationNextButton},DataNavigationButtonFactory.prototype.createButton=function(e,t){var n=this.buttons[e];if("function"!=typeof n)return void console.error("Wrong button type: "+e);var i=new n(t);return i.setParent(this._dataNavigation),i},_.inherit(DataNavigationControl,Control),_.extend(DataNavigationControl.prototype,{createControlModel:function(){return new DataNavigationModel},createControlView:function(e){return new DataNavigationView({model:e})},onPageNumberChanged:function(e){this.controlModel.onPageNumberChanged(e)},onPageSizeChanged:function(e){this.controlModel.onPageSizeChanged(e)}});var DataNavigationModel=ControlModel.extend({defaults:_.defaults({pageNumber:0,pageStart:0,_buttonsCount:5,_buttonsTemplate:["prev","page","next"],pageCount:null,isDataReady:!1},ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.set("availablePageSizes",new Collection),this.on("change:pageNumber",this.updatePageStart,this),this.on("change:pageSize",this.updatePageSize,this)},updatePageStart:function(){var e=this.get("pageNumber"),t=this.get("pageStart"),n=this.get("_buttonsCount");e+1>=t+n?t+=Math.floor(n/2):e===t?t=Math.max(0,t-Math.floor(n/2)):e+10&&this.set("pageNumber",e-1)},onPageNumberChanged:function(e){this.on("change:pageNumber",function(t,n){e.call(null,{value:n})})},onPageSizeChanged:function(e){this.on("change:pageSize",function(t,n){e.call(null,{value:n})})}}),DataNavigationView=ControlView.extend({template:InfinniUI.Template["controls/dataNavigation/template/dataNavigation.tpl.html"],className:"pl-data-navigation",UI:{buttons:"ul",sizes:".pl-page-size"},initialize:function(e){ControlView.prototype.initialize.call(this,e),this._childViews=[],this.buttonsFactory=new DataNavigationButtonFactory(this),this._pageSizes=new DataNavigationPageSizes,this._pageSizes.setParent(this)},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:pageStart",this.updateButtons),this.listenTo(this.model,"change:pageCount",this.updateButtons),this.listenTo(this.model,"change:isDataReady",this.updateButtons)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),this.updateButtons()},render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.updateProperties(),this.trigger("render"),this.renderPageSizes(),this.postrenderingActions(),this},renderPageSizes:function(){this.ui.sizes.append(this._pageSizes.render().$el)},renderButtons:function(){var e,t,n=this.model.get("_buttonsTemplate"),i=this.model.get("_buttonsCount"),o=this.model.get("pageCount"),r=(this.model.get("pageNumber"),this.model.get("pageStart")),a=this.model.get("isDataReady");if(this._removeChildViews(),a){var l=this.buttonsFactory;this.model;e=n.reduce(function(e,t){if("page"===t)for(var n=0;n=o&&(t=r+i-o+1,0==o&&(t+=1),e.splice(e.length-t,100));var s=e.map(function(e){return this.listenTo(e,"command",this.onCommandHandler),this._appendChildView(e),e.render().$el},this);this.ui.buttons.append(s)}},updateButtons:function(){this.renderButtons()},onCommandHandler:function(e,t){switch(e){case"prev":this.model.prevPage();break;case"next":this.model.nextPage();break;case"page":this.model.set("pageNumber",t.pageNumber)}},_removeChildViews:function(){this._childViews.forEach(function(e){this.stopListening(e),e.remove()},this),this._childViews.length=0},_appendChildView:function(e){this._childViews.push(e)}}),DataNavigationPageSizes=Backbone.View.extend({className:"btn-group",template:InfinniUI.Template["controls/dataNavigation/pageSizes/template/pageSizes.tpl.html"],events:{"click button":"onClickButtonHandler"},setParent:function(e){this.model=e.model;var t=this.model.get("availablePageSizes");t.onChange(this.onAvailablePageSizesChanged.bind(this)),this.model.on("change:pageSize",this.renderButtons,this)},render:function(){return this.renderButtons(),this},renderButtons:function(){var e=this.model.get("availablePageSizes"),t=this.model.get("pageSize"),n=e.toArray().map(function(e){return this.template({size:e,active:t===e})},this);this.$el.html(n)},onAvailablePageSizesChanged:function(){this.renderButtons()},onClickButtonHandler:function(e){var t=$(e.target),n=parseInt(t.attr("data-size"),10);this.model.set("pageSize",n)}}),CommonLabelView=ControlView.extend(_.extend({},editorBaseViewMixin,{className:"pl-label",template:InfinniUI.Template["controls/label/commonView/template/label.tpl.html"],UI:_.extend({},editorBaseViewMixin.UI,{control:".label-control"}),initialize:function(){ControlView.prototype.initialize.apply(this)},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),editorBaseViewMixin.initHandlersForProperties.call(this),this.listenTo(this.model,"change:displayFormat",this.updateDisplayFormat),this.listenTo(this.model,"change:textWrapping",this.updateTextWrapping),this.listenTo(this.model,"change:textTrimming",this.updateTextTrimming)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),editorBaseViewMixin.updateProperties.call(this),this.updateDisplayFormat(),this.updateTextWrapping(),this.updateTextTrimming()},updateFocusable:function(){var e=this.model.get("focusable");e?this.ui.control.attr("tabindex",0):this.ui.control.removeAttr("tabindex")},updateValue:function(){var e=this.model.get("escapeHtml"),t=e?"text":"html",n=this.getLabelText(),i=this.getLabelElement();i[t](n);var o=String(n);i.attr("title",o.replace(/<\/?[^>]+>/g,""))},updateDisplayFormat:function(){this.updateValue()},updateTextWrapping:function(){var e=this.model.get("textWrapping");this.getLabelElement().toggleClass("pl-text-wrapping",e)},updateTextTrimming:function(){var e=this.model.get("textTrimming");this.getLabelElement().toggleClass("pl-text-trimming",e)},updateText:function(){this.updateValue()},getData:function(){return _.extend({},ControlView.prototype.getData.call(this),editorBaseViewMixin.getData.call(this),{text:this.getLabelText()})},render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},getLabelText:function(){var e,t=this.model,n=t.get("value"),i=t.get("displayFormat");return"undefined"!=typeof n&&null!==n?e="function"==typeof i?i(null,{value:n}):n:(e=this.model.get("text"),"undefined"!=typeof e&&null!=e||(e="")),e},getLabelElement:function(){return this.ui.control}}));InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.Label.common",CommonLabelView);var LabelControl=function(e){_.superClass(LabelControl,this,e),this.initialize_editorBaseControl()};_.inherit(LabelControl,Control),_.extend(LabelControl.prototype,{createControlModel:function(){return new LabelModel},createControlView:function(e,t){t&&t in window.InfinniUI.viewModes.Label||(t="simple");var n=window.InfinniUI.viewModes.Label[t];return new n({model:e})},getDisplayValue:function(){return this.controlView.getLabelText()}},editorBaseControlMixin);var LabelModel=ControlModel.extend(_.extend({defaults:_.defaults({horizontalTextAlignment:"Left",verticalAlignment:"Top",textWrapping:!0,textTrimming:!0,escapeHtml:!0,focusable:!1},ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.initialize_editorBaseModel()}},editorBaseModelMixin)),SimpleLabelView=CommonLabelView.extend({tagName:"span",template:function(){return""},UI:_.extend({},editorBaseViewMixin.UI,{}),updateFocusable:function(){var e=this.model.get("focusable");e?this.$el.attr("tabindex",0):this.$el.removeAttr("tabindex")},getLabelElement:function(){return this.$el}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.Label.simple",SimpleLabelView);var BaseListBoxView=ListEditorBaseView.extend({template:{plain:InfinniUI.Template["controls/listBox/baseView/template/listBox.tpl.html"],grouped:InfinniUI.Template["controls/listBox/baseView/template/listBoxGrouped.tpl.html"]},className:"pl-listbox",events:{"change .pl-listbox-input":"onChangeHandler"},UI:_.defaults({items:".pl-listbox-i",checkingInputs:".pl-listbox-input input"},ListEditorBaseView.prototype.UI),initialize:function(e){ListEditorBaseView.prototype.initialize.call(this,e)},updateGrouping:function(){var e=null!=this.model.get("groupValueSelector");e?this.strategy=new ListBoxViewGroupStrategy(this):this.strategy=new ListBoxViewPlainStrategy(this)},updateValue:function(){this.ui.items.removeClass("pl-listbox-i-chosen"),this.ui.checkingInputs.prop("checked",!1);var e,t,n=this.model.get("value");if(this.isMultiselect()||void 0===n||null===n||(n=[n]),$.isArray(n))for(var i=0,o=n.length;i0&&(n=i.valueByItem(t.data("pl-data-item"))),this.model.set("value",n)},updateDisabledItem:function(){var e=this.model,t=e.get("disabledItemCondition");this.ui.items.removeClass("pl-disabled-list-item"),this.ui.checkingInputs.attr("disabled",null),null!=t&&this.ui.items.each(function(e,n){var i=$(n),o=i.data("pl-data-item"),r=t(void 0,{value:o});r&&(i.hasClass("pl-listbox-i-selected")&&this.model.set("selectedItem",null),i.toggleClass("pl-disabled-list-item",!0),i.find("input").attr("disabled","disabled"),i.find("button").attr("disabled","disabled"))})},disableAll:function(){this.ui.items.addClass("pl-disabled-list-item")},_getElementByItem:function(e){var t=_.find(this.ui.items,function(t){return $(t).data("pl-data-item")==e});return $(t)}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.ListBox.base",BaseListBoxView),_.extend(ListBoxViewGroupStrategy.prototype,{prepareItemsForRendering:function(){var e=this.listbox.getItems(),t="listbox-"+guid(),n={isMultiselect:this.listbox.isMultiselect(),focusable:this.listbox.isFocusable(),inputName:t,groups:[]},i={},o=this.listbox.getGroupValueSelector();e.forEach(function(e,t){var n=o(void 0,{value:e});n in i||(i[n]=[]),i[n].push({index:t,item:e})});for(var r in i)n.groups.push({items:i[r]});return n},getTemplate:function(){return this.listbox.template.grouped},appendItemsContent:function(e){var t,n,i,o,r,a=this.listbox.$el,l=this.listbox.getItemTemplate(),s=this.listbox.getGroupItemTemplate(),u=e.groups,d=this.listbox;a.find(".pl-listbox-group-i").each(function(e,a){r=u[e],i=s(void 0,{index:r.items[0].index,item:r}),d.addChildElement(i),o=$(a),o.find(".pl-listbox-group-title").append(i.render()),o.find(".pl-listbox-body").each(function(e,i){t=r.items[e].item,n=l(void 0,{index:r.items[e].index,item:t}),d.addChildElement(n),$(i).append(n.render()),$(i).parent().data("pl-data-item",t)})})}}),_.extend(ListBoxViewPlainStrategy.prototype,{prepareItemsForRendering:function(){var e=this.listbox.getItems(),t="listbox-"+guid(),n={isMultiselect:this.listbox.isMultiselect(),focusable:this.listbox.isFocusable(),inputName:t,items:e.toArray()};return n},getTemplate:function(){return this.listbox.template.plain},appendItemsContent:function(e){var t,n,i=this.listbox.$el,o=this.listbox.getItemTemplate(),r=e.items,a=this.listbox;i.find(".pl-listbox-body").each(function(e,i){n=$(i),t=o(void 0,{index:e,item:r[e]}),a.addChildElement(t),n.append(t.render()),n.parent().data("pl-data-item",r[e])})}}),_.inherit(ListBoxControl,ListEditorBaseControl),_.extend(ListBoxControl.prototype,{createControlModel:function(){return new ListBoxModel},createControlView:function(e,t){(!t||!t in window.InfinniUI.viewModes.ListBox)&&(t="common");var n=window.InfinniUI.viewModes.ListBox[t];return new n({model:e})},updateDisabledItem:function(){this.controlView.updateDisabledItem()},disableAll:function(){this.controlView.disableAll()}});var ListBoxModel=ListEditorBaseModel.extend({initialize:function(){ListEditorBaseModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),CheckingListBoxView=BaseListBoxView.extend({className:"pl-listbox",template:{plain:InfinniUI.Template["controls/listBox/checkingView/template/listBox.tpl.html"],grouped:InfinniUI.Template["controls/listBox/checkingView/template/listBoxGrouped.tpl.html"]},events:_.extend({},BaseListBoxView.prototype.events),initialize:function(e){BaseListBoxView.prototype.initialize.call(this,e),this.initDomHandlers()},updateEnabled:function(){ListEditorBaseView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");this.ui.checkingInputs.attr("disabled",!e)},initDomHandlers:function(){var e=this.$el,t=this;e.get(0).addEventListener("click",function(n){n=$.event.fix(n);var i,o,r,a=$(n.target);if(t.model.get("enabled")){for(;a.get(0)!=e.get(0);)a.hasClass("pl-listbox-i")&&(i=a),a=a.parent();i&&i.length>0&&(o=i.data("pl-data-item"),r=t.model.isDisabledItem(o),r||t.model.toggleValue(o),t.model.set("selectedItem",o))}},!0)}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.ListBox.checking",CheckingListBoxView);var CommonListBoxView=BaseListBoxView.extend({className:"pl-listbox pl-listbox-common-mode",events:_.extend({},BaseListBoxView.prototype.events),initialize:function(e){BaseListBoxView.prototype.initialize.call(this,e),this.initDomHandlers()},initDomHandlers:function(){var e=this.$el,t=this;e.get(0).addEventListener("click",function(n){n=$.event.fix(n);for(var i,o,r,a=$(n.target);a.get(0)!=e.get(0);)a.hasClass("pl-listbox-i")&&(i=a),a=a.parent();i.length>0&&(o=i.data("pl-data-item"),r=t.model.isDisabledItem(o),r||t.model.toggleValue(o),t.model.set("selectedItem",o))},!0)}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.ListBox.common",CommonListBoxView);var CommonPopupButtonView=ContainerView.extend({className:"pl-popup-button",template:InfinniUI.Template["controls/popupButton/commonView/template/popupButton.tpl.html"],dropdownTemplate:InfinniUI.Template["controls/popupButton/commonView/template/popupButton.dropdown.tpl.html"],events:{click:"onClickHandler"},UI:{button:".pl-popup-button__button",grip:".pl-popup-button__grip"},updateProperties:function(){ContainerView.prototype.updateProperties.call(this),this.updateContent()},updateContent:CommonButtonView.prototype.updateContent,updateText:CommonButtonView.prototype.updateText,getButtonElement:function(){return this.ui.button},render:function(){this.prerenderingActions();var e=this.model.get("items").toArray(),t=this.template;return this.removeChildElements(),this.$el.html(t({items:e})),this.bindUIElements(),this.$dropdown=this.renderDropdown(),this.$dropdown.on("click",this.close.bind(this)),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderDropdown:function(){var e=this.dropdownTemplate,t=this.model.get("items").toArray(),n=$(e({items:t}));return this.appendItemsContent(n,t),n},appendItemsContent:function(e,t){var n,i,o=this,r=this.model.get("itemTemplate");e.find(".pl-popup-button__item").each(function(e,a){i=$(a),n=r(void 0,{index:e,item:t[e]}),o.addChildElement(n),i.append(n.render())})},open:function(){$("body").append(this.$dropdown),this.$dropdown.addClass("open"),this.alignDropdown();this.$dropdown.add(this.ui.grip)},close:function(){this.$dropdown.removeClass("open"),this.$dropdown.detach()},alignDropdown:function(){var e=this.$el.offset(),t=this.$el.height(),n=this.$el.width(),i=this.$dropdown.find(".pl-popup-button__items")[0],o=i.offsetHeight,r=i.offsetWidth,a=e.left,l=e.top+t;e.left+r>=window.innerWidth&&(a+=n-r),l+o>=window.innerHeight&&(l-=t+o+2),this.$dropdown.offset({top:l,left:a})},toggle:function(){this.$dropdown.hasClass("open")?this.close():this.open()},onClickHandler:function(){this.toggle()},updateGrouping:function(){}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.PopupButton.common",CommonPopupButtonView),_.inherit(PopupButtonControl,ContainerControl),_.extend(PopupButtonControl.prototype,{createControlModel:function(){return new PopupButtonModel},createControlView:function(e,t){(!t||!t in window.InfinniUI.viewModes.PopupButton)&&(t="common");var n=window.InfinniUI.viewModes.PopupButton[t];return new n({model:e})}},buttonControlMixin);var PopupButtonModel=ContainerModel.extend({}),ForMenuPopupButtonView=CommonPopupButtonView.extend({tagName:"a",className:"pl-popup-button",attributes:{href:"javascript:;"},template:InfinniUI.Template["controls/popupButton/forMenuView/template/popupButton.tpl.html"],dropdownTemplate:InfinniUI.Template["controls/popupButton/commonView/template/popupButton.dropdown.tpl.html"],events:{click:"onClickGripHandler"},UI:{button:".pl-popup-button__button",grip:".pl-popup-button__grip"},updateProperties:function(){ContainerView.prototype.updateProperties.call(this),this.updateContent()},updateContent:CommonButtonView.prototype.updateContent,updateText:CommonButtonView.prototype.updateText,updateHorizontalAlignment:function(){var e,t=this.model.get("horizontalAlignment"),n=this;this.whenReady(function(){return e=n.$el.parent().parent(),e.length>0},function(){"Right"==t?e.addClass("pull-right"):e.removeClass("pull-right")})},getButtonElement:function(){return this.ui.button},render:function(){this.prerenderingActions();var e=this.model.get("items").toArray(),t=this.template;return this.removeChildElements(),this.$el.html(t({items:e})),this.bindUIElements(),this.$dropdown=this.renderDropdown(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderDropdown:function(){var e=this.dropdownTemplate,t=this.model.get("items").toArray(),n=$(e({items:t}));return this.appendItemsContent(n,t),n.on("click",function(){this.close()}.bind(this)),n},appendItemsContent:function(e,t){var n,i,o=this,r=this.model.get("itemTemplate");e.find(".pl-popup-button__item").each(function(e,a){i=$(a),n=r(void 0,{index:e,item:t[e]}),o.addChildElement(n),i.append(n.render())})},open:function(){var e=this,t=this.$el.parent();$("body").append(this.$dropdown),this.$dropdown.addClass("open"),t.addClass("open"),this.alignDropdown();var n=this.$dropdown.add(this.$el);new ActionOnLoseFocus(n,function(){e.close()})},close:function(){this.$dropdown.removeClass("open"),this.$el.parent().removeClass("open"),this.$dropdown.detach()},alignDropdown:function(){var e,t=this.model.get("horizontalAlignment"),n=this.$el.parent(),i=n.offset(),o=i.top+n.height()-2,r=this.$dropdown.find(".dropdown-menu");e="Right"==t?i.left-(r.width()-n.width()):i.left,this.$dropdown.offset({top:o,left:e})},onClickGripHandler:function(){this.toggle()},updateGrouping:function(){},whenReady:function(e,t,n){var i=this;void 0===n&&(n=100),e()?t():n>0&&setTimeout(function(){i.whenReady(e,t,n-1)},10)}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.PopupButton.forMenu",ForMenuPopupButtonView),_.inherit(StackPanelControl,ContainerControl),_.extend(StackPanelControl.prototype,{createControlModel:function(){return new StackPanelModel},createControlView:function(e,t){var n=new StackPanelView({model:e});return n.viewMode=t,n}});var StackPanelModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),StackPanelView=ContainerView.extend({tagName:"ul",className:"pl-stack-panel pl-clearfix",template:{plain:InfinniUI.Template["controls/stackPanel/baseView/template/stackPanel.tpl.html"],grouped:InfinniUI.Template["controls/stackPanel/baseView/template/stackPanelGrouped.tpl.html"]},UI:{items:".stackpanel-items"},initialize:function(e){ContainerView.prototype.initialize.call(this,e),this.initOrientation()},updateGrouping:function(){var e=null!=this.model.get("groupValueSelector");e?this.strategy=new StackPanelViewGroupStrategy(this):this.strategy=new StackPanelViewPlainStrategy(this)},render:function(){this.prerenderingActions(),this.removeChildElements();var e=this.strategy.prepareItemsForRendering(),t=this.strategy.getTemplate();return this.$el.html(t(e)),this.strategy.appendItemsContent(e),this.bindUIElements(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},initOrientation:function(){this.listenTo(this.model,"change:orientation",this.updateOrientation),this.updateOrientation()},updateOrientation:function(){var e=this.model.get("orientation");this.$el.toggleClass("horizontal-orientation","Horizontal"==e),this.$el.toggleClass("pl-stack-panel_horizontal","Horizontal"==e)},getItems:function(){return this.model.get("items")},getItemTemplate:function(){return this.model.get("itemTemplate")},getGroupValueSelector:function(){return this.model.get("groupValueSelector")},getGroupItemTemplate:function(){return this.model.get("groupItemTemplate")}});_.extend(StackPanelViewGroupStrategy.prototype,{groupTemplate:InfinniUI.Template["controls/stackPanel/baseView/template/stackPanelGroup.tpl.html"],prepareItemsForRendering:function(){var e=this.stackPanel.getItems(),t="listbox-"+guid(),n={inputName:t,groups:[]},i={},o=this.stackPanel.getGroupValueSelector();e.forEach(function(e,t){var n=o(void 0,{value:e});n in i||(i[n]=[]),i[n].push(e)});for(var r in i)i.hasOwnProperty(r)&&n.groups.push({items:i[r],indices:i[r].map(function(t){return e.indexOf(t)})});return n},getTemplate:function(){return this.stackPanel.template.grouped},appendItemsContent:function(e){var t,n=this.stackPanel,i=n.$el,o=this.groupTemplate,r=this.stackPanel.getGroupItemTemplate(),a=this.stackPanel.getItemTemplate(),l=e.groups;t=l.map(function(e,t){var i,l=e.items||[],s=e.indices||[],u=$(o({items:l})),d=r(null,{index:s[0],item:e});return n.addChildElement(d),i=l.map(function(e,t){var i=a(null,{index:s[t],item:e});return n.addChildElement(i),i.render()}),$(".pl-stack-panel-group__header",u).append(d.render()),$(".pl-stack-panel-list__item",u).each(function(e,t){$(t).append(i[e])}),u}),i.append(t)}}),_.extend(StackPanelViewPlainStrategy.prototype,{prepareItemsForRendering:function(){var e=this.stackPanel.getItems(),t={items:e.toArray()};return t},getTemplate:function(){return this.stackPanel.template.plain},appendItemsContent:function(e,t){var n,i,o=this.stackPanel.$el,r=this.stackPanel.getItemTemplate(),a=e.items,l=this.stackPanel;t=t||".pl-stack-panel-i",o.find(t).each(function(e,t){i=$(t),n=r(void 0,{index:e,item:a[e]}),l.addChildElement(n),i.append(n.render()),i.parent().data("pl-data-item",a[e])})}}),_.inherit(TablePanelControl,ContainerControl),_.extend(TablePanelControl.prototype,{createControlModel:function(){return new TablePanelModel},createControlView:function(e){return new TablePanelView({model:e})}});var TablePanelModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),TablePanelView=ContainerView.extend({className:"pl-table-panel",initialize:function(e){ContainerView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.renderItemsContents(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItemsContents:function(){var e,t=this.model.get("items"),n=this.model.get("itemTemplate"),i=this;t.forEach(function(t,o){e=n(void 0,{item:t,index:o}),i.addChildElement(e),i.$el.append(e.render())})},updateGrouping:function(){}});_.inherit(CellControl,ContainerControl),_.extend(CellControl.prototype,{createControlModel:function(){return new CellModel},createControlView:function(e){return new CellView({model:e})}});var CellModel=ContainerModel.extend({defaults:_.defaults({columnSpan:1},ContainerModel.prototype.defaults),initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),CellView=ContainerView.extend({className:"pl-cell",initialize:function(e){ContainerView.prototype.initialize.call(this,e),this.initColumnSpan()},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.renderItemsContents(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItemsContents:function(){var e,t=this.model.get("items"),n=this.model.get("itemTemplate"),i=this;t.forEach(function(t,o){e=n(void 0,{item:t,index:o}),i.addChildElement(e),i.$el.append(e.render())})},initColumnSpan:function(){this.listenTo(this.model,"change:columnSpan",this.updateColumnSpan),this.updateColumnSpan()},updateColumnSpan:function(){var e=this.model.get("columnSpan"),t=this.columnSpan;e!=t&&(t&&this.$el.removeClass("col-xs-"+t),this.$el.addClass("col-xs-"+e),this.columnSpan=e)},updateGrouping:function(){}});_.inherit(RowControl,ContainerControl),_.extend(RowControl.prototype,{createControlModel:function(){return new RowModel},createControlView:function(e){return new RowView({model:e})}});var RowModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),RowView=ContainerView.extend({className:"pl-row row",initialize:function(e){ContainerView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.renderItemsContents(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItemsContents:function(){var e,t=this.model.get("items"),n=this.model.get("itemTemplate"),i=this;t.forEach(function(t,o){e=n(void 0,{item:t,index:o}),i.addChildElement(e),i.$el.append(e.render())})},updateGrouping:function(){}});_.inherit(TabPanelControl,ContainerControl),_.extend(TabPanelControl.prototype,{setSelectedItem:function(e){var t=null,n=this.controlModel,i=this.controlView.childElements,o=n.get("items");if(e instanceof TabPage)n.set("selectedItem",e);else if(Array.isArray(i)){var r=o.indexOf(e);r!==-1&&(t=i[r]),this.controlModel.set("selectedItem",t)}},createControlModel:function(){return new TabPanelModel},createControlView:function(e){return new TabPanelView({model:e})}});var TabPanelModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))},defaults:_.defaults({headerLocation:InfinniUI.TabHeaderLocation.top,headerOrientation:InfinniUI.TabHeaderOrientation.horizontal},ContainerModel.prototype.defaults)}),TabPanelView=ContainerView.extend({className:"pl-tabpanel",template:{top:InfinniUI.Template["controls/tabPanel/template/tabPanel.top.tpl.html"],right:InfinniUI.Template["controls/tabPanel/template/tabPanel.right.tpl.html"], -bottom:InfinniUI.Template["controls/tabPanel/template/tabPanel.bottom.tpl.html"],left:InfinniUI.Template["controls/tabPanel/template/tabPanel.left.tpl.html"],none:InfinniUI.Template["controls/tabPanel/template/tabPanel.none.tpl.html"]},UI:{header:".pl-tabpanel-header",content:".pl-tabpanel-content"},initHandlersForProperties:function(){ContainerView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:headerLocation",this.onChangeHeaderLocation),this.listenTo(this.model,"change:headerOrientation",this.updateHeaderOrientation),this.listenTo(this.model,"change:selectedItem",this.updateSelectedItem)},render:function(){return this.prerenderingActions(),this.renderTemplate(this.getTemplate()),this.renderItemsContents(),this.checkSelectedItem(),this.postrenderingActions(),this.trigger("render"),this.updateProperties(),this},renderItemsContents:function(){var e=this.model.get("items");this.removeChildElements(),this.ui.content.empty(),this.model.set("selectedItemIndex",-1);var t=[];e.forEach(function(e,n){t.push({tabElement:this.renderTabContent(e,n),item:e,index:n})},this),this.renderTabHeaders(t)},renderTabHeaders:function(e){var t,n=this.model,i=n.get("items");n.get("selectedItem");if(Array.isArray(this.tabHeaders))for(;t=this.tabHeaders.pop();)this.stopListening(t),t.remove();this.tabHeaders=e.map(function(e){var t=i.indexOf(e.item)!==-1,o=this.renderTabHeader(e.tabElement,t);return this.listenTo(o,"selected",function(){n.set("selectedItem",e.tabElement)}),this.listenTo(o,"close",function(){e.tabElement.close()}),o},this)},renderTabHeader:function(e,t){var n=new TabHeaderView({text:e.getText(),canClose:e.getCanClose(),selected:t});return e.onPropertyChanged("text",function(){n.setText(e.getText())}),e.onPropertyChanged("canClose",function(){n.setCanClose(e.getCanClose())}),this.ui.header.append(n.render().$el),n},renderTabContent:function(e,t){var n=this.model.get("itemTemplate"),i=n(void 0,{item:e,index:t});return this.addChildElement(i),this.ui.content.append(i.render()),i},getTemplate:function(){var e,t=this.model.get("headerLocation");switch(t){case InfinniUI.TabHeaderLocation.top:e=this.template.top;break;case InfinniUI.TabHeaderLocation.right:e=this.template.right;break;case InfinniUI.TabHeaderLocation.bottom:e=this.template.bottom;break;case InfinniUI.TabHeaderLocation.left:e=this.template.left;break;case InfinniUI.TabHeaderLocation.none:default:e=this.template.none}return e},updateProperties:function(){ContainerView.prototype.updateProperties.call(this),this.updateHeaderOrientation(),this.updateSelectedItem()},onChangeHeaderLocation:function(){this.rerender()},updateHeaderOrientation:function(){},checkSelectedItem:function(){var e=this.model,t=this.childElements,n=e.get("selectedItem");Array.isArray(t)&&t.length?t.indexOf(n)===-1&&e.set("selectedItem",t[0]):e.set("selectedItem",null)},updateSelectedItem:function(){if(this.wasRendered){var e=this.childElements,t=this.tabHeaders,n=this.model.get("selectedItem"),i=e.indexOf(n);Array.isArray(e)&&(e.forEach(function(e){e.setSelected(!1)}),i!==-1&&e[i].setSelected(!0)),Array.isArray(t)&&(t.forEach(function(e){e.setSelected(!1)}),i!==-1&&t[i].setSelected(!0))}},updateGrouping:function(){}}),TabHeaderModel=Backbone.Model.extend({defaults:{text:"",canClose:!1}}),TabHeaderView=Backbone.View.extend({className:"pl-tabheader",tagName:"li",template:InfinniUI.Template["controls/tabPanel/tabHeader/template/tabHeader.tpl.html"],events:{click:"onClickHandler","click .pl-close":"onClickCloseHandler"},UI:{label:".pl-tabheader-text",close:".pl-close"},initialize:function(e){this.model=new TabHeaderModel(e),this.on("rendered",this.onRenderedHandler)},render:function(){return this.$el.html(this.template),this.bindUIElements(),this.trigger("rendered"),this},setText:function(e){this.model.set("text",e)},setCanClose:function(e){this.model.set("canClose",e)},setSelected:function(e){this.model.set("selected",e)},updateProperties:function(){this.updateTextHandler(),this.updateCanClose(),this.updateSelectedHandler()},onRenderedHandler:function(){this.updateProperties(),this.listenTo(this.model,"change:text",this.updateTextHandler),this.listenTo(this.model,"change:selected",this.updateSelectedHandler),this.listenTo(this.model,"cahnge:canClose",this.updateCanClose)},updateTextHandler:function(){var e=this.model.get("text");this.ui.label.text(e)},updateCanClose:function(){var e=this.model.get("canClose");this.ui.close.toggleClass("hidden",!e)},updateSelectedHandler:function(){var e=this.model.get("selected");this.$el.toggleClass("pl-active active",e)},onClickHandler:function(e){this.trigger("selected")},onClickCloseHandler:function(e){e.stopPropagation(),this.trigger("close")}});_.extend(TabHeaderView.prototype,bindUIElementsMixin),_.inherit(TabPageControl,ContainerControl),_.extend(TabPageControl.prototype,{createControlModel:function(){return new TabPageModel},createControlView:function(e){return new TabPageView({model:e})}});var TabPageModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))},defaults:_.defaults({canClose:!1,selected:!1},ContainerModel.prototype.defaults)}),TabPageView=ContainerView.extend({className:"pl-tabpage hidden",template:InfinniUI.Template["controls/tabPanel/tabPage/template/tabPage.tpl.html"],UI:{},initHandlersForProperties:function(){ContainerView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:selected",this.updateSelected)},updateProperties:function(){ContainerView.prototype.updateProperties.call(this),this.updateSelected()},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.$el.html(this.template({items:this.model.get("items")})),this.renderItemsContents(),this.bindUIElements(),this.postrenderingActions(),this.trigger("render"),this.updateProperties(),this},renderItemsContents:function(){var e,t,n=this.$el.find(".pl-tabpage-i"),i=this.model.get("items"),o=this.model.get("itemTemplate"),r=this;n.each(function(n,a){t=i.getByIndex(n),e=o(void 0,{item:t,index:n}),r.addChildElement(e),$(a).append(e.render())})},updateSelected:function(){var e=this.model.get("selected");this.$el.toggleClass("hidden",!e)},updateGrouping:function(){}});_.inherit(TreeViewControl,ListEditorBaseControl),_.extend(TreeViewControl.prototype,{createControlModel:function(){return new TreeViewModel},createControlView:function(e){return new TreeViewView({model:e})}});var TreeViewModel=ListEditorBaseModel.extend({initialize:function(){ListEditorBaseModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))},toggleItem:function(e,t){var n=this.valueByItem(e);this.toggleValue(n,t),this.trigger("toggle")}}),TreeViewView=ListEditorBaseView.extend({className:"pl-treeview",classNameMultiSelect:"pl-treeview_multi-select",classNameSingleSelect:"pl-treeview_single-select",template:InfinniUI.Template["controls/treeView/template/treeview.tpl.html"],events:{},UI:_.defaults({},ListEditorBaseView.prototype.UI),initialize:function(e){ListEditorBaseView.prototype.initialize.call(this,e),this.ItemsMap=new HashMap},render:function(){return this.prerenderingActions(),this.renderTemplate(this.getTemplate()),this.renderItems(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItems:function(e){function t(e){return a.toArray().filter(function(t){var i=l(null,{value:t});return n(e)?n(i):i===e}).map(function(e){function n(t){return r.itemByValue(t)===e}var i=(new u).render(),l=i.$el,h=d(null,{value:e,index:a.indexOf(e)}).render();l.data("pl-data-item",e),i.listenTo(r,"change:selectedItem",function(t,n){i.setSelected(n===e)}),i.listenTo(r,"change:value",function(e,t){var o,r=e.get("multiSelect");o=r?!!Array.isArray(t)&&t.some(n):n(t),i.setChecked(o)}),o.listenTo(i,"select",o.onSelectNodeHandler.bind(o,e,i)),o.listenTo(i,"check",o.onCheckNodeHandler.bind(o,e,i)),i.setItemContent(h);var p=s(null,{value:e}),m=t(p);return i.setItemsContent(m),c.add(p,e),l})}function n(e){return null===e||"undefined"==typeof e}var i,o=this,r=this.model,a=r.get("items"),l=r.get("parentSelector"),s=r.get("keySelector"),u=this.getNodeConstructor(),d=r.get("itemTemplate"),c=this.ItemsMap;c.clear(),i=t(),this.$el.append(i)},getNodeConstructor:function(){var e=this.model.get("multiSelect");return e===!0?TreeViewNodeCheckbox:TreeViewNodeRadio},onSelectNodeHandler:function(e,t){var n=this.model,i=n.get("multiSelect");n.set("selectedItem",e),i||this.tryToggleValue(e)},onCheckNodeHandler:function(e,t){var n=this.model,i=n.get("multiSelect");this.tryToggleValue(e),i||n.set("selectedItem",e)},tryToggleValue:function(e){var t=this.model,n=this.isDisabledItem(e);if(!n){var i=t.valueByItem(e);t.toggleValue(i)}},isDisabledItem:function(e){return null!=e&&(this.model.isDisabledItem(e)||this.isDisabledItem(this.getParent(e)))},getParent:function(e){var t=this.model.get("parentSelector"),n=t(null,{value:e});return n&&this.ItemsMap.get(n)},getTemplate:function(){return this.template},updateProperties:function(){ListEditorBaseView.prototype.updateProperties.call(this),this.updateMultiSelect()},updateMultiSelect:function(){var e=this.model.get("multiSelect");this.$el.toggleClass(this.classNameMultiSelect,!!e),this.$el.toggleClass(this.classNameSingleSelect,!e)},updateEnabled:function(){ListEditorBaseView.prototype.updateEnabled.call(this);this.model.get("enabled")},updateValue:function(){},updateSelectedItem:function(){},updateGrouping:function(){},updateDisabledItem:function(){var e=this.model,t=e.get("disabledItemCondition"),n=this.$el.find(".pl-treeview-node");n.removeClass("pl-disabled-list-item"),null!=t&&n.each(function(t,n){var i=$(n),o=i.data("pl-data-item");e.isDisabledItem(o)&&i.addClass("pl-disabled-list-item")})},rerender:function(){}}),TreeViewNodeBase=Backbone.View.extend({className:"pl-treeview-node",classNameCheckerChecked:"pl-treeview-item__checker_checked",classNameContentSelected:"pl-treeview-item__content_selected",classNameItemsExpanded:"pl-treeview-node__items_expanded",classNameItemsCollapsed:"pl-treeview-node__items_collapsed",classNameButtonCollapse:"pl-treeview-node__button_collapse",classNameButtonExpand:"pl-treeview-node__button_expand",UI:{checker:".pl-treeview-item__checker",content:".pl-treeview-item__content",items:".pl-treeview-node__items",button:".pl-treeview-node__button"},initialize:function(){var e=new Backbone.Model({collapsed:!0});this.model=e,this.listenTo(e,"change:selected",this.updateSelected),this.listenTo(e,"change:checked",this.updateChecked),this.listenTo(e,"change:collapsed",this.updateCollapsed)},updateChecked:function(){var e=this.model.get("checked");this.ui.checker.toggleClass(this.classNameCheckerChecked,e===!0)},updateSelected:function(){var e=this.model.get("selected");this.ui.content.toggleClass(this.classNameContentSelected,e===!0)},updateCollapsed:function(){var e=!!this.model.get("collapsed");this.ui.items.toggleClass(this.classNameItemsExpanded,!e),this.ui.items.toggleClass(this.classNameItemsCollapsed,e),this.ui.button.toggleClass(this.classNameButtonCollapse,!e),this.ui.button.toggleClass(this.classNameButtonExpand,e)},updateState:function(){this.updateCollapsed(),this.updateSelected(),this.updateChecked()},render:function(){return this.$el.html(this.template),this.bindUIElements(),this.updateState(),this.initDomEventsHandlers(),this},initDomEventsHandlers:function(){this.ui.button.on("click",this.onClickEventHandler.bind(this)),this.ui.content[0].addEventListener("click",this.onClickItemHandler.bind(this),!0),this.ui.checker[0].addEventListener("click",this.onClickCheckHandler.bind(this),!0)},onClickItemHandler:function(e){this.trigger("select")},onClickCheckHandler:function(e){this.trigger("check")},toggle:function(){var e=this.model,t=e.get("collapsed");this.model.set("collapsed",!t)},setItemContent:function(e){this.ui.content.empty(),this.ui.content.append(e)},setItemsContent:function(e){this.ui.items.empty(),this.ui.items.append(e)},onClickEventHandler:function(e){this.toggle()},setSelected:function(e){this.model.set("selected",e)},setChecked:function(e){this.model.set("checked",e)}});_.extend(TreeViewNodeBase.prototype,bindUIElementsMixin);var TreeViewNodeCheckbox=TreeViewNodeBase.extend({template:InfinniUI.Template["controls/treeView/template/node-checkbox.tpl.html"]}),TreeViewNodeRadio=TreeViewNodeBase.extend({template:InfinniUI.Template["controls/treeView/template/node-radio.tpl.html"]});_.inherit(CheckBoxControl,Control),_.extend(CheckBoxControl.prototype,{createControlModel:function(){return new CheckBoxModel},createControlView:function(e){return new CheckBoxView({model:e})}},editorBaseControlMixin);var CheckBoxModel=ControlModel.extend(_.extend({defaults:_.defaults({value:!1},ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.initialize_editorBaseModel()}},editorBaseModelMixin)),CheckBoxView=ControlView.extend(_.extend({},editorBaseViewMixin,{template:InfinniUI.Template["controls/checkBox/template/checkBox.tpl.html"],UI:_.extend({},editorBaseViewMixin.UI,{text:".checkbox-label",input:"input"}),events:{"click input":"onClickHandler"},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),editorBaseViewMixin.initHandlersForProperties.call(this)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),editorBaseViewMixin.updateProperties.call(this)},updateFocusable:function(){var e=this.model.get("focusable");e?this.ui.input.removeAttr("tabindex"):this.ui.input.attr("tabindex",-1)},updateText:function(){var e=this.model.get("text");this.ui.text.text(e?e:"")},updateEnabled:function(){ControlView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");this.ui.input.prop("disabled",!e)},render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},onClickHandler:function(){var e=this.model,t=e.get("enabled");t&&e.set("value",!e.get("value"))},updateValue:function(){var e=this.model.get("value");this.ui.input.prop("checked",!!e)},setFocus:function(){this.ui.input.focus()}}));_.inherit(ComboBoxControl,ListEditorBaseControl),_.extend(ComboBoxControl.prototype,{createControlModel:function(){return new ComboBoxModel},createControlView:function(e){return new ComboBoxView({model:e})}});var ComboBoxModel=ListEditorBaseModel.extend({defaults:_.defaults({showClear:!0,autocomplete:!1,autocompleteValue:"",valueTemplate:function(e,t){return{render:function(){return t.value}}}},ListEditorBaseModel.prototype.defaults),initialize:function(){ListEditorBaseModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments)),this.on("change:value",this.syncSelectedItem)},setSelectedItemToValue:function(){var e=this.get("autocomplete"),t=this.get("multiSelect");if(!e&&!t){var n=this.getSelectedItem(),i=this.valueByItem(n);this.set("value",i)}},syncSelectedItem:function(e,t){var n=this.itemByValue(t);this.setSelectedItem(n)},getSelectedItem:function(){var e=this.get("selectedItem");return e},setSelectedItem:function(e){this.set("selectedItem",e)},selectNextItem:function(){var e=this.get("items"),t=this.getSelectedItem();if(e.length>0){var n=0;t&&(n=e.indexOf(t),n=n===-1?0:Math.min(e.length-1,n+1)),t=e.getByIndex(n)}else t=null;this.setSelectedItem(t),this.setSelectedItemToValue()},selectPrevItem:function(){var e=this.get("items"),t=this.getSelectedItem();if(e.length>0){var n=0;t&&(n=e.indexOf(t),n=n===-1?0:Math.max(0,n-1)),t=e.getByIndex(n)}this.setSelectedItem(t),this.setSelectedItemToValue()},selectFirstItem:function(){var e=this.get("items"),t=null;e.length>0&&(t=e.getByIndex(0)),this.setSelectedItem(t),this.setSelectedItemToValue()},selectLastItem:function(){var e=this.get("items"),t=null;e.length>0&&(t=e.getByIndex(e.length-1)),this.setSelectedItem(t),this.setSelectedItemToValue()},toggleItem:function(e,t){var n=this.valueByItem(e);this.toggleValue(n,t),this.trigger("toggle")}}),ComboBoxView=ListEditorBaseView.extend({className:"pl-combobox form-group",template:InfinniUI.Template["controls/comboBox/template/combobox.tpl.html"],events:{"click .pl-combobox__grip":"onClickGripHandler","click .pl-combobox__value":"onClickValueHandler","click .pl-combobox__clear":"onClickClearHandler","click .pl-control":"onClickValueHandler","keydown .pl-control":"onKeyDownControlHandler"},UI:_.defaults({control:".pl-control",label:".pl-control-label",value:".pl-combobox__value",clear:".pl-combobox__clear"},ListEditorBaseView.prototype.UI),isControlElement:function(e){var t=ListEditorBaseView.prototype.isControlElement.call(this,e);return t?t:!!this.dropDownView&&$.contains(this.dropDownView.el,e)},updateFocusable:function(){var e=this.model.get("focusable"),t=this.model.get("enabled");e&&t?this.ui.control.attr("tabindex",0):this.ui.control.removeAttr("tabindex")},initialize:function(e){ListEditorBaseView.prototype.initialize.call(this,e);var t=this.model,n=this;this.on("render",function(){n.renderValue(),t.on("change:dropdown",function(e,t){if(t){e.set("autocompleteValue",""),e.set("focused",!0),n.dropDownView&&n.dropDownView.remove();var i=new ComboBoxDropdownView({model:e});n.dropDownView=i,this.listenTo(i,"search",_.debounce(n.onSearchValueHandler.bind(n),300));var o=i.render();$("body").append(o),i.updatePosition(n.el),n.dropDownView.on("itemsRendered2",function(){i.updatePosition(n.el)}),e.get("autocomplete")?i.setSearchFocus():n.ui.control.focus(),setTimeout(i.ensureVisibleSelectedItem.bind(i),0)}else n.ui.control.focus()}),t.onValueChanged(this.onChangeValueHandler.bind(this))},this)},initHandlersForProperties:function(){ListEditorBaseView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:showClear",this.updateShowClear),this.listenTo(this.model,"change:labelText",this.updateLabelText)},render:function(){return this.prerenderingActions(),this.renderTemplate(this.getTemplate()),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},getTemplate:function(){return this.template},onKeyDownControlHandler:function(e){var t=this.model.get("enabled");if(!t)return void e.preventDefault();if(!e.ctrlKey&&!e.altKey){if(this.isDropdown())return this.dropDownView.onKeyDownHandler.call(this.dropDownView,e);switch(e.which){case 40:case 13:e.preventDefault(),this.toggleDropdown()}}},onClickClearHandler:function(){var e=this.model.get("enabled");e&&(this.model.set("value",null),this.ui.control.focus())},onClickGripHandler:function(){var e=this.model.get("enabled");e&&this.toggleDropdown()},updateProperties:function(){ListEditorBaseView.prototype.updateProperties.call(this),this.updateLabelText(),this.updateShowClear()},updateGrouping:function(){this.toggleDropdown(!1)},updateLabelText:function(){var e=this.model.get("labelText");e&&""!==e?this.ui.label.toggleClass("hidden",!1):this.ui.label.toggleClass("hidden",!0),this.ui.label.text(e)},updateEnabled:function(){ListEditorBaseView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");e?this.updateFocusable():this.ui.control.removeAttr("tabindex")},updateValue:function(){this.updateShowClear()},updateShowClear:function(){var e=this.model,t=e.get("showClear"),n=e.get("value"),i=null===n||"undefined"==typeof n;this.ui.clear.toggleClass("hidden",!t||i)},updateSelectedItem:function(){},updateDisabledItem:function(){this.toggleDropdown(!1)},isDropdown:function(){var e=this.model;return!!e.get("dropdown")},toggleDropdown:function(e){var t=this.model;"undefined"==typeof e&&(e=!t.get("dropdown")),t.set("dropdown",e)},onChangeValueHandler:function(){this.renderValue()},rerender:function(){},renderValue:function(){var e=this.model,t=e.get("multiSelect"),n=this.model.get("value"),i=[],o=this.model.get("valueTemplate");if(t&&Array.isArray(n)){var r=new ComboBoxValues({items:n.map(function(e,t){return{$value:o(null,{value:e,index:t}).render(),value:e,index:t}})});r.listenTo(e,"toggle",r.setFocus),this.listenTo(r,"remove",this.onRemoveValueHandler),this.listenTo(r,"search",_.debounce(this.onSearchValueHandler.bind(this),300)),i=r.render()}else i=o(null,{value:n}).render();this.ui.value.empty(),this.ui.value.append(i),editorBaseViewMixin.updateValueState.call(this)},onRemoveValueHandler:function(e){this.model.toggleValue(e,!1)},onSearchValueHandler:function(e){this.toggleDropdown(!0),this.model.set("autocompleteValue",e)},onClickValueHandler:function(e){var t=this.model.get("enabled");t&&this.toggleDropdown(!0)}});_.inherit(ContextMenuControl,ContainerControl),_.extend(ContextMenuControl.prototype,{createControlModel:function(){return new ContextMenuModel},createControlView:function(e){return new ContextMenuView({model:e})}});var ContextMenuModel=ContainerModel.extend({}),ContextMenuView=ContainerView.extend({contextMenuTemplate:InfinniUI.Template["controls/contextMenu/template/contextMenu.tpl.html"],updateProperties:function(){ContainerView.prototype.updateProperties.call(this),this.updateContent()},updateContent:CommonButtonView.prototype.updateContent,updateText:CommonButtonView.prototype.updateText,updateHorizontalAlignment:function(){var e,t=this.model.get("horizontalAlignment"),n=this;this.whenReady(function(){return e=n.$el.parent().parent(),e.length>0},function(){"Right"==t?e.addClass("pull-right"):e.removeClass("pull-right")})},getButtonElement:function(){return this.ui.button},render:function(){var e=window.InfinniUI.global.messageBus,t=this;return this.prerenderingActions(),this.removeChildElements(),this.$el=this.renderDropdown(),this.bindUIElements(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),e.subscribe(messageTypes.onOpenContextMenu.name,function(e,n){t.open(n.value)}),this},renderDropdown:function(){var e=this.contextMenuTemplate,t=this.model.get("items").toArray(),n=$(e({items:t}));return this.appendItemsContent(n,t),n.on("click",function(){this.close()}.bind(this)),n.on("contextmenu",function(e){e.preventDefault()}.bind(this)),n},appendItemsContent:function(e,t){var n,i,o=this,r=this.model.get("itemTemplate");e.find(".pl-popup-button__item").each(function(e,a){i=$(a),n=r(void 0,{index:e,item:t[e]}),o.addChildElement(n),i.append(n.render())})},open:function(e){var t=this;$("body").append(this.$el);var n=this.$el.parent();this.$el.addClass("open"),n.addClass("open"),this.alignDropdown(e);var i=this.$el;new ActionOnLoseFocus(i,function(){t.close()})},close:function(){this.$el.removeClass("open"),this.$el.parent().removeClass("open"),this.$el.detach()},alignDropdown:function(e){var t=(this.model.get("horizontalAlignment"),this.$el.parent()),n={width:t.width(),height:t.height()},i={width:this.$el[0].children[0].clientWidth,height:this.$el[0].children[0].clientHeight};e.x+i.width>n.width&&(e.x-=i.width),e.y+i.height>n.height&&(e.y-=i.height),this.$el.offset({top:e.y,left:e.x})},updateGrouping:function(){},whenReady:function(e,t,n){var i=this;void 0===n&&(n=100),e()?t():n>0&&setTimeout(function(){i.whenReady(e,t,n-1)},10)}});_.inherit(DividerControl,Control),_.extend(DividerControl.prototype,{createControlModel:function(){return new DividerModel},createControlView:function(e){return new DividerView({model:e})}});var DividerModel=ControlModel.extend({initialize:function(){ControlModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),DividerView=ControlView.extend({tagName:"hr",className:"pl-divider",initialize:function(e){ControlView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this}}),ExtensionPanelControl=function(){_.superClass(ExtensionPanelControl,this)};_.inherit(ExtensionPanelControl,ContainerControl),_.extend(ExtensionPanelControl.prototype,{createControlModel:function(){return new ExtensionPanelModel},createControlView:function(e){return new ExtensionPanelView({model:e})}});var ExtensionPanelModel=ContainerModel.extend({defaults:_.defaults({extensionName:null,context:null},ContainerModel.prototype.defaults),initialize:function(){ContainerModel.prototype.initialize.apply(this)}}),ExtensionPanelView=ContainerView.extend({className:"pl-extension-panel",initialize:function(){ContainerView.prototype.initialize.apply(this),this.extensionObject=null},render:function(){return this.prerenderingActions(),this.extensionObject||this.initExtensionObject(),this.extensionObject.render(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},updateGrouping:function(){},initExtensionObject:function(){var e=this.model.get("extensionName"),t=this.model.get("context"),n=this.model.get("itemTemplate"),i=this.model.get("parameters"),o=this.model.get("items"),r=this.model.get("builder");this.extensionObject=new window[e](t,{$el:this.$el,parameters:i,itemTemplate:n,items:o,builder:r})}});_.inherit(FileBoxControl,Control),_.extend(FileBoxControl.prototype,{createControlModel:function(){return new FileBoxModel},createControlView:function(e){return new FileBoxView({model:e})}},editorBaseControlMixin);var FileBoxModel=ControlModel.extend(_.extend({defaults:_.defaults({},editorBaseModelMixin.defaults_editorBaseModel,ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.initialize_editorBaseModel(),this.set("acceptTypes",new Collection),this.on("change:file",this.onChangeFileHandler),this.on("change:value",function(e,t){t instanceof File&&e.set("fileName",t.name)}),this.on("invalid",function(e,t){this.set("errorText",t)})},validate:function(e,t){var n=e.file,i=this.get("maxSize"),o=this.get("acceptTypes");if(n){if(i&&n.size>i)return"Размер выбранного файла "+(n.size/1048576).toFixed(1)+"Мб больше допустимого размера "+(i/1048576).toFixed(1)+"Мб";if(o.length){var r=o.contains(n.type),a=n.name.toLowerCase();if(!r)var l=a.length,r=o.some(function(e){return a.lastIndexOf(e.toLowerCase())===l-e.length});if(!r)return"Загрузка данного типа файла не разрешена"}}},setFile:function(e){this.set("file",e,{validate:!0})&&this.set("errorText","")},removeFile:function(){this.setFile(null)},onChangeFileHandler:function(e,t){t?(e.set("fileName",t.name),e.set("fileSize",t.size)):(e.set("fileName",null),e.set("fileSize",null)),e.set("value",t)}},editorBaseModelMixin)),FileBoxView=ControlView.extend(_.extend({},editorBaseViewMixin,{template:InfinniUI.Template["controls/fileBox/template/template.tpl.html"],className:"pl-file-box",UI:_.extend({},editorBaseViewMixin.UI,{label:".pl-control-label",btnRemove:".pl-filebox-btn-remove",btnPick:".pl-filebox-btn-pick",fileEmpty:".pl-filebox-file-empty",fileUpload:".pl-filebox-file-upload",fileDownload:".pl-filebox-file-download",fileDownloadUrl:".pl-filebox-file-download-url",edit:".pl-filebox-edit",control:".form-control",input:"input"}),events:{"change input":"onChangeFileHandler","click .pl-filebox-btn-remove":"onClickRemoveImageHandler"},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:labelText",this.updateLabelText),this.listenTo(this.model,"change:fileName",this.updateFileName),this.listenTo(this.model,"change:fileSize",this.updateFileSize),this.listenTo(this.model,"change:fileTime",this.updateFileTime),this.listenTo(this.model,"change:fileType",this.updateFileType),this.listenTo(this.model,"change:value",this.updateValue),this.listenTo(this.model,"change:hintText",this.updateHintText),this.listenTo(this.model,"change:errorText",this.updateErrorText),this.listenTo(this.model,"change:warningText",this.updateWarningText),this.listenTo(this.model,"invalid",this.onInvalidHandler);var e=this.model.get("acceptTypes");e.onChange(this.updateAcceptTypes.bind(this))},updateProperties:function(){ControlView.prototype.updateProperties.call(this),this.updateLabelText(),this.updateFileName(),this.updateFileSize(),this.updateFileType(),this.updateFileTime(),this.updateAcceptTypes(),this.updateValue(),this.updateHintText(),this.updateErrorText(),this.updateWarningText()},updateLabelText:function(){var e=this.model.get("labelText");""!=e?this.ui.label.css({display:"inline-block"}).text(e):this.ui.label.css({display:"none"})},updateAcceptTypes:function(){var e=this.model.get("acceptTypes");if(0===e.length)this.ui.input.removeAttr("accept");else{var t=e.toArray().join(",");this.ui.input.attr("accept",t)}},updateFocusable:function(){var e=this.model.get("focusable");e?this.ui.control.attr("tabindex",0):this.ui.control.removeAttr("tabindex")},updateText:function(){var e=this.model.get("text");this.ui.btnPick.attr("title",e)},updateHintText:function(){var e=this.model.get("hintText");e?this.ui.hintText.text(e).removeClass("hidden"):this.ui.hintText.text("").addClass("hidden")},updateErrorText:function(){var e=this.model.get("errorText");e?this.ui.errorText.text(e).removeClass("hidden"):this.ui.errorText.text("").addClass("hidden")},updateWarningText:function(){var e=this.model.get("warningText");e?this.ui.warningText.text(e).removeClass("hidden"):this.ui.warningText.text("").addClass("hidden")},updateEnabled:function(){ControlView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");this.ui.input.prop("disabled",!e),this.ui.btnRemove.prop("disabled",!e),this.ui.btnPick.toggleClass("disabled",!e)},updateFileName:function(){var e=this.model.get("fileName");this.ui.fileUpload.text(e),this.ui.fileDownloadUrl.text(e)},updateFileSize:function(){},updateFileInfo:function(){return},updateFileTime:function(){this.model.get("fileTime")},updateFileType:function(){this.model.get("fileType")},updateValue:function(){var e=this.model,t=e.get("value"),n=!1,i=!1,o=!1;null===t||"undefined"==typeof t?(n=null===t||"undefined"==typeof t,this.ui.input.val(null),this.updateUrl(null)):t&&"object"==typeof t?(i=t&&"object"==typeof t,this.updateUrl(null)):(o=!0,this.updateUrl(t)),this.ui.fileEmpty.toggleClass("hidden",!n),this.ui.fileUpload.toggleClass("hidden",!i),this.ui.fileDownload.toggleClass("hidden",!o),this.ui.btnRemove.toggleClass("hidden",n),this.ui.btnPick.toggleClass("hidden",!n)},updateUrl:function(e){this.ui.fileDownloadUrl.attr("href",e);var t=null===e||"undefined"==typeof e;this.$el.toggleClass("pl-empty",t),this.updateFileInfo()},onClickRemoveImageHandler:function(){this.model.removeFile(),this.ui.input.val("")},onChangeFileHandler:function(){var e=null,t=this.ui.input[0].files;t&&t[0]&&(e=t[0]),this.model.setFile(e)},render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},onInvalidHandler:function(){this.ui.input.val(null)}}));_.inherit(FormControl,StackPanelControl),_.extend(FormControl.prototype,{createControlModel:function(){return new FormModel},createControlView:function(e){return new FormView({model:e})},onSubmit:function(e){this.controlView.$el.on("submit",e)},setSubmitFunction:function(e){this.controlModel.set("submitFunction",e)},getSubmitFunction:function(){return this.controlModel.get("submitFunction")},setMethod:function(e){this.controlModel.set("method",e)},getMethod:function(){return this.controlModel.get("method")},setAction:function(e){this.controlModel.set("action",e)},getAction:function(){return this.controlModel.get("action")}});var FormModel=StackPanelModel.extend({defaults:_.defaults({submitFunction:null,method:"",action:""},StackPanelModel.prototype.defaults)}),FormView=StackPanelView.extend({className:"pl-form",tagName:"form",template:{plain:InfinniUI.Template["controls/form/template/form.tpl.html"]},events:{submit:"onSubmit"},onSubmit:function(e){e.preventDefault()},initialize:function(e){StackPanelView.prototype.initialize.call(this,e),this.listenTo(this.model,"change:method",this.updateMethod),this.listenTo(this.model,"change:action",this.updateAction)},updateGrouping:function(){this.strategy=new StackPanelViewPlainStrategy(this)},render:function(){this.prerenderingActions(), -this.removeChildElements();var e=this.strategy.prepareItemsForRendering(),t=this.strategy.getTemplate();return this.$el.html(t(e)),this.strategy.appendItemsContent(e,".pl-form-i"),this.bindUIElements(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},updateProperties:function(){StackPanelView.prototype.updateProperties.call(this),this.updateMethod(),this.updateAction()},updateMethod:function(){var e=this.model.get("method");this.$el.attr("method",e)},updateAction:function(){var e=this.model.get("action");this.$el.attr("action",e)}}),FrameControl=function(){_.superClass(FrameControl,this),this.initialize_editorBaseControl()};_.inherit(FrameControl,Control),_.extend(FrameControl.prototype,{createControlModel:function(){return new FrameModel},createControlView:function(e){return new FrameView({model:e})}},editorBaseControlMixin);var FrameModel=ControlModel.extend(_.extend({defaults:_.defaults({},editorBaseModelMixin.defaults_editorBaseModel,ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.initialize_editorBaseModel()}},editorBaseModelMixin)),FrameView=ControlView.extend(_.extend({},editorBaseViewMixin,{className:"pl-frame",template:InfinniUI.Template["controls/frame/template/frame.tpl.html"],UI:_.extend({},editorBaseViewMixin.UI,{iframe:"iframe"}),initialize:function(){ControlView.prototype.initialize.apply(this)},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),editorBaseViewMixin.initHandlersForProperties.call(this)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),editorBaseViewMixin.updateProperties.call(this)},updateValue:function(){var e=this.model.get("value");this.ui.iframe.attr("src",e)},getData:function(){return _.extend({},ControlView.prototype.getData.call(this),editorBaseViewMixin.getData.call(this),{})},render:function(){this.model;return this.prerenderingActions(),this.renderTemplate(this.template),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this}}));_.inherit(GridPanelControl,ContainerControl),_.extend(GridPanelControl.prototype,{createControlModel:function(){return new GridPanelModel},createControlView:function(e){return new GridPanelView({model:e})}});var GridPanelModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),GridPanelView=ContainerView.extend({className:"pl-grid-panel pl-clearfix",columnCount:12,template:{row:InfinniUI.Template["controls/gridPanel/template/row.tpl.html"]},initialize:function(e){ContainerView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.renderItemsContents(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItemsContents:function(){var e,t=this.model.get("items"),n=this.model.get("itemTemplate"),i=this,o=[],r=0;t.forEach(function(t,a){e=n(void 0,{item:t,index:a});var l=e.getColumnSpan();r+l>i.columnCount&&(i.renderRow(o),o.length=0,r=0),o.push(e),r+=l}),o.length&&i.renderRow(o)},renderRow:function(e){var t=this,n=$(this.template.row());n.append(e.map(function(e){return t.addChildElement(e),e.render()})),this.$el.append(n)},updateGrouping:function(){}});_.inherit(IconControl,Control),_.extend(IconControl.prototype,{createControlModel:function(){return new IconModel},createControlView:function(e){return new IconView({model:e})}});var IconModel=ControlModel.extend({defaults:_.defaults({value:null,focusable:!1},ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments)}}),IconView=ControlView.extend({className:"pl-icon fa",tagName:"i",render:function(){return this.prerenderingActions(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderIcon:function(){var e=this.model.get("value");this.switchClass("fa",e)},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:value",this.updateValue)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),this.updateValue()},updateFocusable:function(){var e=this.model.get("focusable");e?this.$el.attr("tabindex",0):this.$el.removeAttr("tabindex")},updateValue:function(){this.renderIcon()}});_.inherit(ImageBoxControl,Control),_.extend(ImageBoxControl.prototype,{createControlModel:function(){return new ImageBoxModel},createControlView:function(e){return new ImageBoxView({model:e})}},editorBaseControlMixin);var ImageBoxModel=ControlModel.extend(_.extend({defaults:_.defaults({text:"Выбрать изображение"},editorBaseModelMixin.defaults_editorBaseModel,ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.initialize_editorBaseModel(),this.set("acceptTypes",new Collection),this.on("change:file",this.onChangeFileHandler),this.on("invalid",function(e,t){this.set("errorText",t)})},validate:function(e,t){var n=e.file,i=this.get("maxSize"),o=this.get("acceptTypes");if(n){if(i&&n.size>i)return"Размер выбранного файла "+(n.size/1048576).toFixed(1)+"Мб больше допустимого размера "+(i/1048576).toFixed(1)+"Мб";if(o.length&&!o.contains(n.type))return"Загрузка данного типа файла не разрешена"}},setFile:function(e){this.set("file",e,{validate:!0})&&this.set("errorText","")},removeFile:function(){this.setFile(null)},onChangeFileHandler:function(e,t){}},editorBaseModelMixin)),ImageBoxView=ControlView.extend(_.extend({},editorBaseViewMixin,{className:"pl-imagebox",template:InfinniUI.Template["controls/imageBox/template/imageBox.tpl.html"],UI:_.extend({},editorBaseViewMixin.UI,{input:"input",img:"img",file:".pl-image-file",remove:".pl-image-remove",uploadButton:".pl-image-file-upload-button"}),events:{"change input":"onChangeFileHandler","click .pl-image-remove":"onClickRemoveImageHandler"},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:value",this.updateValue),this.listenTo(this.model,"change:hintText",this.updateHintText),this.listenTo(this.model,"change:errorText",this.updateErrorText),this.listenTo(this.model,"change:warningText",this.updateWarningText)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),this.updateValue(),this.updateHintText(),this.updateErrorText(),this.updateWarningText()},updateFocusable:function(){var e=this.model.get("focusable");e?this.ui.file.attr("tabindex",0):this.ui.file.removeAttr("tabindex")},updateText:function(){var e=this.model.get("text");this.ui.uploadButton.text(e)},updateEnabled:function(){ControlView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");this.ui.input.prop("disabled",!e)},updateValue:function(){var e=this.model,t=e.get("value");if(t&&"object"==typeof t){this.stopLoadingFile();var n=this.loadPreview(t);this.fileLoader=n,n.then(function(e,t){this.updateUrl(t)}.bind(this),function(e){console.log(e)})}else this.updateUrl(t)},updateUrl:function(e){this.ui.img.attr("src",e);var t=null===e||"undefined"==typeof e;this.$el.toggleClass("pl-empty",t)},stopLoadingFile:function(){var e=this.fileLoader;e&&"pending"===e.state()&&e.reject()},loadPreview:function(e){var t=$.Deferred(),n=new FileReader;return n.onload=function(e){return function(n){t.resolve(e,n.target.result)}}(e),n.onerror=function(e){t.reject(e)},n.readAsDataURL(e),t.promise()},onClickRemoveImageHandler:function(){this.model.removeFile(),this.ui.input.val("")},onChangeFileHandler:function(){var e=null,t=this.ui.input[0].files;t&&t[0]&&(e=t[0]),this.model.setFile(e)},render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this}}));_.inherit(IndeterminateCheckBoxControl,CheckBoxControl),_.extend(IndeterminateCheckBoxControl.prototype,{createControlModel:function(){return new IndeterminateCheckBoxModel},createControlView:function(e){return new IndeterminateCheckBoxView({model:e})}},editorBaseControlMixin);var IndeterminateCheckBoxModel=CheckBoxModel.extend({defaults:_.defaults({value:"unchecked"},CheckBoxModel.prototype.defaults)}),IndeterminateCheckBoxView=CheckBoxView.extend({className:"pl-indeterminate-checkbox",onClickHandler:function(){var e=this.model,t=e.get("enabled");if(t){var n=e.get("value");n="indeterminate"===n?"unchecked":"unchecked"===n?"checked":"unchecked",e.set("value",n)}},updateValue:function(){var e=this.model.get("value");"checked"===e?(this.ui.input.prop("indeterminate",!1),this.ui.input.prop("checked",!0)):"unchecked"===e?(this.ui.input.prop("indeterminate",!1),this.ui.input.prop("checked",!1)):"indeterminate"===e&&(this.ui.input.prop("checked",!1),this.ui.input.prop("indeterminate",!0))}});_.inherit(LinkElementControl,ButtonControl),_.extend(LinkElementControl.prototype,{createControlModel:function(){return new LinkElementModel},createControlView:function(e){return new LinkElementView({model:e})}});var LinkElementModel=ButtonModel.extend({defaults:_.defaults({href:"javascript:;",target:"self"},ButtonModel.prototype.defaults),initialize:function(){ButtonModel.prototype.initialize.apply(this,arguments)}}),LinkElementView=CommonButtonView.extend({tagName:"a",className:"pl-link",events:{click:"onClickHandler"},template:function(){return""},updateProperties:function(){CommonButtonView.prototype.updateProperties.call(this),this.updateHref(),this.updateTarget()},getButtonElement:function(){return this.$el},initHandlersForProperties:function(){CommonButtonView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:href",this.updateHref),this.listenTo(this.model,"change:target",this.updateTarget)},updateHref:function(){var e=this.model.get("href"),t=this.getButtonElement();t.attr("href",e)},updateTarget:function(){var e=this.model.get("target"),t=this.getButtonElement();t.attr("target","_"+e)},onClickHandler:function(e){var t=this.model.get("href");t.indexOf("http://")===-1&&(InfinniUI.AppRouter.navigate(t,{trigger:!0}),2!==e.which&&e.preventDefault())}});!function(){var e=InfinniUI.Template["controls/loaderIndicator/template.tpl.html"];InfinniUI.loaderIndicator={show:function(){$.blockUI({message:$(e()),ignoreIfBlocked:!0,baseZ:99999})},hide:function(){$.unblockUI()}},InfinniUI.config.useLoaderIndicator&&jQuery(function(){var t=$(e());$("body").append(t),$.blockUI.defaults.css={},$(document).ajaxStart(function(){$.blockUI({message:t,ignoreIfBlocked:!0,baseZ:99999})}).ajaxStop(function(){$.unblockUI()}).ajaxError(function(){$.unblockUI()})})}(),_.inherit(MenuBarControl,ContainerControl),_.extend(MenuBarControl.prototype,{createControlModel:function(){return new MenuBarModel},createControlView:function(e){return new MenuBarView({model:e})}});var MenuBarModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),MenuBarView=ContainerView.extend({tagName:"nav",className:"pl-menu-bar navbar navbar-default",template:InfinniUI.Template["controls/menuBar/template/menuBar.tpl.html"],UI:{},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.$el.html(this.template({items:this.model.get("items")})),this.renderItemsContents(),this.bindUIElements(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItemsContents:function(){var e,t,n=this.$el.find(".pl-menu-bar-item"),i=this.model.get("items"),o=this.model.get("itemTemplate"),r=this;n.each(function(n,a){t=i.getByIndex(n),e=o(void 0,{item:t,index:n}),r.addChildElement(e),$(a).append(e.render())})},updateGrouping:function(){}});_.inherit(NumericBoxControl,TextEditorBaseControl),_.extend(NumericBoxControl.prototype,{createControlModel:function(){return new NumericBoxModel},createControlView:function(e){return new NumericBoxView({model:e})}});var NumericBoxModel=TextEditorBaseModel.extend({defaults:_.defaults({increment:1,inputType:"number"},TextEditorBaseModel.prototype.defaults),incValue:function(){var e=this.get("increment");this.addToValue(e)},decValue:function(){var e=this.get("increment");this.addToValue(-e)},addToValue:function(e){var t=this.get("value"),n=this.get("startValue"),i=this.get("minValue"),o=this.get("maxValue"),r=_.isNumber(t)?t:+t;this.isSetValue(t)&&_.isNumber(t)?r+=e:r=_.isNumber(n)?n:0,_.isNumber(i)&&ro&&(r=o),this.set("value",r)},initialize:function(){TextEditorBaseModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))},validateValue:function(e,t){var n=!0,i=this.get("minValue"),o=this.get("maxValue");return!this.isSetValue(e)||(_.isNumber(i)&&_.isNumber(o)?(eo)&&(n=!1):_.isNumber(i)&&eo&&(n=!1),n)}}),NumericBoxView=TextEditorBaseView.extend({className:"pl-numericbox form-group",template:InfinniUI.Template["controls/numericBox/template/numericBox.tpl.html"],UI:_.extend({},TextEditorBaseView.prototype.UI,{min:".pl-numeric-box-min",max:".pl-numeric-box-max"}),events:_.extend({},TextEditorBaseView.prototype.events,{"click .pl-numeric-box-min":"onClickMinControlHandler","click .pl-numeric-box-max":"onClickMaxControlHandler","mousedown .pl-numeric-box-min":"onMousedownMinControlHandler","mousedown .pl-numeric-box-max":"onMousedownMaxControlHandler"}),render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.renderNumericBoxEditor(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},getData:function(){var e=this.model;return _.extend({},TextEditorBaseView.prototype.getData.call(this),{minValue:e.get("minValue"),maxValue:e.get("maxValue"),increment:e.get("increment")})},renderNumericBoxEditor:function(){this.renderControlEditor()},onChangeEnabledHandler:function(e,t){this.ui.control.prop("disabled",!t),this.ui.min.prop("disabled",!t),this.ui.max.prop("disabled",!t)},onClickMinControlHandler:function(){this.canChangeValue()&&this.model.decValue()},onClickMaxControlHandler:function(){this.canChangeValue()&&this.model.incValue()},onMousedownMinControlHandler:function(e){this.canChangeValue()&&this.repeatUpdateValue(this.model.decValue.bind(this.model))},onMousedownMaxControlHandler:function(e){this.canChangeValue()&&this.repeatUpdateValue(this.model.incValue.bind(this.model))},repeatUpdateValue:function(e){function t(){n&&(clearInterval(n),n=null),window.document.removeEventListener("mouseup",t)}var n;window.document.addEventListener("mouseup",t),n=setInterval(e,200)},canChangeValue:function(){var e=this.model,t=e.get("enabled");return t===!0}});_.inherit(PanelControl,ContainerControl),_.extend(PanelControl.prototype,{createControlModel:function(){return new PanelModel},createControlView:function(e){return new PanelView({model:e})}});var PanelModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments)),this.on("change:collapsed",function(e,t){e.trigger(t?"collapsed":"expanded",null,{})})},defaults:_.defaults({collapsible:!1,collapsed:!1,collapsibleArea:""},ContainerModel.prototype.defaults),set:function(e,t,n){if(null==e)return this;var i;"object"==typeof e?(i=e,n=t):(i={})[e]=t;var o,r;if("collapsed"in i){o=this.get("collapsed"),r=i.collapsed;var a;r&&!o?a=this.set("_collapsing",!0,{validate:!1}).trigger("collapsing",null,{}).get("_collapsing"):!r&&o&&(a=this.set("_expanding",!0,{validate:!1}).trigger("expanding",null,{}).get("_expanding")),a===!1&&delete i.collapsed}return ContainerModel.prototype.set.call(this,i,n)},on:function(e,t,n){var i,o=this;switch(e){case"collapsing":i=function(){var e=t(null,{});e===!1&&o.set("_collapsing",!1)};break;case"expanding":i=function(){var e=t(null,{});e===!1&&o.set("_expanding",!1)};break;default:i=t}ContainerModel.prototype.on.call(this,e,i,n)}}),PanelView=ContainerView.extend({className:"pl-panel panel panel-default",template:InfinniUI.Template["controls/panel/template/panel.tpl.html"],UI:{header:".pl-panel-header",items:".panel-items"},events:{"click >.pl-panel-header":"onClickHeaderHandler"},initialize:function(e){ContainerView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.$el.html(this.template({items:this.model.get("items")})),this.bindUIElements(),this.renderItemsContents(),this.trigger("render"),this.updateProperties(),this.postrenderingActions(),this},initHandlersForProperties:function(){ContainerView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:collapsed",this.updateCollapsed),this.listenTo(this.model,"change:collapsible",this.updateCollapsible),this.listenTo(this.model,"change:header",this.updateHeader)},updateProperties:function(){ContainerView.prototype.updateProperties.call(this),this.updateCollapsed(),this.updateCollapsible(),this.updateHeader()},updateCollapsed:function(){this.ui.header.toggleClass("pl-collapsed",this.model.get("collapsed"))},updateCollapsible:function(e,t){this.ui.header.toggleClass("pl-collapsible",this.model.get("collapsible"))},updateHeader:function(){var e=this.model;this.ui.header.empty();var t=e.get("headerTemplate");if("function"==typeof t){var n=e.get("header");this.ui.header.append(t(null,{value:n}).render())}},renderItemsContents:function(){var e,t,n=this.$el.find(".pl-panel-i"),i=this.model.get("items"),o=this.model.get("itemTemplate"),r=this;n.each(function(n,a){t=i.getByIndex(n),e=o(void 0,{item:t,index:n}),r.addChildElement(e),$(a).append(e.render())})},updateGrouping:function(){},onEventCallback:function(){var e=this.model.get("collapsible");if(e){var t=this.model.get("collapsed");this.model.set("collapsed",!t),this.updateLayout()}},onClickHeaderHandler:function(e){var t=this.model.get("collapsibleArea");""!==t?$(e.target).closest("[data-pl-name="+t+"]").length&&this.onEventCallback():this.onEventCallback()}}),PasswordBoxControl=function(){_.superClass(PasswordBoxControl,this),this.initialize_editorBaseControl()};_.inherit(PasswordBoxControl,Control),_.extend(PasswordBoxControl.prototype,{createControlModel:function(){return new PasswordBoxModel},createControlView:function(e){return new PasswordBoxView({model:e})}},editorBaseControlMixin);var PasswordBoxModel=ControlModel.extend(_.extend({defaults:_.defaults({autocomplete:!0},editorBaseModelMixin.defaults_editorBaseModel,ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.initialize_editorBaseModel()}},editorBaseModelMixin)),PasswordBoxView=ControlView.extend(_.extend({},editorBaseViewMixin,{className:"pl-password-box form-group",template:{autocomplete:InfinniUI.Template["controls/passwordBox/template/passwordBox.on.tpl.html"],noautocomplete:InfinniUI.Template["controls/passwordBox/template/passwordBox.off.tpl.html"]},UI:_.extend({},editorBaseViewMixin.UI,{label:".pl-control-label",input:".pl-control"}),events:{"blur .pl-control":"onBlurHandler","input .pl-control":"onInputHandler","change .pl-control":"onChangeHandler"},initialize:function(){ControlView.prototype.initialize.apply(this)},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),editorBaseViewMixin.initHandlersForProperties.call(this),this.listenTo(this.model,"change:labelText",this.updateLabelText),this.listenTo(this.model,"change:labelFloating",this.updateLabelFloating),this.listenTo(this.model,"change:autocomplete",this.updateAutocomplete)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),editorBaseViewMixin.updateProperties.call(this),this.updateLabelText()},updateLabelText:function(){var e=this.model.get("labelText");this.ui.label.text(e)},updateAutocomplete:function(){this.rerender()},updateValue:function(){editorBaseViewMixin.updateValueState.call(this);var e=this.model.get("value");this.ui.input.val(e)},updateEnabled:function(){ControlView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");this.ui.input.prop("disabled",!e)},getData:function(){return _.extend({},ControlView.prototype.getData.call(this),editorBaseViewMixin.getData.call(this))},render:function(){this.model;return this.prerenderingActions(),this.renderTemplate(this.getTemplate()),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},remove:function(){ControlView.prototype.remove.call(this)},getTemplate:function(){var e=this.model;return e.get("autocomplete")?this.template.autocomplete:this.template.noautocomplete},updateModelValue:function(){var e=this.ui.input.val(),t=this.model;t.set("value",e),t.set("rawValue",e)},onBlurHandler:function(){this.updateModelValue()},onChangeHandler:function(){this.updateModelValue()},onInputHandler:function(){this.updateModelValue()}}));_.inherit(ScrollPanelControl,ContainerControl),_.extend(ScrollPanelControl.prototype,{createControlModel:function(){return new ScrollPanelModel},createControlView:function(e){return new ScrollPanelView({model:e})}});var ScrollPanelModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))},defaults:_.defaults({verticalAlignment:"Stretch",horizontalScroll:InfinniUI.ScrollVisibility.auto,verticalScroll:InfinniUI.ScrollVisibility.auto},ContainerModel.prototype.defaults)}),ScrollPanelView=ContainerView.extend({className:"pl-scrollpanel panel panel-default",template:InfinniUI.Template["controls/scrollPanel/template/scrollPanel.tpl.html"],UI:{},initialize:function(e){ContainerView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.$el.html(this.template({items:this.model.get("items")})),this.renderItemsContents(),this.bindUIElements(),this.postrenderingActions(),this.trigger("render"),this.updateProperties(),function(e){setTimeout(function(){e.scrollTop(0)},0)}(this.$el),this},initHandlersForProperties:function(){ContainerView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:horizontalScroll",this.updateHorizontalScroll),this.listenTo(this.model,"change:verticalScroll",this.updateVerticalScroll)},updateProperties:function(){ContainerView.prototype.updateProperties.call(this),this.updateHorizontalScroll(),this.updateVerticalScroll()},updateHorizontalScroll:function(){var e="";switch(this.model.get("horizontalScroll")){case InfinniUI.ScrollVisibility.visible:e="visible";break;case InfinniUI.ScrollVisibility.hidden:e="hidden";break;case InfinniUI.ScrollVisibility.auto:default:e="auto"}this.switchClass("pl-horizontal-scroll",e,this.$el)},updateVerticalScroll:function(e,t){var n="";switch(this.model.get("verticalScroll")){case InfinniUI.ScrollVisibility.visible:n="visible";break;case InfinniUI.ScrollVisibility.hidden:n="hidden";break;case InfinniUI.ScrollVisibility.auto:default:n="auto"}this.switchClass("pl-vertical-scroll",n,this.$el)},renderItemsContents:function(){var e,t,n=this.$el.find(".pl-scrollpanel-i"),i=this.model.get("items"),o=this.model.get("itemTemplate"),r=this;n.each(function(n,a){t=i.getByIndex(n),e=o(void 0,{item:t,index:n}),r.addChildElement(e),$(a).append(e.render())})},updateGrouping:function(){}});_.inherit(ToggleButtonControl,Control),_.extend(ToggleButtonControl.prototype,{createControlModel:function(){return new ToggleButtonModel},createControlView:function(e){return new ToggleButtonView({model:e})}},editorBaseControlMixin);var ToggleButtonModel=ControlModel.extend(_.extend({defaults:_.defaults({value:!1,textOn:"ON",textOff:"OFF",horizontalAlignment:"Left"},ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.initialize_editorBaseModel()}},editorBaseModelMixin)),ToggleButtonView=ControlView.extend(_.extend({},editorBaseViewMixin,{template:InfinniUI.Template["controls/toggleButton/template/toggleButton.tpl.html"],UI:_.extend({},editorBaseViewMixin.UI,{textOn:".togglebutton-handle-on",textOff:".togglebutton-handle-off",container:".togglebutton-container"}),events:{"click .togglebutton-box":"onClickHandler"},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),editorBaseViewMixin.initHandlersForProperties.call(this),this.listenTo(this.model,"change:textOn",this.updateTextOn),this.listenTo(this.model,"change:textOff",this.updateTextOff)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),editorBaseViewMixin.updateProperties.call(this),this.updateTextOn(),this.updateTextOff()},updateFocusable:function(){var e=this.model.get("focusable");e?this.ui.container.attr("tabindex",0):this.ui.container.removeAttr("tabindex")},updateTextOn:function(){var e=this.model.get("textOn");this.ui.textOn.html(e||" ")},updateTextOff:function(){var e=this.model.get("textOff");this.ui.textOff.html(e||" ")},render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},getData:function(){var e=this.model;return _.extend({},ControlView.prototype.getData.call(this),editorBaseViewMixin.getData.call(this),{textOn:e.get("textOn"),textOff:e.get("textOff")})},onClickHandler:function(e){var t=this.model;t.set("value",!t.get("value"))},updateValue:function(){var e=this.model.get("value");this.switchClass("toggle",e?"on":"off",this.$el)}}));_.inherit(ToolBarControl,ContainerControl),_.extend(ToolBarControl.prototype,{createControlModel:function(){return new ToolBarModel},createControlView:function(e){return new ToolBarView({model:e})}});var ToolBarModel=ContainerModel.extend({}),ToolBarView=ContainerView.extend({className:"pl-tool-bar",template:InfinniUI.Template["controls/toolBar/template/toolBar.tpl.html"],itemTemplate:InfinniUI.Template["controls/toolBar/template/toolBarItem.tpl.html"],UI:{container:".pl-tool-bar__container"},render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.ui.container.append(this.renderItems()),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItems:function(){var e=this.model,t=e.get("items"),n=e.get("itemTemplate");this.removeChildElements();var i=[];return t.forEach(function(e,t){var o=this.itemTemplate(),r=$(o),a=n(null,{index:t,item:e});this.addChildElement(a),r.append(a.render()),i.push(r)},this),i},updateGrouping:function(){}});_.inherit(ViewControl,ContainerControl),_.extend(ViewControl.prototype,{createControlModel:function(){return new ViewModel},createControlView:function(e){return new ViewView({model:e})}});var DialogResult={none:0,accepted:1,canceled:2};window.InfinniUI.DialogResult=DialogResult;var ViewModel=ContainerModel.extend({defaults:_.defaults({dialogResult:DialogResult.none,isApplication:!1,closeButtonVisibility:!0},ContainerModel.prototype.defaults),initialize:function(){ContainerModel.prototype.initialize.apply(this),this.set("scripts",new Collection([],"name")),this.set("parameters",new Collection([],"name")),this.set("dataSources",new Collection([],"name"))}}),ViewView=ContainerView.extend({className:"pl-view",initialize:function(e){ContainerView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.$el.empty(),this.renderItemsContents(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItemsContents:function(){var e,t=this,n=this.model.get("items"),i=this.model.get("itemTemplate");n.forEach(function(n,o){e=i(void 0,{item:n,index:o}),e&&t.$el.append(e.render())})},updateGrouping:function(){}}),ViewPanelControl=function(){_.superClass(ViewPanelControl,this)};_.inherit(ViewPanelControl,Control),ViewPanelControl.prototype.createControlModel=function(){return new ViewPanelModel},ViewPanelControl.prototype.createControlView=function(e){return new ViewPanelView({model:e})};var ViewPanelModel=ControlModel.extend({defaults:_.defaults({layout:null},ControlModel.prototype.defaults),initialize:function(){var e=this;ControlModel.prototype.initialize.apply(this),this.once("change:layout",function(t,n){n&&n.onLoaded&&e.subscribeOnLoaded()})},subscribeOnLoaded:function(){var e=this,t=this.get("layout");t.onLoaded(function(){e.set("isLoaded",!0)})}}),ViewPanelView=ControlView.extend({className:"pl-view-panel",initialize:function(){ControlView.prototype.initialize.apply(this),this.listenTo(this.model,"change:layout",this.onChangeLayoutHandler)},onChangeLayoutHandler:function(e,t){this.$el.empty(),t&&this.$el.append(t.render())},render:function(){this.prerenderingActions();var e=this.model.get("layout");return e&&this.$el.append(e.render()),this.updateProperties(),this.trigger("render"),this.postrenderingActions(!1),this}}),DataSourceValidationNotifierMixin={initNotifyValidation:function(e){e.onErrorValidator(this.notifyOnValidationError.bind(this))},notifyOnValidationError:function(e,t){var n=t.value;"undefined"!=typeof n&&null!==n&&!n.IsValid&&Array.isArray(n.Items)&&n.Items.forEach(function(e){var t=window.InfinniUI.global.messageBus;t.send(messageTypes.onNotifyUser,{item:e,messageText:e.Message,messageType:"error"})})}},BaseDataSource=Backbone.Model.extend({defaults:{name:null,idProperty:"_id",identifyingMode:"byId",view:null,isDataReady:!1,dataProvider:null,model:null,modifiedItems:{},itemsById:{},fillCreatedItem:!0,suspendingList:null,waitingOnUpdateItemsHandlers:null,errorValidator:null,isRequestInProcess:!1,isLazy:!0,isWaiting:!1,resolvePriority:0,newItemsHandler:null,isNumRegEx:/^\d/},initialize:function(){var e=this.get("view"),t={items:null,selectedItem:null};if(this.initDataProvider(),!e)throw"BaseDataSource.initialize: При создании объекта не была задана view.";this.set("suspendingList",[]),this.set("waitingOnUpdateItemsHandlers",[]),this.set("model",new TreeModel(e.getContext(),this,t)),_.extend(this,BaseDataSource.identifyingStrategy.byId)},initDataProvider:function(){throw"BaseDataSource.initDataProvider В потомке BaseDataSource не задан провайдер данных."},onPropertyChanged:function(e,t,n){"function"==typeof e&&(n=t,t=e,e="*"),e="."==e.charAt(0)?e.substr(1):""==e?"items":"items."+e,this.get("model").onPropertyChanged(e,function(e,n){var i=n.property;i="items."==i.substr(0,6)?i.substr(6):"items"==i?"":"."+i,n.property=i,t(e,n)},n)},onSelectedItemChanged:function(e,t){var n=this;this.get("model").onPropertyChanged("selectedItem",function(t,i){var o=n._getArgumentTemplate();o.value=i.newValue,e(t,o)},t)},onErrorValidator:function(e){this.on("onErrorValidator",e)},onItemSaved:function(e){this.on("onItemSaved",e)},onItemCreated:function(e){this.on("onItemCreated",e)},onItemsUpdated:function(e){this.on("onItemsUpdated",e)},onItemsUpdatedOnce:function(e){this.once("onItemsUpdated",e)},onItemDeleted:function(e){this.on("onItemDeleted",e)},onProviderError:function(e){this.on("onProviderError",e)},getName:function(){return this.get("name")},setName:function(e){this.set("name",e),this.name=e},getView:function(){return this.get("view")},getProperty:function(e){var t,n=e.charAt(0);if(this.get("isNumRegEx").test(n))e="items."+e;else if(""==n)e="items";else if("$"==n){if(t=this._indexOfSelectedItem(),t==-1)return;e="items."+t+e.substr(1)}else if("."==n)e=e.substr(1);else{if(t=this._indexOfSelectedItem(),t==-1)return;e="items."+t+"."+e}return this.get("model").getProperty(e)},setProperty:function(e,t){var n,i,o,r=e.split(".");if("$"==r[0]){if(i=this._indexOfSelectedItem(),i==-1)return;e=i+e.substr(1),r[0]=i.toString()}if(n=e.charAt(0),1==r.length)if(""==r[0])this._setItems(t);else if(this.get("isNumRegEx").test(r[0]))this._changeItem(r[0],t);else{if(i=this._indexOfSelectedItem(),i==-1)return;e="items."+i+"."+e,o=this.get("model").setProperty(e,t),o&&this._includeItemToModifiedSetByIndex(i)}else if("."==n)e=e.substr(1),this.get("model").setProperty(e,t);else if(this.get("isNumRegEx").test(n))e="items."+e,o=this.get("model").setProperty(e,t), -o&&this._includeItemToModifiedSetByIndex(parseInt(r[0]));else{if(i=this._indexOfSelectedItem(),i==-1)return;e="items."+i+"."+e,o=this.get("model").setProperty(e,t),o&&this._includeItemToModifiedSetByIndex(i)}},_setItems:function(e){this._detectIdentifyingMode(e);var t;this.set("isDataReady",!0),this.get("model").setProperty("items",e),this._clearModifiedSet(),e&&e.length>0?(t=this._indexItemsById(e),this.set("itemsById",t),this._restoreSelectedItem()||this.setSelectedItem(e[0])):this.setSelectedItem(null)},_restoreSelectedItem:function(){var e=window.InfinniUI.global.logger;e.warn({message:"BaseDataSource._restoreSelectedItem: not overrided by strategy",source:this})},getSelectedItem:function(){return this.get("model").getProperty("selectedItem")},setSelectedItem:function(e,t,n){var i=window.InfinniUI.global.logger;i.warn({message:"BaseDataSource.setSelectedItem: not overrided by strategy",source:this})},_notifyAboutSelectedItem:function(e,t){var n=this.getContext(),i=this._getArgumentTemplate();i.value=e,t&&t(n,i)},_tuneMirroringOfModel:function(e){e!=-1?this.get("model").setMirroring("items.$","items."+e):this.get("model").setMirroring(null,null)},getIdProperty:function(){return this.get("idProperty")},setIdProperty:function(e){this.set("idProperty",e)},getFillCreatedItem:function(){return this.get("fillCreatedItem")},setFillCreatedItem:function(e){this.set("fillCreatedItem",e)},suspendUpdate:function(e){var t=e||"default",n=this.get("suspendingList");n.indexOf(t)===-1&&(n=n.slice(0),n.push(t),this.set("suspendingList",n))},resumeUpdate:function(e){var t=e||"default",n=this.get("suspendingList"),i=n.indexOf(t);i!==-1&&(n=n.slice(0),n.splice(i,1),this.set("suspendingList",n),!this.isUpdateSuspended()&&this.get("waitingOnUpdateItemsHandlers").length>0&&this.updateItems())},isUpdateSuspended:function(){var e=this.get("suspendingList");return e.length>0},isModifiedItems:function(){return this.isModified()},isModified:function(e){if(0==arguments.length)return _.size(this.get("modifiedItems"))>0;if(null===e||void 0===e)return!1;var t=this.idOfItem(e);return t in this.get("modifiedItems")},_includeItemToModifiedSetByIndex:function(e){var t;t=this.getItems()[e],this._includeItemToModifiedSet(t)},_includeItemToModifiedSet:function(e){var t=window.InfinniUI.global.logger;t.warn({message:"BaseDataSource._includeItemToModifiedSet: not overrided by strategy",source:this})},_excludeItemFromModifiedSet:function(e){var t=window.InfinniUI.global.logger;t.warn({message:"BaseDataSource._excludeItemFromModifiedSet: not overrided by strategy",source:this})},_clearModifiedSet:function(){this.set("modifiedItems",{})},_checkPropertyName:function(e){var t=!0;try{if(e&&e.length>0&&(t=e.match(/^[\$#@\d]+/)),!t)throw new Error('Wrong property name "'+e+'"')}catch(n){console.debug(n)}},_changeItem:function(e,t){var n=this.get("model").getProperty("items."+e),i=n==this.getSelectedItem(),o=this.get("idProperty"),r=this.get("itemsById");t!=n&&(this._excludeItemFromModifiedSet(n),delete r[n[o]],this.get("model").setProperty("items."+e,t),this._includeItemToModifiedSet(t),r[t[o]]=t,this.set("itemsById",r),i&&this.get("model").setProperty("selectedItem",t))},tryInitData:function(){this.get("isDataReady")||this.get("isRequestInProcess")||this.updateItems()},saveItem:function(e,t,n){var i,o=this.get("dataProvider"),r=(window.InfinniUI.global.logger,this),a=this._compensateOnErrorOfProviderHandler(n);return this.isModified(e)?(i=this.validateOnErrors(e),i.IsValid?void o.saveItem(e,function(i){if("IsValid"in i&&i.IsValid!==!0){var o=r._getValidationResult(i);r._notifyAboutValidation(o,"error"),r._executeCallback(n,{item:e,result:o})}else r._excludeItemFromModifiedSet(e),r._notifyAboutItemSaved({item:e,result:i.data},"modified"),r._executeCallback(t,{item:e,result:r._getValidationResult(i)})},function(t){var n=r._getValidationResult(t);r._notifyAboutValidation(n,"error"),r._executeCallback(a,{item:e,result:n})}):void this._executeCallback(n,{item:e,result:i})):(this._notifyAboutItemSaved({item:e,result:null},"notModified"),void r._executeCallback(t,{item:e,result:{IsValid:!0}}))},_getValidationResult:function(e){return e.data&&e.data.responseJSON&&e.data.responseJSON.Result?e.data.responseJSON.Result.ValidationResult:e.data&&e.data.Result&&e.data.Result.ValidationResult},_executeCallback:function(e,t){e&&e(this.getContext(),t)},_notifyAboutItemSaved:function(e,t){var n=this.getContext(),i=this._getArgumentTemplate();i.value=e,i.result=t,this.trigger("onItemSaved",n,i)},deleteItem:function(e,t,n){var i=this.get("dataProvider"),o=this,r=this.idOfItem(e),a=void 0!==this.get("itemsById")[r],l=this._compensateOnErrorOfProviderHandler(n);return null==e||void 0!==r&&!a?void this._notifyAboutMissingDeletedItem(e,n):(this.beforeDeleteItem(e),void i.deleteItem(e,function(i){if("IsValid"in i&&i.IsValid!==!0){var r=o._getValidationResult(i);o._notifyAboutValidation(r,"error"),o._executeCallback(n,{item:e,result:r})}else o._handleDeletedItem(e,t)},function(t){var n=o._getValidationResult(t);o._notifyAboutValidation(n,"error"),o._executeCallback(l,{item:e,result:n})}))},beforeDeleteItem:function(e){},_handleDeletedItem:function(e,t){var n=window.InfinniUI.global.logger;n.warn({message:"BaseDataSource._handleDeletedItem: not overrided by strategy",source:this})},_notifyAboutItemDeleted:function(e,t){var n=this.getContext(),i=this._getArgumentTemplate();i.value=e,t&&t(n,i),this.trigger("onItemDeleted",n,i)},_notifyAboutMissingDeletedItem:function(e,t){var n=this.getContext(),i=this._getArgumentTemplate();i.value=e,i.error={message:"Нельзя удалить элемент, которого нет текущем наборе источника данных"},t&&t(n,i)},isDataReady:function(){return this.get("isDataReady")},getItems:function(){var e=window.InfinniUI.global.logger;return this.isDataReady()||e.warn({message:"BaseDataSource: Попытка получить данные источника данных ("+this.get("name")+"), до того как он был проинициализирован данными",source:this}),this.get("model").getProperty("items")},updateItems:function(e,t){if(this.isUpdateSuspended()){var n=this.get("waitingOnUpdateItemsHandlers");n.push({onSuccess:e,onError:t})}else{var i=this.get("dataProvider"),o=this;t=this._compensateOnErrorOfProviderHandler(t),this.set("isRequestInProcess",!0),i.getItems(function(n){o._handleSuccessUpdateItemsInProvider(n,e,t)},t)}},_compensateOnErrorOfProviderHandler:function(e){var t=this;return function(){"function"==typeof e?e.apply(void 0,arguments):t.trigger("onProviderError",arguments)}},_handleSuccessUpdateItemsInProvider:function(e,t,n){var i=this,o=i.get("isWaiting"),r=function(){i.set("isRequestInProcess",!1),i._handleUpdatedItemsData(e.data,t,n)};o?i.once("change:isWaiting",function(){r()}):r()},_onErrorProviderUpdateItemsHandle:function(){},setIsWaiting:function(e){this.set("isWaiting",e)},_handleUpdatedItemsData:function(e,t,n){this.get("newItemsHandler")&&(e=this.get("newItemsHandler")(e)),this.setProperty("",e),this._notifyAboutItemsUpdated(e,t,n)},_notifyAboutItemsUpdated:function(e,t,n){for(var i=this.getContext(),o={value:e,source:this},r=this.get("waitingOnUpdateItemsHandlers"),a=0,l=r.length;a0?!$.isPlainObject(e[0])||this.getIdProperty()in e[0]?(this.set("identifyingMode","byId"),_.extend(this,BaseDataSource.identifyingStrategy.byId)):(this.set("identifyingMode","byLink"),_.extend(this,BaseDataSource.identifyingStrategy.byLink)):(this.set("identifyingMode","byId"),_.extend(this,BaseDataSource.identifyingStrategy.byId))},_getIdentifyingMode:function(){return this.get("identifyingMode")}});BaseDataSource.identifyingStrategy={byId:{_restoreSelectedItem:function(){var e=this.getSelectedItem(),t=this.idOfItem(e);if(null!=t){var n=this.get("itemsById"),i=n[t];if(null!=i)return this.setSelectedItem(i),!0}return!1},setSelectedItem:function(e,t,n){var i,o=this.getSelectedItem(),r=this.get("itemsById"),a=this.idOfItem(e);if("undefined"==typeof e&&(e=null),e!=o){if(null!==e&&!r[a]){if(n)return void n(this.getContext(),{error:"BaseDataSource.setSelectedItem() Попытка выбрать элемент в источнике, которого нет среди элементов этого источника."});throw"BaseDataSource.setSelectedItem() Попытка выбрать элемент в источнике, которого нет среди элементов этого источника."}this.get("model").setProperty("selectedItem",e),i=this._indexOfItem(r[a]),this._tuneMirroringOfModel(i),this._notifyAboutSelectedItem(e,t)}},_includeItemToModifiedSet:function(e){var t=this.idOfItem(e);this.get("modifiedItems")[t]=e},_excludeItemFromModifiedSet:function(e){var t=this.idOfItem(e);delete this.get("modifiedItems")[t]},_handleDeletedItem:function(e,t){for(var n=this.getItems(),i=this.get("idProperty"),o=this.idOfItem(e),r=this.getSelectedItem(),a=0,l=n.length,s=!1;a=0&&(n.splice(o,1),this._excludeItemFromModifiedSet(e),i&&i==e&&this.setSelectedItem(null)),this._notifyAboutItemDeleted(e,t)}}},window.InfinniUI.BaseDataSource=BaseDataSource;var RestDataSource=BaseDataSource.extend({defaults:_.defaults({updatingItemsConverter:null},BaseDataSource.prototype.defaults),initialize:function(){BaseDataSource.prototype.initialize.apply(this,Array.prototype.slice.call(arguments));var e=this.get("model");e.urlParams={get:{method:"get",origin:null,path:"",data:{},params:{}},set:{method:"post",origin:null,path:"",data:{},params:{}},"delete":{method:"delete",origin:null,path:"",data:{},params:{}}},this.initUrlParamsHandlers()},initDataProvider:function(){var e=window.InfinniUI.providerRegister.build("RestDataSource");this.set("dataProvider",e)},initUrlParamsHandlers:function(){var e=this;this.get("model").onPropertyChanged("urlParams.get.*",function(t,n){var i,o=e.get("dataProvider"),r=e.getGettingUrlParams();o.setOrigin("get",r.origin),i=e._templateParamsInStr(r.path,r.params),o.setPath("get",i),i=e._templateParamsInObject(r.data,r.params),o.setData("get",i),(e.get("isDataReady")||e.get("isRequestInProcess")||e.get("waitingOnUpdateItemsHandlers").length>0)&&e.updateItems()}),this.get("model").onPropertyChanged("urlParams.set.*",function(t,n){var i,o=e.get("dataProvider"),r=e.getSettingUrlParams();o.setOrigin("set",r.origin),i=e._templateParamsInStr(r.path,r.params),o.setPath("set",i),i=e._templateParamsInObject(r.data,r.params),o.setData("set",i)}),this.get("model").onPropertyChanged("urlParams.delete.*",function(t,n){var i,o=e.get("dataProvider"),r=e.getDeletingUrlParams();o.setOrigin("delete",r.origin),i=e._templateParamsInStr(r.path,r.params),o.setPath("delete",i),i=e._templateParamsInObject(r.data,r.params),o.setData("delete",i)})},updateItems:function(){this._checkGettingUrlParamsReady()?(BaseDataSource.prototype.updateItems.apply(this,Array.prototype.slice.call(arguments)),this.resumeUpdate("urlGettingParamsNotReady")):(this.suspendUpdate("urlGettingParamsNotReady"),BaseDataSource.prototype.updateItems.apply(this,Array.prototype.slice.call(arguments)))},getGettingUrlParams:function(e){return e=0==arguments.length?"urlParams.get":""==e?"urlParams.get":"urlParams.get."+e,this.get("model").getProperty(e)},setGettingUrlParams:function(e,t){1==arguments.length?(t=e,e="urlParams.get"):e=""==e?"urlParams.get":"urlParams.get."+e,this.get("model").setProperty(e,t)},getSettingUrlParams:function(e){return e=0==arguments.length?"urlParams.set":""==e?"urlParams.set":"urlParams.set."+e,this.get("model").getProperty(e)},setSettingUrlParams:function(e,t){1==arguments.length?(t=e,e="urlParams.set"):e=""==e?"urlParams.set":"urlParams.set."+e,this.get("model").setProperty(e,t)},getDeletingUrlParams:function(e){return e=0==arguments.length?"urlParams.delete":""==e?"urlParams.delete":"urlParams.delete."+e,this.get("model").getProperty(e)},setDeletingUrlParams:function(e,t){1==arguments.length?(t=e,e="urlParams.delete"):e=""==e?"urlParams.delete":"urlParams.delete."+e,this.get("model").setProperty(e,t)},_checkGettingUrlParamsReady:function(){var e,t,n,i,o,r=[];if(!this._checkUrlParamsReady(this.getGettingUrlParams()))return!1;e=this.getGettingUrlParams("path"),t=this._findSubstitutionParams(e),r=r.concat(t),n=this.getGettingUrlParams("data"),e=JSON.stringify(n),t=this._findSubstitutionParams(e),r=r.concat(t),i=this.getGettingUrlParams("params");for(var a=0,l=r.length;a/g,function(e,n){return t.push(n),e}),t},_templateParamsInStr:function(e,t){return e&&t?e.replace(/<%([\s\S]+?)%>/g,function(e,n){return t[n]}):e},_templateParamsInObject:function(e,t){if(!e||!t)return e;var n=JSON.stringify(e),i=this._templateParamsInStr(n,t);return JSON.parse(i)},getUpdatingItemsConverter:function(){return this.get("updatingItemsConverter")},setUpdatingItemsConverter:function(e){this.set("updatingItemsConverter",e)},_handleUpdatedItemsData:function(e,t,n){var i,o=this.getUpdatingItemsConverter();i=o?o(e):e,BaseDataSource.prototype._handleUpdatedItemsData.call(this,i,t,n)}});window.InfinniUI.RestDataSource=RestDataSource;var DocumentDataSource=RestDataSource.extend({defaults:_.defaults({documentId:null},RestDataSource.prototype.defaults),initialize:function(){RestDataSource.prototype.initialize.apply(this,Array.prototype.slice.call(arguments));var e=this.get("model");e.setProperty("pageNumber",0),e.setProperty("pageSize",15),e.setProperty("filterParams",{}),this.setUpdatingItemsConverter(function(t){return e.setProperty("totalCount",t.Result.Count),t.Result.Items}),this.initHandlers()},initHandlers:function(){var e=this.get("model"),t=this,n=_.bind(this.updateGettingUrlParams,this);e.onPropertyChanged("documentId",function(){t.updateGettingUrlParams(),t.updateSettingUrlParams(),t.updateDeletingUrlParams()}),e.onPropertyChanged("filter",n),e.onPropertyChanged("filterParams.*",n),e.onPropertyChanged("pageNumber",n),e.onPropertyChanged("pageSize",n),e.onPropertyChanged("search",n),e.onPropertyChanged("select",n),e.onPropertyChanged("order",n),e.onPropertyChanged("needTotalCount",n),this.updateGettingUrlParams(),this.updateSettingUrlParams(),this.updateDeletingUrlParams()},updateGettingUrlParams:function(){var e=this.get("model"),t={type:"get",origin:InfinniUI.config.serverUrl,path:"/documents/"+this.get("model").getProperty("documentId"),data:{},params:{}},n=e.getProperty("filter"),i=e.getProperty("filterParams"),o=e.getProperty("pageNumber"),r=e.getProperty("pageSize"),a=e.getProperty("search"),l=e.getProperty("select"),s=e.getProperty("order"),u=e.getProperty("needTotalCount");n&&(t.data.filter=n,i&&_.extend(t.params,i)),r&&(o=o||0,t.data.skip=o*r,t.data.take=r),a&&(t.data.search=a),l&&(t.data.select=l),s&&(t.data.order=s),u&&(t.data.count=u),this.setGettingUrlParams(t)},updateSettingUrlParams:function(){var e=(this.get("model"),{type:"post",origin:InfinniUI.config.serverUrl,path:"/documents/"+this.get("model").getProperty("documentId"),data:{},params:{}});this.setSettingUrlParams(e)},updateDeletingUrlParams:function(){var e=(this.get("model"),{type:"delete",origin:InfinniUI.config.serverUrl,path:"/documents/"+this.get("model").getProperty("documentId")+"/<%id%>",data:{},params:{}});this.setDeletingUrlParams(e)},initDataProvider:function(){var e=window.InfinniUI.providerRegister.build("DocumentDataSource");this.set("dataProvider",e)},getDocumentId:function(){return this.get("model").getProperty("documentId")},setDocumentId:function(e){this.get("model").setProperty("documentId",e)},getFilter:function(){return this.get("model").getProperty("filter")},setFilter:function(e){this.get("model").setProperty("filter",e)},getFilterParams:function(e){return e=0==arguments.length?"filterParams":""==e?"filterParams":"filterParams."+e,this.get("model").getProperty(e)},setFilterParams:function(e,t){1==arguments.length?(t=e,e="filterParams"):e=""==e?"filterParams":"filterParams."+e,this.get("model").setProperty(e,t)},setIdFilter:function(e){this.setFilter("eq("+this.getIdProperty()+","+this.quoteValue(e)+")")},getPageNumber:function(){return this.get("model").getProperty("pageNumber")},setPageNumber:function(e){this.get("model").setProperty("pageNumber",e)},getPageSize:function(){return this.get("model").getProperty("pageSize")},setPageSize:function(e){this.get("model").setProperty("pageSize",e)},getSearch:function(){return this.get("model").getProperty("search")},setSearch:function(e){this.get("model").setProperty("search",e)},getSelect:function(){return this.get("model").getProperty("select")},setSelect:function(e){this.get("model").setProperty("select",e)},getOrder:function(){return this.get("model").getProperty("order")},setOrder:function(e){this.get("model").setProperty("order",e)},getTotalCount:function(){return this.get("model").getProperty("totalCount")},getNeedTotalCount:function(){return this.get("model").getProperty("needTotalCount")},setNeedTotalCount:function(e){this.get("model").setProperty("needTotalCount",e)},beforeDeleteItem:function(e){var t=this.idOfItem(e);void 0!==t&&this.setDeletingUrlParams("params.id",t)},quoteValue:function(e){var t="'";return _.isString(e)?t+e+t:e}});window.InfinniUI.DocumentDataSource=DocumentDataSource;var BaseDataSourceBuilder=function(){};_.extend(BaseDataSourceBuilder.prototype,{build:function(e,t){var n=this.createDataSource(t.parentView);return n.suspendUpdate("tuningInSourceBuilder"),this.applyMetadata(t.builder,t.parentView,t.metadata,n),this.applySuspended(n,t.suspended),n.resumeUpdate("tuningInSourceBuilder"),n},applySuspended:function(e,t){if(t)for(var n in t)t.hasOwnProperty(n)&&e.getName()===n&&e.suspendUpdate(t[n])},applyMetadata:function(e,t,n,i){var o=n.IdProperty;o&&i.setIdProperty(o),i.setName(n.Name),i.setFillCreatedItem(n.FillCreatedItem),"IsLazy"in n&&i.setIsLazy(n.IsLazy),"ResolvePriority"in n&&i.setResolvePriority(n.ResolvePriority),_.isObject(n.CustomProperties)&&this.initCustomProperties(i,n.CustomProperties),this.initValidation(t,i,n),this.initNotifyValidation(i),this.initScriptsHandlers(t,n,i),this.initFileProvider(i)},createDataSource:function(e){throw"BaseDataSourceBuilder.createDataSource В потомке BaseDataSourceBuilder не переопределен метод createDataSource."},initCustomProperties:function(e,t){_.each(t,function(t,n){e.setProperty("."+n,t)})},initValidation:function(e,t,n){n.ValidationErrors&&t.setErrorValidator(function(t,i){return new ScriptExecutor(e).executeScript(n.ValidationErrors.Name||n.ValidationErrors,i)})},initScriptsHandlers:function(e,t,n){e&&(t.OnSelectedItemChanged&&n.onSelectedItemChanged(function(n,i){new ScriptExecutor(e).executeScript(t.OnSelectedItemChanged.Name||t.OnSelectedItemChanged,i)}),t.OnItemsUpdated&&n.onItemsUpdated(function(n,i){new ScriptExecutor(e).executeScript(t.OnItemsUpdated.Name||t.OnItemsUpdated,i)}),t.OnPropertyChanged&&n.onPropertyChanged(function(n,i){new ScriptExecutor(e).executeScript(t.OnPropertyChanged.Name||t.OnPropertyChanged,i)}),t.OnItemDeleted&&n.onItemDeleted(function(){new ScriptExecutor(e).executeScript(t.OnItemDeleted.Name||t.OnItemDeleted)}),t.OnErrorValidator&&n.onErrorValidator(function(){new ScriptExecutor(e).executeScript(t.OnErrorValidator.Name||t.OnErrorValidator)}))},buildBindingBuilder:function(e){return function(t){return e.builder.buildBinding(t,{parentView:e.parentView,basePathOfProperty:e.basePathOfProperty})}},initFileProvider:function(e){var t=InfinniUI.config.serverUrl,n=new DocumentUploadQueryConstructor(t),i=new DocumentFileProvider(n);e.setFileProvider(i)}}),_.extend(BaseDataSourceBuilder.prototype,DataSourceValidationNotifierMixin),window.InfinniUI.BaseDataSourceBuilder=BaseDataSourceBuilder;var RestDataSourceBuilder=function(){_.superClass(RestDataSourceBuilder,this)};_.inherit(RestDataSourceBuilder,BaseDataSourceBuilder),_.extend(RestDataSourceBuilder.prototype,{createDataSource:function(e){return new RestDataSource({view:e})},applyMetadata:function(e,t,n,i){BaseDataSourceBuilder.prototype.applyMetadata.call(this,e,t,n,i);var o;this.initProviderErrorHandling(i),"GettingParams"in n&&(o=this.extractUrlParams(n.GettingParams,".urlParams.get.params"),i.setGettingUrlParams(o),this.bindParams(n.GettingParams,i,t,".urlParams.get.params",e)),"SettingParams"in n&&(o=this.extractUrlParams(n.SettingParams,".urlParams.set.params"),i.setSettingUrlParams(o),this.bindParams(n.SettingParams,i,t,".urlParams.set.params",e)),"DeletingParams"in n&&(o=this.extractUrlParams(n.DeletingParams,".urlParams.delet.params"),i.setDeletingUrlParams(o),this.bindParams(n.DeletingParams,i,t,".urlParams.delet.params",e)),"UpdatingItemsConverter"in n&&i.setUpdatingItemsConverter(function(e){return new ScriptExecutor(t).executeScript(n.UpdatingItemsConverter.Name||n.UpdatingItemsConverter,{value:e,source:i})})},extractUrlParams:function(e,t){var n={};return"Origin"in e?n.origin=e.Origin:n.origin=InfinniUI.config.serverUrl,"Path"in e&&(n.path=e.Path),"Data"in e&&(n.data=e.Data),"Method"in e&&(n.method=e.Method),n.params={},n},bindParams:function(e,t,n,i,o){if("Params"in e){var r=e.Params;for(var a in r)this.initBindingToProperty(r[a],t,n,i+"."+a,o)}},initBindingToProperty:function(e,t,n,i,o){if("object"!=typeof e)void 0!==e&&t.setProperty(i,e);else{var r={parent:n,parentView:n},a=o.buildBinding(e,r);a.setMode(InfinniUI.BindingModes.toElement),a.bindElement(t,i)}},initProviderErrorHandling:function(e){e.onProviderError(function(){var e=window.InfinniUI.global.messageBus;e.send(messageTypes.onNotifyUser,{messageText:"Ошибка на сервере",messageType:"error"})})}}),window.InfinniUI.RestDataSourceBuilder=RestDataSourceBuilder;var DocumentDataSourceBuilder=function(){_.superClass(DocumentDataSourceBuilder,this)};_.inherit(DocumentDataSourceBuilder,BaseDataSourceBuilder),_.extend(DocumentDataSourceBuilder.prototype,{applyMetadata:function(e,t,n,i){if(BaseDataSourceBuilder.prototype.applyMetadata.call(this,e,t,n,i),i.setDocumentId(n.DocumentId),"PageNumber"in n&&i.setPageNumber(n.PageNumber),"PageSize"in n&&i.setPageSize(n.PageSize),"Filter"in n&&i.setFilter(n.Filter),"FilterParams"in n){var o=n.FilterParams;for(var r in o)this.initBindingToProperty(o[r],i,t,".filterParams."+r,e)}"Search"in n&&i.setSearch(n.Search),"Select"in n&&i.setSelect(n.Select),"Order"in n&&i.setOrder(n.Order),"NeedTotalCount"in n&&i.setNeedTotalCount(n.NeedTotalCount),Array.isArray(n.DefaultItems)&&i.setProperty("",n.DefaultItems)},createDataSource:function(e){return new DocumentDataSource({view:e})},initBindingToProperty:RestDataSourceBuilder.prototype.initBindingToProperty}),window.InfinniUI.DocumentDataSourceBuilder=DocumentDataSourceBuilder;var Element=function(e,t){this.parent=e,this.control=this.createControl(t),this.state={Enabled:!0},this.childElements=[]};Object.defineProperties(Element.prototype,{name:{get:function(){return this.getName()}}}),_.extend(Element.prototype,{createControl:function(e){throw"Не перегружен абстрактный метод Element.createControl"},setParent:function(e){this.parent=e},getParent:function(){return this.parent},getChildElements:function(){return this.childElements},findAllChildrenByType:function(e){function t(){return this.constructor.name===e}function n(t){return t.findAllChildrenByType(e)}return this._findAllChildren(t,n)},findAllChildrenByName:function(e){function t(){return this.getName()===e}function n(t){return t.findAllChildrenByName(e)}return this._findAllChildren(t,n)},_findAllChildren:function(e,t){var n=this.getChildElements(),i=[];return Array.isArray(n)&&n.forEach(function(n){e.call(n)&&i.push(n),Array.prototype.push.apply(i,t(n))}),i},getView:function(){return this.parentView||(this.parent&&this.parent.isView?this.parentView=this.parent:this.parent&&this.parent.getView?this.parentView=this.parent.getView():this.parentView=null),this.parentView},getName:function(){return this.control.get("name")},setName:function(e){if(this.getName())throw"name already exists";"string"==typeof e&&this.control.set("name",e)},getProperty:function(e){var t="get"+this._upperFirstSymbol(e);if("function"==typeof this[t])return this[t]();throw"expect that "+t+" is getter function"},setProperty:function(e,t){var n,i="set"+this._upperFirstSymbol(e);if("function"==typeof this[i])this[i](t);else{if(!this._isCollectionProperty(e))throw"expect that "+i+" is setter function";n="get"+this._upperFirstSymbol(e),this[n]().set(t)}},_isCollectionProperty:function(e){var t="get"+this._upperFirstSymbol(e);return"function"==typeof this[t]&&this[t]()instanceof Collection},onPropertyChanged:function(e,t){var n="on"+this._upperFirstSymbol(e)+"Changed";"function"==typeof this[n]?this[n](t):this.control.on("change:"+e,function(n,i){var o=this.getView(),r=o?o.getContext():void 0,a={property:e,oldValue:n.previous(e),newValue:i};t(r,a)}.bind(this))},getText:function(){return this.control.get("text")},setText:function(e){"undefined"!=typeof e&&this.control.set("text",e)},getEnabled:function(){return this.control.get("enabled")},setEnabled:function(e){if("boolean"==typeof e){this.setState("Enabled",e);var t=this.control.get("parentEnabled"),n=this.control.get("enabled");e=t&&e,e!==n&&(this.control.set("enabled",e),this.setParentEnabledOnChild(e))}},setParentEnabledOnChild:function(e){var t=this.getChildElements();if(_.isEmpty(t)===!1)for(var n=0,i=t.length;ni)&&(t="Значение должно быть от "+n+" до "+i):ei&&(t="Значение должно быть меьше "+i):t="Значение должно быть числом",t)},NumericBox.prototype.convertValue=function(e){var t=null===e||""===e||"undefined"==typeof e?null:+e;return _.isNumber(t)?t:null},NumericBox.prototype.getStartValue=function(){ -return this.control.get("startValue")},window.InfinniUI.NumericBoxBuilder=NumericBoxBuilder,_.inherit(NumericBoxBuilder,TextEditorBaseBuilder),NumericBoxBuilder.prototype.createElement=function(e){return new NumericBox(e.parent)},NumericBoxBuilder.prototype.applyMetadata=function(e){TextEditorBaseBuilder.prototype.applyMetadata.call(this,e);var t=e.element,n=e.metadata;t.setMinValue(n.MinValue),t.setMaxValue(n.MaxValue),t.setIncrement(n.Increment),t.setStartValue(n.StartValue)},window.InfinniUI.Panel=Panel,_.inherit(Panel,Container),Panel.prototype.getCollapsible=function(){return this.control.get("collapsible")},Panel.prototype.setCollapsible=function(e){"undefined"!=typeof e&&this.control.set("collapsible",!!e)},Panel.prototype.getCollapsed=function(){return this.control.get("collapsed")},Panel.prototype.setCollapsed=function(e){"undefined"!=typeof e&&this.control.set("collapsed",!!e)},Panel.prototype.getHeaderTemplate=function(){return this.control.get("headerTemplate")},Panel.prototype.setHeaderTemplate=function(e){this.control.set("headerTemplate",e)},Panel.prototype.getHeader=function(){return this.control.get("header")},Panel.prototype.setHeader=function(e){this.control.set("header",e)},Panel.prototype.getCollapsibleArea=function(){return this.control.get("collapsibleArea")},Panel.prototype.setCollapsibleArea=function(e){this.control.set("collapsibleArea",e)},Panel.prototype.onExpanding=function(e){this.control.on("expanding",e)},Panel.prototype.onExpanded=function(e){this.control.on("expanded",e)},Panel.prototype.onCollapsing=function(e){this.control.on("collapsing",e)},Panel.prototype.onCollapsed=function(e){this.control.on("collapsed",e)},Panel.prototype.createControl=function(){return new PanelControl},window.InfinniUI.PanelBuilder=PanelBuilder,_.inherit(PanelBuilder,ContainerBuilder),_.extend(PanelBuilder.prototype,{createElement:function(e){return new Panel(e.parent)},applyMetadata:function(e){var t=e.metadata,n=e.element,i=ContainerBuilder.prototype.applyMetadata.call(this,e);n.setCollapsible(t.Collapsible),n.setCollapsed(t.Collapsed),n.setCollapsibleArea(t.CollapsibleArea);var o=this.buildHeaderTemplate(t.HeaderTemplate,e);if(n.setHeaderTemplate(o),t.Header&&"object"==typeof t.Header){var r=e.builder,a=r.buildType("PropertyBinding",t.Header,{parent:n,parentView:e.parentView,basePathOfProperty:e.basePathOfProperty});a.bindElement(n,"header")}else n.setHeader(t.Header);return this.initEventHandler(e),i},initEventHandler:function(e){function t(){return new ScriptExecutor(e.parentView)}var n=e.metadata,i=e.element;n.OnExpanding&&i.onExpanding(function(e,i){return t().executeScript(n.OnExpanding.Name||n.OnExpanding,i)}),n.OnExpanded&&i.onExpanded(function(e,i){return t().executeScript(n.OnExpanded.Name||n.OnExpanded,i)}),n.OnCollapsing&&i.onCollapsing(function(e,i){return t().executeScript(n.OnCollapsing.Name||n.OnCollapsing,i)}),n.OnCollapsed&&i.onCollapsed(function(e,i){return t().executeScript(n.OnCollapsed.Name||n.OnCollapsed,i)})},buildHeaderTemplate:function(e,t){var n;return n="undefined"==typeof e||_.isEmpty(e)?this.buildDefaultHeaderTemplate(t):this.buildMetadataHeaderTemplate(e,t)},buildDefaultHeaderTemplate:function(e){return function(e,t){var n=new Label(this);return n.setText(t.value),n}},buildMetadataHeaderTemplate:function(e,t){var n=t.element,i=t.builder;return function(o,r){var a={parent:n,parentView:t.parentView,basePathOfProperty:t.basePathOfProperty};return i.build(e,a)}}}),window.InfinniUI.PasswordBox=PasswordBox,_.inherit(PasswordBox,Element),_.extend(PasswordBox.prototype,{setAutocomplete:function(e){"undefined"!=typeof e&&null!==e&&this.control.set("autocomplete",!!e)},getAutocomplete:function(){return this.control.get("autocomplete")},createControl:function(){return new PasswordBoxControl},getRawValue:function(){return this.control.get("rawValue")}},editorBaseMixin,labelTextElementMixin),window.InfinniUI.PasswordBoxBuilder=PasswordBoxBuilder,_.inherit(PasswordBoxBuilder,ElementBuilder),_.extend(PasswordBoxBuilder.prototype,{applyMetadata:function(e){ElementBuilder.prototype.applyMetadata.call(this,e),this.applyMetadata_editorBaseBuilder(e);var t=e.metadata,n=e.element;this.initBindingToProperty(e,"LabelText"),n.setAutocomplete(t.Autocomplete)},createElement:function(e){var t=new PasswordBox(e.parent);return t}},editorBaseBuilderMixin),window.InfinniUI.PopupButton=PopupButton,_.inherit(PopupButton,Container),_.extend(PopupButton.prototype,{createControl:function(e){return new PopupButtonControl(e)}},buttonMixin),window.InfinniUI.PopupButtonBuilder=PopupButtonBuilder,_.inherit(PopupButtonBuilder,ContainerBuilder),_.extend(PopupButtonBuilder.prototype,{createElement:function(e){var t=this.detectViewMode(e);return new PopupButton(e.parent,t)},detectViewMode:function(e){var t=e.metadata.ViewMode,n=e.parent,i=!1;if(!t)for(;!i;)n?n instanceof MenuBar?(t="forMenu",i=!0):n=n.parent:i=!0;return t},applyMetadata:function(e){ContainerBuilder.prototype.applyMetadata.call(this,e),this.applyButtonMetadata.call(this,e)}},buttonBuilderMixin),window.InfinniUI.RadioGroupBuilder=RadioGroupBuilder,_.inherit(RadioGroupBuilder,ListBoxBuilder),_.extend(RadioGroupBuilder.prototype,{createElement:function(e){var t=e.metadata.ViewMode||"checking";return new ListBox(e.parent,t)},applyMetadata:function(e){var t=e.element;ListBoxBuilder.prototype.applyMetadata.call(this,e),t.setMultiSelect(!1)}}),window.InfinniUI.ScrollPanel=ScrollPanel,_.inherit(ScrollPanel,Container),ScrollPanel.prototype.getHorizontalScroll=function(){return this.control.get("horizontalScroll")},ScrollPanel.prototype.setHorizontalScroll=function(e){InfinniUI.Metadata.isValidValue(e,InfinniUI.ScrollVisibility)&&this.control.set("horizontalScroll",e)},ScrollPanel.prototype.getVerticalScroll=function(){return this.control.get("verticalScroll")},ScrollPanel.prototype.setVerticalScroll=function(e){InfinniUI.Metadata.isValidValue(e,InfinniUI.ScrollVisibility)&&this.control.set("verticalScroll",e)},ScrollPanel.prototype.createControl=function(){return new ScrollPanelControl},window.InfinniUI.ScrollPanelBuilder=ScrollPanelBuilder,_.inherit(ScrollPanelBuilder,ContainerBuilder),_.extend(ScrollPanelBuilder.prototype,{createElement:function(e){return new ScrollPanel(e.parent)},applyMetadata:function(e){var t=e.metadata,n=e.element,i=ContainerBuilder.prototype.applyMetadata.call(this,e);return n.setHorizontalScroll(t.HorizontalScroll),n.setVerticalScroll(t.VerticalScroll),i}}),window.InfinniUI.TabPanel=TabPanel,_.inherit(TabPanel,Container),TabPanel.prototype.getHeaderLocation=function(){return this.control.get("headerLocation")},TabPanel.prototype.setHeaderLocation=function(e){InfinniUI.Metadata.isValidValue(e,InfinniUI.TabHeaderLocation)&&this.control.set("headerLocation",e)},TabPanel.prototype.getHeaderOrientation=function(){return this.control.get("headerOrientation")},TabPanel.prototype.setHeaderOrientation=function(e){InfinniUI.Metadata.isValidValue(e,InfinniUI.TabHeaderOrientation)&&this.control.set("headerOrientation",e)},TabPanel.prototype.setHeaderTemplate=function(e){this.control.set("headerTemplate",e)},TabPanel.prototype.getHeaderTemplate=function(){return this.control.get("headerTemplate")},TabPanel.prototype.setSelectedItem=function(e){return this.control.setSelectedItem(e)},TabPanel.prototype.getSelectedItem=function(){return this.control.get("selectedItem")},TabPanel.prototype.onSelectedItemChanged=function(e){this.control.on("change:selectedItem",e)},TabPanel.prototype.closeTab=function(e){var t=this.childElements.indexOf(e);if(t===-1)throw new Error("TabPage not found in TabPanel.childElements");this.getItems().removeAt(t)},TabPanel.prototype.createControl=function(){return new TabPanelControl},window.InfinniUI.TabPanelBuilder=TabPanelBuilder,_.inherit(TabPanelBuilder,ContainerBuilder),_.extend(TabPanelBuilder.prototype,{createElement:function(e){return new TabPanel(e.parent)},applyMetadata:function(e){var t=e.metadata,n=e.element,i=ContainerBuilder.prototype.applyMetadata.call(this,e);return n.setHeaderLocation(t.HeaderLocation),n.setHeaderOrientation(t.HeaderOrientation),this.initScriptHandlers(e),i},initScriptHandlers:function(e){var t=e.metadata,n=e.element;n.onSelectedItemChanged(function(e,t){var n=window.InfinniUI.global.messageBus;n.send("OnChangeLayout",{})}),t.OnSelectedItemChanged&&n.onSelectedItemChanged(function(n,i){return new ScriptExecutor(e.parentView).executeScript(t.OnSelectedItemChanged.Name||t.OnSelectedItemChanged,i)})}}),window.InfinniUI.TablePanel=TablePanel,_.inherit(TablePanel,Container),_.extend(TablePanel.prototype,{createControl:function(){return new TablePanelControl}}),window.InfinniUI.TablePanelBuilder=TablePanelBuilder,_.inherit(TablePanelBuilder,ContainerBuilder),_.extend(TablePanelBuilder.prototype,{createElement:function(e){return new TablePanel(e.parent)},applyMetadata:function(e){e.metadata,e.element;ContainerBuilder.prototype.applyMetadata.call(this,e)}}),window.InfinniUI.ToggleButton=ToggleButton,_.inherit(ToggleButton,Element),_.extend(ToggleButton.prototype,{createControl:function(e){return new ToggleButtonControl(e)},getTextOn:function(){return this.control.get("textOn")},setTextOn:function(e){return this.control.set("textOn",e?e:"")},getTextOff:function(){return this.control.get("textOff")},setTextOff:function(e){return this.control.set("textOff",e?e:"")}},editorBaseMixin),window.InfinniUI.ToggleButtonBuilder=ToggleButtonBuilder,_.inherit(ToggleButtonBuilder,ElementBuilder),_.extend(ToggleButtonBuilder.prototype,{createElement:function(e){return new ToggleButton(e.parent)},applyMetadata:function(e){ElementBuilder.prototype.applyMetadata.call(this,e),this.applyMetadata_editorBaseBuilder(e);var t=e.element,n=e.metadata;t.setTextOff(n.TextOff),t.setTextOn(n.TextOn)}},editorBaseBuilderMixin);var ToolBar=function(e){_.superClass(ToolBar,this,e)};window.InfinniUI.ToolBar=ToolBar,_.inherit(ToolBar,Container),ToolBar.prototype.createControl=function(){return new ToolBarControl},window.InfinniUI.ToolBarBuilder=ToolBarBuilder,_.inherit(ToolBarBuilder,ContainerBuilder),_.extend(ToolBarBuilder.prototype,{createElement:function(e){return new ToolBar(e.parent)}}),window.InfinniUI.TreeView=TreeView,_.inherit(TreeView,ListEditorBase),TreeView.prototype.createControl=function(){return new TreeViewControl},TreeView.prototype.getKeySelector=function(){return this.control.get("keySelector")},TreeView.prototype.setKeySelector=function(e){this.control.set("keySelector",e)},TreeView.prototype.getParentSelector=function(){return this.control.get("parentSelector")},TreeView.prototype.setParentSelector=function(e){this.control.set("parentSelector",e)},window.InfinniUI.TreeViewBuilder=TreeViewBuilder,_.inherit(TreeViewBuilder,ListEditorBaseBuilder),_.extend(TreeViewBuilder.prototype,{createElement:function(e){return new TreeView(e.parent)},applyMetadata:function(e){ListEditorBaseBuilder.prototype.applyMetadata.call(this,e);this._initKeySelector(e),this._initParentSelector(e)},_initKeySelector:function(e){var t,n=e.element,i=e.metadata;t=i.KeySelector?function(e,t){var o=new ScriptExecutor(n.getScriptsStorage());return o.executeScript(i.KeySelector.Name||i.KeySelector,t)}:i.KeyProperty?function(e,t){return InfinniUI.ObjectUtils.getPropertyValue(t.value,i.KeyProperty)}:function(e,t){return t.value},n.setKeySelector(t)},_initParentSelector:function(e){var t,n=e.element,i=e.metadata;t=i.ParentSelector?function(e,t){var o=new ScriptExecutor(n.getScriptsStorage());return o.executeScript(i.ParentSelector.Name||i.ParentSelector,t)}:i.ParentProperty?function(e,t){return InfinniUI.ObjectUtils.getPropertyValue(t.value,i.ParentProperty)}:function(e,t){return t.value},n.setParentSelector(t)}}),window.InfinniUI.View=View,_.inherit(View,Container),_.extend(View.prototype,{isView:!0,_initDataSourceHandlers:function(){var e=this,t=this.getContext().dataSources,n=[];this.control.onLoaded(function(){for(var i in t)n.push(t[i].getCurrentRequestPromise());n.length>0?$.when.apply($,n).done(function(){e._notifyAboutDsReady()}):e._notifyAboutDsReady()})},_notifyAboutDsReady:function(){this.handlers.onBeforeLoaded.resolve(),this.handlers.onLoaded.resolve()},createControl:function(){return new ViewControl},_initContext:function(){this.context={view:this,scripts:{},parameters:{},dataSources:{},controls:{},messageBus:new MessageBus(this),global:InfinniUI.global};var e=this;this.control.get("scripts").onChange(function(){e.context.scripts={};var t=e.getScripts();t.forEach(function(t){e.context.scripts[t.name]=t.func})}),this.control.get("parameters").onChange(function(){e.context.parameters={};var t=e.getParameters();t.forEach(function(t){e.context.parameters[t.name]=t,e.registerMember(t.name,t)})}),this.control.get("dataSources").onChange(function(){e.context.dataSources={};var t=e.getDataSources();t.forEach(function(t){e.context.dataSources[t.get("name")]=t,e.registerMember(t.name,t)})})},getApplicationView:function(){var e=this.control.get("isApplication"),t=this.parent;return e?this:_.isEmpty(t)?null:t.getApplicationView()},isApplication:function(e){var t=this.control.get("isApplication");return _.isBoolean(e)&&this.control.set("isApplication",e),t},registerElement:function(e){this.context.controls[e.name]=e,this.registerMember(e.name,e)},getContext:function(){return this.context},getScripts:function(){return this.control.get("scripts")},getParameters:function(){return this.control.get("parameters")},getDataSources:function(){return this.control.get("dataSources")},getDialogResult:function(){return this.control.get("dialogResult")},setDialogResult:function(e){return this.control.set("dialogResult",e)},open:function(e,t){var n=this.getContext(),i=this._getScriptArgs();this.eventManager.trigger("onOpening",i,n)?(this.openStrategy.open(),this.eventManager.trigger("onOpened",i,n),e&&e(n,i)):t&&t(n,i)},close:function(e,t,n){if(!this.isClosing){this.isClosing=!0;var i=this.getContext(),o=this._getScriptArgs();n||this.eventManager.trigger("onClosing",o,i)?(this.eventManager.trigger("onClosed",o,i),this.openStrategy.close(),e&&e(i,o)):t&&t(i,o)}},getScriptsStorage:function(){return this},setOpenStrategy:function(e){this.openStrategy=e},onBeforeLoaded:function(e){this.handlers.onBeforeLoaded.done(e)},onLoaded:function(e){this.handlers.onLoaded.done(e)},onOpening:function(e){this.eventManager.on("onOpening",e)},onOpened:function(e){this.eventManager.on("onOpened",e)},onClosing:function(e){this.eventManager.on("onClosing",e)},onClosed:function(e){this.eventManager.on("onClosed",e)},_getScriptArgs:function(){return{source:this}},setHeaderTemplate:function(e){this.headerTemplate=e},getHeaderTemplate:function(){return this.headerTemplate},setCloseButtonVisibility:function(e){"boolean"==typeof e&&this.control.set("closeButtonVisibility",e)},getCloseButtonVisibility:function(){return this.control.get("closeButtonVisibility")},noDataSourceOnView:function(){this._initDataSourceHandlers()},registerMember:function(e,t){this.members[e]=t,e in this.membersDeferreds&&this.membersDeferreds[e].resolve(t)},getDeferredOfMember:function(e){if(!(e in this.membersDeferreds)&&(this.membersDeferreds[e]=$.Deferred(),this.members[e])){var t=this.members[e];this.membersDeferreds[e].resolve(t)}return this.membersDeferreds[e]},setFocusOnControl:function(e){this.control.set("focusOnControl",e)},getFocusOnControl:function(){return this.control.get("focusOnControl")}}),window.InfinniUI.ViewBuilder=ViewBuilder,_.inherit(ViewBuilder,ContainerBuilder),_.extend(ViewBuilder.prototype,{createElement:function(e){return new View(e.parent)},applyMetadata:function(e){e.parentView;e=_.extend({},e),e.parentView=e.element;var t=e.metadata,n=e.element,i=e.builder,o=n.getScripts(),r=n.getParameters();if(t.Scripts)for(var a=0,l=t.Scripts.length;a1&&(_.each(e,function(e){e.setIsWaiting(!0)}),n(t))}},viewBuilderHeaderTemplateMixin),window.InfinniUI.ViewPanel=ViewPanel,_.inherit(ViewPanel,Element),_.extend(ViewPanel.prototype,{setLayout:function(e){var t=this.getLayout();t&&t.close(),this.control.set("layout",e)},getLayout:function(){return this.control.get("layout")},createControl:function(){return new ViewPanelControl}}),window.InfinniUI.ViewPanelBuilder=ViewPanelBuilder,_.inherit(ViewPanelBuilder,ElementBuilder),_.extend(ViewPanelBuilder.prototype,{applyMetadata:function(e){ElementBuilder.prototype.applyMetadata.call(this,e);var t=e.builder,n=e.element,i=e.metadata;e.parentView;if(_.isEmpty(i.Name)&&(i.Name=guid(),n.setName(i.Name)),InfinniUI.global.containers[i.Name]=n,"LinkView"in i){var o=t.build(i.LinkView,{parentView:e.parentView,parent:e.element});o.setOpenMode("Container"),o.setContainer(i.Name),o.createView(function(e){e.open()})}},createElement:function(e){return new ViewPanel(e.parent)}}),InfinniUI.global.containers={},_.inherit(DataGridRow,Element),_.extend(DataGridRow.prototype,{createControl:function(){return new DataGridRowControl},setCellTemplates:function(e){this.control.set("cellTemplates",e)},toggle:function(e){this.control.set("toggle",e)},getSelected:function(){this.control.get("selected")},setSelected:function(e){this.control.set("selected",e)},setMultiSelect:function(e){this.control.set("multiSelect",e)},setShowSelectors:function(e){this.control.set("showSelectors",e)},onToggle:function(e){this.control.onToggle(e)},setRowBackground:function(e){this.control.set("rowBackground",e)},getRowBackground:function(){return this.control.get("rowBackground")},setRowForeground:function(e){this.control.set("rowForeground",e)},getRowForeground:function(){return this.control.get("rowForeground")},setRowTextStyle:function(e){this.control.set("rowTextStyle",e)},getRowTextStyle:function(){return this.control.get("rowTextStyle")},setRowStyle:function(e){this.control.set("rowStyle",e)},getRowStyle:function(){return this.control.get("rowStyle")},setGrid:function(e){this.control.set("grid",e)},_transformRowProperties:function(e){for(var t in e)e.hasOwnProperty(t)&&(this.setProperty(e[t],this.getProperty(t)),this.onPropertyChanged(t,function(e,t){return function(n,i){e.setProperty(t,i.newValue)}}(this,e[t])))}}),_.inherit(TabPage,Container),TabPage.prototype.getIcon=function(){return this.control.get("icon")},TabPage.prototype.setIcon=function(e){this.control.set("icon",e)},TabPage.prototype.getCanClose=function(){return this.control.get("canClose")},TabPage.prototype.setCanClose=function(e){this.control.set("canClose",e)},TabPage.prototype.close=function(e,t){var n=this.getCanClose(),i=this,o=this.events;n&&this.events.trigger("closing").done(function(){i.parent&&i.parent.closeTab(i),"function"==typeof e&&e(),o.trigger("closed")}).fail(function(){"function"==typeof t&&t()})},TabPage.prototype.onClosing=function(e){this.events.on("closing",e)},TabPage.prototype.onClosed=function(e){this.events.on("closed",e)},TabPage.prototype.getSelected=function(){return this.control.get("selected")},TabPage.prototype.setSelected=function(e){this.control.set("selected",e)},TabPage.prototype.createControl=function(){return new TabPageControl},_.inherit(TabPageBuilder,ContainerBuilder),_.extend(TabPageBuilder.prototype,{createElement:function(e){return new TabPage(e.parent)},applyMetadata:function(e){var t=e.metadata,n=e.element,i=ContainerBuilder.prototype.applyMetadata.call(this,e);return n.setIcon(t.Icon),n.setCanClose(t.CanClose),this.initScriptHandlers(e),i},initScriptHandlers:function(e){var t=e.metadata,n=e.element;t.OnClosing&&n.onClosing(function(){return new ScriptExecutor(e.parentView).executeScript(t.OnClosing.Name||t.OnClosing,{})}),t.OnClosed&&n.onClosed(function(){return new ScriptExecutor(e.parentView).executeScript(t.OnClosed.Name||t.OnClosed,{})})}}),_.inherit(Cell,Container),_.extend(Cell.prototype,{createControl:function(){return new CellControl},getColumnSpan:function(){return this.control.get("columnSpan")},setColumnSpan:function(e){this.control.set("columnSpan",e)}}),_.inherit(CellBuilder,ContainerBuilder),_.extend(CellBuilder.prototype,{createElement:function(e){return new Cell(e.parent)},applyMetadata:function(e){var t=e.metadata;e.element;ContainerBuilder.prototype.applyMetadata.call(this,e),e.element.setColumnSpan(t.ColumnSpan)}}),_.inherit(Row,Container),_.extend(Row.prototype,{createControl:function(){return new RowControl}}),_.inherit(RowBuilder,ContainerBuilder),_.extend(RowBuilder.prototype,{createElement:function(e){return new Row(e.parent)},applyMetadata:function(e){e.metadata,e.element;ContainerBuilder.prototype.applyMetadata.call(this,e)}}),window.InfinniUI.BaseAction=BaseAction,_.extend(BaseAction.prototype,{defaults:{},setProperty:function(e,t){var n=this._properties;n[e]!==t&&(n[e]=t,this.trigger("change:"+e,this,t))},getProperty:function(e){return this._properties[e]},initDefaultValues:function(){},onExecutedHandler:function(e){var t=this.getProperty("onExecutedHandler");_.isFunction(t)&&t(e)}},Backbone.Events),InfinniUI.global.executeAction=function(e,t,n){var i=new ApplicationBuilder,o=i.build(t,{parentView:e.view});o.execute(n)};var BaseActionBuilderMixin={applyBaseActionMetadata:function(e,t){var n=t.metadata;"OnExecuted"in n&&e.setProperty("onExecutedHandler",function(t){new ScriptExecutor(e.parentView).executeScript(n.OnExecuted.Name||n.OnExecuted,t)})}};window.InfinniUI.BaseEditAction=BaseEditAction,_.inherit(BaseEditAction,BaseAction),_.extend(BaseEditAction.prototype,{execute:function(e){var t=this,n=this.getProperty("linkView");this.setProperty("callback",e),n.createView(function(e){t.handleViewReady(e)})},handleViewReady:function(e){var t=this.getProperty("sourceSource"),n=e.getContext().dataSources[t],i=this.getProperty("destinationSource"),o=this.parentView.getContext().dataSources[i],r=this;this.setProperty("editDataSource",n),this.setProperty("destinationDataSource",o);var a=this.setSelectedItem();a?(e.open(),e.onClosed(function(){var t=e.getDialogResult();t==DialogResult.accepted&&r.handleClosingView()})):e.close()},handleClosingView:function(){var e=this.getProperty("callback");this.save(),this.onExecutedHandler(),_.isFunction(e)&&e()},_isObjectDataSource:function(e){return"setItems"in e}});var BaseEditActionBuilderMixin={applyBaseEditActionMetadata:function(e,t){var n=t.metadata,i=t.parentView,o=t.builder,r={};r[n.SourceValue.Source]="BaseEditAction";var a=o.build(n.LinkView,{parent:t.parent,parentView:i,basePathOfProperty:t.basePathOfProperty,suspended:r});e.setProperty("linkView",a),e.setProperty("sourceSource",n.SourceValue.Source),e.setProperty("destinationSource",n.DestinationValue.Source);var l=null!=t.basePathOfProperty?t.basePathOfProperty.resolveProperty(n.DestinationValue.Property):n.DestinationValue.Property;e.setProperty("destinationProperty",l)}},BaseFallibleActionBuilderMixin={applyBaseFallibleActionMetadata:function(e,t){var n=t.metadata;"OnSuccess"in n&&e.setProperty("onSuccessHandler",function(t){new ScriptExecutor(e.parentView).executeScript(n.OnSuccess.Name||n.OnSuccess,t)}),"OnError"in n&&e.setProperty("onErrorHandler",function(t){new ScriptExecutor(e.parentView).executeScript(n.OnError.Name||n.OnError,t)})}},BaseFallibleActionMixin={onSuccessHandler:function(e){var t=this.getProperty("onSuccessHandler");_.isFunction(t)&&t(e)},onErrorHandler:function(e){var t=this.getProperty("onErrorHandler");_.isFunction(t)&&t(e)}};_.inherit(AcceptAction,BaseAction),_.extend(AcceptAction.prototype,{execute:function(e){var t=this;this.parentView.onClosed(function(){t.onExecutedHandler(),e&&e()}),this.parentView.setDialogResult(DialogResult.accepted),this.parentView.close()}}),window.InfinniUI.AcceptAction=AcceptAction,_.extend(AcceptActionBuilder.prototype,BaseActionBuilderMixin,{build:function(e,t){var n=new AcceptAction(t.parentView);return this.applyBaseActionMetadata(n,t),n}}),window.InfinniUI.AcceptActionBuilder=AcceptActionBuilder,_.inherit(AddAction,BaseEditAction),_.extend(AddAction.prototype,{setSelectedItem:function(){var e=this.getProperty("editDataSource"),t=e.getView();return t.onBeforeLoaded(function(){e.createItem()}),!0},save:function(){var e=this.getProperty("editDataSource"),t=this.getProperty("destinationDataSource"),n=this.getProperty("destinationProperty")||"";if(this._isObjectDataSource(e)){var i=t.getProperty(n)||[],o=e.getSelectedItem();i=_.clone(i),i.push(o),t.setProperty(n,i)}else t.updateItems()}}),window.InfinniUI.AddAction=AddAction,_.extend(AddActionBuilder.prototype,BaseActionBuilderMixin,BaseEditActionBuilderMixin,{build:function(e,t){var n=new AddAction(t.parentView);return this.applyBaseActionMetadata(n,t),this.applyBaseEditActionMetadata(n,t),n}}),window.InfinniUI.AddActionBuilder=AddActionBuilder,_.inherit(CancelAction,BaseAction),_.extend(CancelAction.prototype,{execute:function(e){var t=this;this.parentView.onClosed(function(){t.onExecutedHandler(),e&&e()}),this.parentView.setDialogResult(DialogResult.canceled),this.parentView.close()}}),window.InfinniUI.CancelAction=CancelAction,_.extend(CancelActionBuilder.prototype,BaseActionBuilderMixin,{build:function(e,t){var n=new CancelAction(t.parentView);return this.applyBaseActionMetadata(n,t),n}}),window.InfinniUI.CancelActionBuilder=CancelActionBuilder,_.inherit(DeleteAction,BaseAction),_.extend(DeleteAction.prototype,BaseFallibleActionMixin,{execute:function(e){var t=this.getProperty("accept"),n=this,i=this.getProperty("destinationSource"),o=this.getProperty("destinationProperty");i.getProperty(o)?t?new MessageBox({text:"Вы уверены, что хотите удалить?",buttons:[{name:"Да",type:"action",onClick:function(){n.remove(e)}},{name:"Нет"}]}):this.remove(e):new MessageBox({text:"Вы не выбрали элемент который необходимо удалить",buttons:[{name:"Закрыть"}]})},remove:function(e){var t=this.getProperty("destinationSource"),n=this.getProperty("destinationProperty");this._isDocument(n)?this._deleteDocument(t,n,e):this._deleteItem(t,n,e)},_deleteDocument:function(e,t,n){var i=this,o=function(t,o){e.updateItems(),i.onExecutedHandler(o),i.onSuccessHandler(o),_.isFunction(n)&&n()},r=function(e,t){i.onExecutedHandler(t),i.onErrorHandler(t),_.isFunction(n)&&n()},a=e.getProperty(t);e.deleteItem(a,o,r)},_deleteItem:function(e,t,n){var i=t.split("."),o=i.pop(),r=i.join("."),a=e.getProperty(r);a=_.clone(a),a.splice(o,1),e.setProperty(r,a),this.onExecutedHandler(),this.onSuccessHandler(),_.isFunction(n)&&n()},_isDocument:function(e){return"$"==e||_.isFinite(e)}}),window.InfinniUI.DeleteAction=DeleteAction,_.extend(DeleteActionBuilder.prototype,BaseActionBuilderMixin,BaseFallibleActionBuilderMixin,{build:function(e,t){var n=t.metadata,i=t.parentView,o=n.DestinationValue.Source,r=n.DestinationValue.Property||"$",a=new DeleteAction(i);this.applyBaseActionMetadata(a,t),this.applyBaseFallibleActionMetadata(a,t);var l=n.Accept!==!1,s=i.getContext().dataSources[o],u=null!=t.basePathOfProperty?t.basePathOfProperty.resolveProperty(r):r;return a.setProperty("accept",l),a.setProperty("destinationSource",s),a.setProperty("destinationProperty",u),a}}),window.InfinniUI.DeleteActionBuilder=DeleteActionBuilder,_.inherit(EditAction,BaseEditAction),_.extend(EditAction.prototype,{setSelectedItem:function(){var e=this.getProperty("editDataSource"),t=this.getProperty("destinationDataSource"),n=this.getProperty("destinationProperty"),i=t.getProperty(n);if(null==i){if(this._isDocumentPath(n)){var o=window.InfinniUI.global.logger,r=stringUtils.format('EditAction: edit item has not been found. {0} does not have item by path "{1}"',[t.getName(),n]);return o.error(r),!1}i=i||{}}return this._isObjectDataSource(e)?this._setItem(e,i):this._setDocument(e,i),!0},_resumeUpdateEditDataSource:function(){var e=this.getProperty("editDataSource");e.resumeUpdate("BaseEditAction")},_setDocument:function(e,t){var n=e.idOfItem(t);e.setIdFilter(n),e.tryInitData(),this._resumeUpdateEditDataSource()},_setItem:function(e,t){var n=_.clone(t);void 0!==n&&null!==n||(n={}),this._resumeUpdateEditDataSource(),e.setItems([n]),e.setSelectedItem(n)},save:function(){var e=this.getProperty("editDataSource"),t=this.getProperty("destinationDataSource"),n=this.getProperty("destinationProperty");if(this._isObjectDataSource(e)){var i=e.getSelectedItem();t.setProperty(n,i)}else t.updateItems()},_isDocumentPath:function(e){return!e.includes(".")}}),window.InfinniUI.EditAction=EditAction,_.extend(EditActionBuilder.prototype,BaseActionBuilderMixin,BaseEditActionBuilderMixin,{build:function(e,t){var n=new EditAction(t.parentView);return this.applyBaseActionMetadata(n,t),this.applyBaseEditActionMetadata(n,t),n}}),window.InfinniUI.EditActionBuilder=EditActionBuilder,_.inherit(OpenAction,BaseAction),_.extend(OpenAction.prototype,{execute:function(e){var t=this.getProperty("linkView"),n=this;t.createView(function(t){t.onLoaded(function(){n.onExecutedHandler(),e&&e(t)}),t.open()})}}),window.InfinniUI.OpenAction=OpenAction,_.extend(OpenActionBuilder.prototype,BaseActionBuilderMixin,{build:function(e,t){var n=new OpenAction(t.parentView);this.applyBaseActionMetadata(n,t);var i=t.builder.build(t.metadata.LinkView,{parent:t.parent,parentView:t.parentView,basePathOfProperty:t.basePathOfProperty});return n.setProperty("linkView",i),n}}),window.InfinniUI.OpenActionBuilder=OpenActionBuilder,_.inherit(RouteToAction,BaseAction),_.extend(RouteToAction.prototype,{execute:function(e){var t=InfinniUI.AppRouter,n=this.getHref();t.navigate(n,{trigger:!0})},getHref:function(){return this.href},setHref:function(e){this.href=e}}),window.InfinniUI.RouteToAction=RouteToAction,_.extend(RouteToActionBuilder.prototype,BaseActionBuilderMixin,routerServiceMixin,{build:function(e,t){var n=new RouteToAction,i=routerService.getLinkByName(t.metadata.Name,"no"),o=t.metadata.Params,r=t.metadata.Query;if(n.setHref(i),t.element=n,o)for(var a=0,l=o.length;a/g,function(e,n){return t.getParam(n)})},_replaceParamsInObject:function(e){if(_.isEmpty(e))return e;var t=JSON.stringify(e),n=this._replaceParamsInStr(t);return JSON.parse(n)}}),window.InfinniUI.ServerAction=ServerAction,_.extend(ServerActionBuilder.prototype,BaseActionBuilderMixin,BaseFallibleActionBuilderMixin,{build:function(e,t){var n=t.builder,i=t.metadata,o=t.parentView,r=new ServerAction(o);if(this.applyBaseActionMetadata(r,t),this.applyBaseFallibleActionMetadata(r,t),r.setProperty("origin",i.Origin),r.setProperty("path",i.Path),i.Data&&r.setProperty("data",i.Data),i.Method&&r.setProperty("method",i.Method),(i.ContentType||i.ContentType===!1)&&r.setProperty("contentType",i.ContentType),i.Params)for(var a in i.Params){var l=i.Params[a];"object"!=typeof l?void 0!==l&&r.setParam(a,l):this._initBinding(a,l,r,o,n)}return r},_initBinding:function(e,t,n,i,o){var r={parent:i,parentView:i},a=o.buildBinding(t,r);a.setMode(InfinniUI.BindingModes.toElement),a.bindElement({setProperty:function(e,t){n.setParam(e,t)},onPropertyChanged:function(){}},e)}}),window.InfinniUI.ServerActionBuilder=ServerActionBuilder;var serverActionContentTypeStrategy={File:{run:function(e,t,n,i,o){e.download(t,n,i,o)}},Object:{run:function(e,t,n,i,o){e.request(t,n,i,o)}}};_.inherit(UpdateAction,BaseAction),_.extend(UpdateAction.prototype,BaseFallibleActionMixin,{execute:function(e){var t=this.getProperty("dataSource"),n=this,i=function(t,i){n.onExecutedHandler(i),n.onSuccessHandler(i),_.isFunction(e)&&e(t,i)},o=function(t,i){n.onExecutedHandler(i),n.onErrorHandler(i),_.isFunction(e)&&e(t,i)};t.updateItems(i,o)}}),window.InfinniUI.UpdateAction=UpdateAction,_.extend(UpdateActionBuilder.prototype,BaseActionBuilderMixin,BaseFallibleActionBuilderMixin,{build:function(e,t){var n=t.parentView.getContext().dataSources[t.metadata.DestinationValue.Source],i=new UpdateAction(t.parentView);return this.applyBaseActionMetadata(i,t),this.applyBaseFallibleActionMetadata(i,t),i.setProperty("dataSource",n),i}}),window.InfinniUI.UpdateActionBuilder=UpdateActionBuilder,_.extend(ApplicationBuilder.prototype,{builder:null,registerElementBuilders:function(){var e=this.builder;e.register("View",new ViewBuilder),e.register("InlineView",new InlineViewBuilder),e.register("AutoView",new MetadataViewBuilder),e.register("StackPanel",new StackPanelBuilder),e.register("GridPanel",new GridPanelBuilder),e.register("ScrollPanel",new ScrollPanelBuilder),e.register("Panel",new PanelBuilder),e.register("ScrollPanel",new ScrollPanelBuilder),e.register("ViewPanel",new ViewPanelBuilder),e.register("TabPanel",new TabPanelBuilder),e.register("TabPage",new TabPageBuilder),e.register("TablePanel",new TablePanelBuilder),e.register("Cell",new CellBuilder),e.register("Row",new RowBuilder),e.register("MenuBar",new MenuBarBuilder),e.register("DataGrid",new DataGridBuilder),e.register("DataGridColumn",new DataGridColumnBuilder),e.register("ListBox",new ListBoxBuilder),e.register("TextBox",new TextBoxBuilder),e.register("PasswordBox",new PasswordBoxBuilder),e.register("CheckBox",new CheckBoxBuilder),e.register("IndeterminateCheckBox",new IndeterminateCheckBoxBuilder),e.register("ImageBox",new ImageBoxBuilder),e.register("FileBox",new FileBoxBuilder),e.register("Label",new LabelBuilder),e.register("Link",new LinkBuilder),e.register("Form",new FormBuilder),e.register("Icon",new IconBuilder),e.register("DateTimePicker",new DateTimePickerBuilder),e.register("DatePicker",new DatePickerBuilder),e.register("TimePicker",new TimePickerBuilder),e.register("ToggleButton",new ToggleButtonBuilder),e.register("NumericBox",new NumericBoxBuilder),e.register("Button",new ButtonBuilder),e.register("ToolBar",new ToolBarBuilder),e.register("ToolBarButton",new ButtonBuilder),e.register("ComboBox",new ComboBoxBuilder),e.register("RadioGroup",new RadioGroupBuilder),e.register("ExtensionPanel",new ExtensionPanelBuilder),e.register("PopupButton",new PopupButtonBuilder),e.register("DataNavigation",new DataNavigationBuilder),e.register("TreeView",new TreeViewBuilder),e.register("Frame",new FrameBuilder),e.register("ButtonEdit",new ButtonEditBuilder),e.register("RestDataSource",new RestDataSourceBuilder),e.register("DocumentDataSource",new DocumentDataSourceBuilder),e.register("PropertyBinding",new DataBindingBuilder),e.register("ObjectDataSource",new ObjectDataSourceBuilder),e.register("Parameter",new ParameterBuilder),e.register("AcceptAction",new AcceptActionBuilder),e.register("AddAction",new AddActionBuilder),e.register("CancelAction",new CancelActionBuilder),e.register("DeleteAction",new DeleteActionBuilder),e.register("EditAction",new EditActionBuilder),e.register("OpenAction",new OpenActionBuilder),e.register("SaveAction",new SaveActionBuilder),e.register("SelectAction",new SelectActionBuilder),e.register("UpdateAction",new UpdateActionBuilder),e.register("ServerAction",new ServerActionBuilder),e.register("RouteToAction",new RouteToActionBuilder),e.register("BooleanFormat",new BooleanFormatBuilder),e.register("DateTimeFormat",new DateTimeFormatBuilder),e.register("NumberFormat",new NumberFormatBuilder),e.register("ObjectFormat",new ObjectFormatBuilder),e.register("DateTimeEditMask",new DateTimeEditMaskBuilder),e.register("NumberEditMask",new NumberEditMaskBuilder),e.register("TemplateEditMask",new TemplateEditMaskBuilder),e.register("RegexEditMask",new RegexEditMaskBuilder),e.register("Script",new ScriptBuilder),e.register("Divider",new DividerBuilder),e.register("ContextMenu",new ContextMenuBuilder);for(var t=ApplicationBuilder.registerQueue,n=0,i=t.length;n0&&(i.url=i.url+"?"+stringUtils.joinDataForQuery(o.data));else{var s=new FormData;s.append("document",JSON.stringify(l.dataWithoutFiles));for(var u in l.files)s.append(u,l.files[u]);i={type:o.method,url:r,xhrFields:{withCredentials:!0},data:s,cache:!1,contentType:!1,processData:!1,success:function(e){t({requestId:a,data:e})},error:function(e){n({requestId:a,data:e})}}}return $.ajax(i),a},getItems:function(e,t){return this.send("get",e,t)},saveItem:function(e,t,n){return this.requestParams.set.data=e,this.send("set",t,n)},deleteItem:function(e,t,n){return this.send("delete",t,n)},createItem:function(e,t){var n=this;setTimeout(function(){e(n.createLocalItem(t))},10)},createLocalItem:function(e){var t={};return t[e]=this._generateLocalId(),t},_generateLocalId:function(){return guid()},extractFilesFromData:function(e){function t(e,i){var o,r,a=Array.isArray(e)?[]:{};for(var l in e)if(e.hasOwnProperty(l))if(r=i.slice(),r.push(l),o=e[l],null!==o&&"object"==typeof o)if(o.constructor===Date)a[l]=o;else{if(o.constructor!==Object&&o.constructor!==Array){a[l]=null,n[r.join(".")]=o;continue}a[l]=t(o,r)}else a[l]=o;return a}var n=Object.create(null),i=t(e,[]);return{dataWithoutFiles:i,files:n}}}),window.InfinniUI.Providers.RestDataProvider=RestDataProvider;var ServerActionProvider=function(){};ServerActionProvider.prototype.request=function(e,t,n,i){var o=Math.round(1e5*Math.random());return $.ajax({type:e.method,url:e.requestUrl,xhrFields:{withCredentials:!0},data:e.args,contentType:e.contentType,success:function(e){var i={requestId:o,data:e};_.isFunction(t)&&t(i),_.isFunction(n)&&n(i)},error:function(e){var n={requestId:o,data:e};_.isFunction(t)&&t(n),_.isFunction(i)&&i(n)}}),o},ServerActionProvider.prototype.download=function(e,t,n,i){new DownloadExecutor(t,n,i).run(e)},window.InfinniUI.Providers.ServerActionProvider=ServerActionProvider;var DataProviderReplaceItemQueue=function(e){var t=e||[],n=[],i="__Id",o=function(e){var n=_.pick(e,t),o=_.isEmpty(e[i])?"Id":i;return n[o]=e[o],n},r=function(e){return _.findWhere(n,o(e))},a=function(e){return _.where(n,o(e))},l=function(e,t){var n=a(e);n.forEach(function(e){e.Id=t.Id,e.value.Id=t.Id})},s=function(e){var t=n.indexOf(e);t===-1&&console.error("DataProviderReplaceItemQueue: Не найден запрос в очереди"),n.splice(t,1);var i=r(e);u(i)},u=function(e){"undefined"!=typeof e&&null!==e&&e.request(e).done(l.bind(void 0,e)).always(s.bind(void 0,e))};this.append=function(e,t){var o=_.defaults(e,_.pick(e.value,["Id",i]));o.request=t;var r=a(o);if(n.push(o),0===r.length)u(e);else if(r.length>1)for(var l=1,s=r.length;l12&&(t-=12),t<10?"0"+t.toString():t.toString()},"%h":function(e){var t=e.getHours();return t>12&&(t-=12),t.toString()},h:function(e){var t=e.getHours();return t>12&&(t-=12),t.toString()},mm:function(e){var t=e.getMinutes();return t<10?"0"+t.toString():t.toString()},"%m":function(e){var t=e.getMinutes();return t.toString()},m:function(e){var t=e.getMinutes();return t.toString()},ss:function(e){var t=e.getSeconds();return t<10?"0"+t.toString():t.toString()},"%s":function(e){var t=e.getSeconds();return t.toString()},s:function(e){var t=e.getSeconds();return t.toString()},tt:function(e,t){var n=e.getHours();return n<12?t.dateTimeFormatInfo.amDesignator:t.dateTimeFormatInfo.pmDesignator},"%t":function(e,t){var n=e.getHours();return n<12?t.dateTimeFormatInfo.amDesignator.substr(0,1):t.dateTimeFormatInfo.pmDesignator.substr(0,1)},t:function(e,t){var n=e.getHours();return n<12?t.dateTimeFormatInfo.amDesignator.substr(0,1):t.dateTimeFormatInfo.pmDesignator.substr(0,1)},zzz:function(e){var t,n,i=-e.getTimezoneOffset()/60;return t=100*(i-Math.floor(i)),i=Math.floor(i),i<0?(n="-",i=-i):n="+",t=t<10?"0"+t.toString():t.toString(),i<10?n+"0"+i.toString()+":"+t:n+i.toString()+":"+t},zz:function(e){var t,n=-e.getTimezoneOffset()/60;return n=Math.floor(n),n<0?(t="-",n=-n):t="+",n<10?t+"0"+n.toString():t+n.toString()},z:function(e,t){var n,i=-e.getTimezoneOffset()/60;return i=Math.floor(i),i<0?(n="-",i=-i):n="+",n+i.toString()},"%z":function(e,t){var n,i=-e.getTimezoneOffset()/60;return i=Math.floor(i),i<0?(n="-",i=-i):n="+",n+i.toString()},":":function(e,t){return t.dateTimeFormatInfo.timeSeparator},"/":function(e,t){return t.dateTimeFormatInfo.dateSeparator}}},formatMixin),window.InfinniUI.DateTimeFormatBuilder=DateTimeFormatBuilder,window.InfinniUI.NumberFormat=NumberFormat,_.extend(NumberFormat.prototype,{defaultFormat:"n",formatValue:function(e,t,n){if("undefined"==typeof e||null===e)return"";var i=this;return t=t||new Culture(InfinniUI.config.lang),n=n||this.getFormat(),n.replace(this.rg,function(n,o,r){return r=void 0!==r&&""!=r?parseInt(r):void 0,i.rules[o].call(i,e,r,t)})},rg:/^([pnc])(\d*)$/gi,rules:{P:function(e,t,n){t=void 0!==t?t:n.numberFormatInfo.percentDecimalDigits;var i,o=e>=0,r=this.formatNumber(Math.abs(e),t,n.numberFormatInfo.percentGroupSeparator,n.numberFormatInfo.percentDecimalSeparator);return i=o?n.numberFormatInfo.percentPositivePattern.replace("p",r):n.numberFormatInfo.percentNegativePattern.replace("p",r),i=i.replace("%",n.numberFormatInfo.percentSymbol)},p:function(e,t,n){return e*=100,this.rules.P.call(this,e,t,n)},n:function(e,t,n){t=void 0!==t?t:n.numberFormatInfo.numberDecimalDigits;var i,o=e>=0,r=this.formatNumber(Math.abs(e),t,n.numberFormatInfo.numberGroupSeparator,n.numberFormatInfo.numberDecimalSeparator);return i=o?n.numberFormatInfo.numberPositivePattern.replace("n",r):n.numberFormatInfo.numberNegativePattern.replace("n",r)},N:function(){return this.rules.n.apply(this,arguments)},c:function(e,t,n){t=void 0!==t?t:n.numberFormatInfo.currencyDecimalDigits;var i,o=e>=0,r=this.formatNumber(Math.abs(e),t,n.numberFormatInfo.currencyGroupSeparator,n.numberFormatInfo.currencyDecimalSeparator);return i=o?n.numberFormatInfo.currencyPositivePattern.replace("c",r):n.numberFormatInfo.currencyNegativePattern.replace("c",r),i=i.replace("$",n.numberFormatInfo.currencySymbol); -},C:function(){return this.rules.c.apply(this,arguments)}},formatNumber:function(e,t,n,i){e=e.toFixed(t);var o=e.toString(),r=o.split("."),a=this.formatIntPath(r[0],n),l=this.formatFractPath(r[1],i,t);return a+l},formatIntPath:function(e,t){return e.replace(/(\d{1,3}(?=(\d{3})+(?:\.\d|\b)))/g,"$1"+t)},formatFractPath:function(e,t,n){var i,o=e?e:"";return 0==n?"":o.length>=n?t+o.substr(0,n):(i=Math.pow(10,n-o.length),i=i.toString().substr(1),t+o+i)}},formatMixin),window.InfinniUI.NumberFormatBuilder=NumberFormatBuilder,window.InfinniUI.ObjectFormat=ObjectFormat,_.extend(ObjectFormat.prototype,{formatValue:function(e,t,n){t=t||new Culture(InfinniUI.config.lang),n=n||this.getFormat();var i=/{[^}]*}/g,o="";return o=n.replace(i,this.formatIterator.bind(this,e,t))},formatIterator:function(e,t,n){var i,o,r,a,l,s=/^{|}$/g;if(i=n,o=n.replace(s,""),l=o.split(":"),a="object"==typeof e?""===l[0]?e:InfinniUI.ObjectUtils.getPropertyValue(e,l[0]):e,2===l.length){for(var u=0,d=this.formatters.length;ui&&(t=i)),t},getPrevIntValue:function(e,t){e=e||{};var n=null,i="undefined"!=typeof e.step?i:1;return"undefined"!=typeof e.min&&(n=e.min),t=parseInt(t,10),isNaN(t)?t=null===n?0:n:(t-=i,null!==n&&t-1},prev:function(e){return this.getPrevMonthValue("MMMM",e)},next:function(e){return this.getNextMonthValue("MMMM",e)},apply:function(e,t){var n=this.getIndexMonthValue("MMMM",t);return n!==-1&&e.setMonth(n),e}}}}(),DateTimeMaskPart=function(e){_.extend(this,DateTimeMaskPartStrategy[e]),this.init()};_.extend(DateTimeMaskPart.prototype,{init:function(){},match:function(e){return!0},validator:function(e){return!0},fulfilled:function(e){return this.match(e)&&this.validator(e)},prev:function(e){return e},next:function(e){return e},format:function(e){return e},applyPart:function(e,t){return e},padNumber:function(e){var t="undefined"!=typeof this.width?this.width:null;e=parseInt(e,10);var n,i;return n=isNaN(e)?n="":e.toString(),i=n.length,null!==t&&in&&(e=n)),e},getPrevIntValue:function(e){var t="undefined"!=typeof this.min?this.min:null,n="undefined"!=typeof this.step?this.step:1;return e=parseInt(e,10),isNaN(e)?e=null===t?0:t:(e-=n,null!==t&&e=0?n[i]:t)},getIndexListValueForMask:function(e,t){var n=this.getListForMask(e);return"undefined"==typeof n?-1:n.indexOf(t)},getNextMonthValue:function(e,t){return this.getNextListValueForMask(e,t)},getPrevMonthValue:function(e,t){return this.getPrevListValueForMask(e,t)},getIndexMonthValue:function(e,t){return this.getIndexListValueForMask(e,t)},rangeValidator:function(e){return e=parseInt(e,10),!(isNaN(e)||ethis.max)}}),window.InfinniUI.DateTimeEditMask=DateTimeEditMask,_.extend(DateTimeEditMask.prototype,editMaskMixin),_.extend(DateTimeEditMask.prototype,{getNextItemMask:function(e){var t,n=this.getItemTemplate(e);return null!==n?(t=this.moveToNextChar(n.left+n.width),t>n.left+n.width&&(e=t)):e=this.moveToNextChar(e),e},setNextValue:function(e){var t,n,i,o=this.getItemTemplate(e);return null!==o?(t=o.item,i=this.masks[t.mask],"undefined"!=typeof i.next&&(n=i.next(t.text),"undefined"!=typeof i.format&&(n=i.format(n)),t.text=""+n,e=Math.min(o.left+t.text.length,e))):e=this.moveToNextChar(e),e},setPrevValue:function(e){var t,n,i,o=this.getItemTemplate(e);return null!==o?(t=o.item,i=this.masks[t.mask],"undefined"!=typeof i.prev&&(n=i.prev(t.text),"undefined"!=typeof i.format&&(n=i.format(n)),t.text=""+n,e=Math.min(o.left+t.text.length,e))):e=this.moveToNextChar(e),e},deleteSelectedText:function(e,t,n){var i,o,r,a,l,s=e,u=t;n=n||"";for(var d=e+n.length-1;(i=this.getItemTemplate(s))&&(l=s,o=s-i.left,r=i.item.text,a=this.masks[i.item.mask],r=r.substring(0,o)+n+r.substring(o+u),r.length&&!a.match(r)||(i.item.text=r),s=this.getNextItemMask(s),l!==s);)u=t-(s-e),n="";return this.moveToNextChar(d)},deleteCharLeft:function(e,t){var n,i,o=this.getItemTemplate(e);return t?e=this.deleteSelectedText(e,t):null!==o?o.index>0?(n=o.item,e--,i=n.text.slice(0,o.index-1)+n.text.slice(o.index),n.text=i):(o=this.getItemTemplate(o.left-1),e=o.left+o.item.text.length):e=this.moveToNextChar(e),e},deleteCharRight:function(e,t){var n,i,o=this.getItemTemplate(e);return t?e=this.deleteSelectedText(e,t):null!==o?(n=o.item,i=n.text.slice(0,o.index)+n.text.slice(o.index+1),n.text=i,0==n.text.length&&(e=this.getNextItemMask(e))):e=this.moveToNextChar(e),e},pasteStringToMask:function(e,t){function n(e){return Math.max(e.mask.length,e.text.length)}function i(n){for(var i=0,o=[],r=a;rn[r].position-i-t&&o.push(n[r]):i+=n[r].length;return o[o.length-1]}e=e.replace(/\D/gi,"");var o=e.split(""),r=this.getItemTemplate(t),a=this.template.indexOf(r.item),l=0,s=i(this.template);l=s?this.template.indexOf(s):a;for(var u=0,d=0,c=a;cd&&o.splice(d,o.length),this.template[c].text=o.join("")+this.template[c].text.slice(o.length,d))},getItemTemplate:function(e){var t,n,i,o=this.template,r=0,a=null;if("undefined"==typeof o&&(this.reset(),o=this.template),!Array.isArray(o))return null;for(var l=0,s=o.length;l=r&&e<=r+n){i=e-r,a={item:t,left:r,width:n,index:e-r};break}r+=n}return a},setCharAt:function(e,t){var n,i,o,r,a,l=this.getItemTemplate(t);if(null!==l)if(i=l.item,r=t-l.left,r>i.text.length&&(t=l.left),o=this.masks[i.mask],a=t-i.position,a<0&&(a=0),n=i.text.slice(a,a+1)?[i.text.slice(0,a),e,i.text.slice(a+1)].join(""):[i.text.slice(0,l.index),e,i.text.slice(l.index)].join(""),o.match(n))i.text=n,t=this.moveToNextChar(t),o.width===a+1&&(t=this.getNextItemMask(t));else{var s=this.template.indexOf(l.item)+1;this.template[s]===e&&(t=this.getNextItemMask(t))}else t=this.moveToNextChar(t);return t},moveToPrevChar:function(e){e-=1;for(var t,n,i,o=this.template,r=0,a=r,l=0,s=o.length;l=r&&ea&&(e=a),e},moveToNextChar:function(e){e+=1;for(var t,n,i,o,r=this.template,a=0,l=0,s=r.length;l=a&&e<=a+o)break;if(e=n&&(e=n),e},getText:function(){var e,t,n=this.template,i=[];if(Array.isArray(n)){for(var o=0,r=n.length;o=0;t-=1)if("string"!=typeof o[t]){r=o[t].position;break}return null===r?0:r+1},moveToPrevChar:function(e){e=Math.max(e,0);var t,n,i=this.template,o=i.slice(0,e),r=null,a=!1;for(t=o.length-1;t>=0;t-=1){if("string"!=typeof o[t]){r=o[t].position+(a?1:0);break}a=!0}if(null===r)for(o=i.slice(e),t=0,n=o.length;t=r&&e<=r+n){i=e-r,a={item:t,left:r,width:n,index:e-r};break}r+=n}return a},deleteCharRight:function(e,t){var n,i,o;if(t>0)return this.deleteSelectedText(e,t);for(i=0,o=this.template.length;i0)return this.deleteSelectedText(e,t);for(i=this.template.length-1;i>=0;i-=1)if(n=this.template[i],!("string"==typeof n||n.position>=e)){e=n.position,n.text="";break}return e},pasteStringToMask:function(e,t){function n(e){return Math.max(e.mask.length,e.text.length)}function i(n){for(var i=0,o=[],r=a;rn[r].position-i-t&&o.push(n[r]):i+=n[r].length;return o[o.length-1]}e=e.replace(/\D/gi,"");var o=e.split(""),r=this.getItemTemplate(t),a=this.template.indexOf(r.item),l=0,s=i(this.template);l=s?this.template.indexOf(s):a;for(var u=0,d=0,c=a;cd&&o.splice(d,o.length),this.template[c].text=o.join("")+this.template[c].text.slice(o.length,d))},clearText:function(e,t){for(var n,i,o=0,r=this.template.length;o=e&&n.position0&&this.clearText(t,n);for(var a=0,l=r.length;at)break}}return t},deleteSelectedText:function(e,t,n){var i=this.clearText(e,t);return"undefined"!=typeof n&&(i=this.setCharAt(n,e)),i},getNextItemMask:function(e){var t,n,i;for(n=this.template.length-1;n>=0;n-=1)if(t=this.template[n],"string"!=typeof t){if(t.position<=e){e="undefined"==typeof i?this.moveToNextChar(e):i;break}i=t.position}return e},getText:function(){for(var e,t=this.template,n=[],i=0,o=t.length;i0)switch(o[0]){case"n":case"N":e=this.culture.numberFormatInfo.numberDecimalSeparator;break;case"p":case"P":e=this.culture.numberFormatInfo.percentDecimalSeparator;break;case"c":case"C":e=this.culture.numberFormatInfo.currencyDecimalSeparator}return e},getDecimalDigits:function(){var e=this.getItemTemplate(),t=e.item,n=/^([npc])(\d*)$/i,i=t.mask.match(n),o=0;if(i&&i.length>0)if(""!==i[2])o=+i[2];else switch(i[0]){case"n":case"N":o=this.culture.numberFormatInfo.numberDecimalDigits;break;case"p":case"P":o=this.culture.numberFormatInfo.percentDecimalDigits;break;case"c":case"C":o=this.culture.numberFormatInfo.currencyDecimalDigits}return o},reset:function(e){this.value=null,"undefined"!=typeof e&&null!==e&&""!==e&&(e=+e,isNaN(e)&&(e=null),this.value=e),this.template=this.buildTemplate(e)},buildTemplate:function(e){var t=/([npc])(\d*)/i,n=this.mask,i=[],o=this;return n.replace(t,function(t,n,r,a,l){i.push(l.slice(0,a)),i.push({mask:t,text:null===e?"":o.formatMask(e,t),value:e}),i.push(l.substring(a+t.length))}),this.template=i},getText:function(){var e,t=[];if(Array.isArray(this.template)){for(var n=0,i=this.template.length;n0?e-1:0;var t,n,i=this.getItemTemplate(),o=i.item,r=o.text;if(e=i.left&&t<=i.left+a.length)if(n=t-o,e==l)null===r.value&&(r.value=0,r.text=this.formatMask(r.value,r.mask)),r.text.indexOf(l)!==-1&&(t=o+r.text.indexOf(l)+l.length);else if(/\d/.test(e)){var s;s=a.indexOf(l)>-1&&n>a.indexOf(l),r.value=this.parseText([a.slice(0,n),e,a.slice(n)].join(""),r.value),r.text=this.formatMask(r.value,r.mask),""===a?t=this.moveToNextChar(o):(t=s?t+1:t+r.text.length-a.length,t=Math.min(t,o+this.getIndexOfEndDigit(r.text)))}return t},updateDigitValue:function(e,t){var n,i=this.getItemTemplate(),o=i.left,r=i.item,a=r.text;if(ei.left+a.length)return this.moveToNextChar(e);if(n=e-o,n>0){var l=a.substr(n-1,1);/\d/.test(l)&&(l=parseInt(l,10)+t,l>9&&(l=9),l<0&&(l=0),r.value=this.parseText([a.slice(0,n-1),l,a.slice(n)].join(""),r.value),r.text=this.formatMask(r.value,r.mask))}return e},setNextValue:function(e){return this.updateDigitValue(e,1)},setPrevValue:function(e){return this.updateDigitValue(e,-1)},deleteSelectedText:function(e,t,n){function i(e,t){return e.slice(0,t).split(" ").length-1}var o=this.getItemTemplate(),r=o.item,a=r.text,l=r.value.toString(),s=t+e;n||(n="");var u=a.slice(0,e),d=a.slice(0,s),c=u.split(" ").length-1,h=d.split(" ").length-1;e-=c,s-=h;var p=l.slice(0,e)+n+l.slice(s,l.length),m=this.formatMask(p,r.mask);return n?(e+=n.length+c,e+=i(m,e)):e+=i(m,e),_.isEmpty(p)&&(p=null),this.reset(p),p?e:0},deleteCharRight:function(e,t){if(t>0)return this.deleteSelectedText(e,t);var n,i=this.getItemTemplate(),o=i.left,r=i.item,a=r.text,l=this.getDecimalSeparator();if(ei.left+a.length)return this.moveToNextChar(0);if(a.length===t)return this.clearValue(r);n=e-o;var s=a.indexOf(l),u=a.substr(n).search(/\d/);if(0===r.value)r.value=null,r.text=this.formatMask(r.value,r.mask),e=o;else if(u>-1){u+=n;var d=a.split(l);n===d[0].length?r.value=this.parseText(d[0],r.value):r.value=this.parseText([a.substr(0,u),a.substr(u+1)].join(""),r.value),r.text=this.formatMask(r.value,r.mask),ui.left+a.length)return this.moveToNextChar(0);var u=this.getDecimalDigits();if(n=e-o,a.length===t)return this.clearValue(r);var d=!1;if(n<=0)return e;s>-1&&(d=n>s,n===a.length-u&&(n-=l.length,e-=l.length));var c=a.slice(0,n),h=/\d/.test(c)?c.length-c.split("").reverse().join("").search(/\d/)-1:0;return r.value=this.parseText(a.slice(0,h)+a.slice(h+1),r.value),r.text=this.formatMask(r.value,r.mask),e=d?e-1:e+r.text.length-a.length,0===r.value&&e<=1&&(r.value=null,r.text=this.formatMask(r.value,r.mask),e=o),e},getValue:function(){var e,t=this.getItemTemplate();return t&&(e=t.item.value),e},getIndexOfEndDigit:function(e){var t=e.split("").reverse().join("").search(/\d/);return t===-1?t:e.length-t},parseText:function(e,t){var n,i=this.getItemTemplate(),o=i.item,r=o.mask,a=this.getDecimalSeparator(),l=this.getDecimalDigits(),s=e.split(a);return s=s.map(function(e,t){var n=e.replace(/[^\d]/g,"");return 1===t?n.substr(0,l):n}),e=s.join("."),""===e?n=null:(n=+e,t<0&&(n=-n),/^p/.test(r)&&(n/=100)),n},getItemTemplate:function(){var e,t=this.template,n=0,i=null;if("undefined"==typeof t&&(this.reset(),t=this.template),!Array.isArray(t))return null;for(var o=0,r=t.length;o0){var o=i[0];if(!jQuery.contains(document,o.control.controlView.el))return;o.setFocus&&o.setFocus(),e()}},1e3/3);setTimeout(e,3e3)}}};window.InfinniUI.InlineViewBuilder=InlineViewBuilder,window.InfinniUI.LinkView=LinkView,_.extend(LinkView.prototype,{setOpenMode:function(e){_.isEmpty(e)||(this.openMode=e)},getOpenMode:function(){return this.openMode},setContainer:function(e){this.containerName=e},setViewTemplate:function(e){this.viewTemplate=e},setDialogWidth:function(e){e=e.toLowerCase(),"extralarge"==e&&(e="100%"),this.dialogWidth=e},createView:function(e){function t(t){n.view=t,n._initViewHandler(t),e(t)}var n=this;this.viewTemplate(t)},_initViewHandler:function(e){var t,n,i=this,o=i.openMode;switch(e.setParent&&e.setParent(this.parent),window.InfinniUI.global.messageBus.send("onViewCreated",{openMode:o,view:e}),o){case"Container":n=InfinniUI.global.containers[this.containerName],t=new OpenModeContainerStrategy,t.setView(e),t.setContainer(n),e.setOpenStrategy(t);break;case"Dialog":t=new OpenModeDialogStrategy,t.setView(e),this.dialogWidth&&t.setDialogWidth(this.dialogWidth),t.setView(e),e.setOpenStrategy(t); -}}}),window.InfinniUI.MetadataViewBuilder=MetadataViewBuilder,_.extend(MetadataViewBuilder.prototype,{build:function(e,t){var n=t.metadata,i=this.getParentViewByOpenMode(t,n.OpenMode),o=this.buildViewTemplate(t,i),r=new LinkView(i);return r.setViewTemplate(o),"OpenMode"in n&&r.setOpenMode(n.OpenMode),"Container"in n&&r.setContainer(n.Container),"DialogWidth"in n&&r.setDialogWidth(n.DialogWidth),r},buildViewTemplate:function(e,t){var n=e.metadata,i=this;return function(o){var r=window.InfinniUI.providerRegister.build("MetadataDataSource",n);r.getMetadata(function(r){if(null==r)return InfinniUI.global.logger.error("view metadata not found"),void InfinniUI.global.messageBus.send(messageTypes.onViewBuildError,{error:"metadata not found",metadata:n});var a=function(){var e=Array.prototype.slice.call(arguments);o.apply(null,e)};i.buildViewByMetadata(e,r,t,a)})}},buildViewByMetadata:function(e,t,n,i){var o=e.builder,r=this.buildParameters(e),a=o.buildType("View",t,{parentView:n,parent:n,params:r,suspended:e.suspended});i(a)},buildParameters:function(e){var t,n=e.metadata.Parameters,i=e.builder,o=e.parentView,r={};if("undefined"!=typeof n&&null!==n)for(var a=0;a'),e.find(".lastfocuselementinmodal").on("focusin",function(){e.find(".firstfocuselementinmodal").focus()}),e.keydown(function(t){$(document.activeElement).hasClass("lastfocuselementinmodal")&&9==(t.which||t.keyCode)&&(t.preventDefault(),e.find(".firstfocuselementinmodal").focus()),$(document.activeElement).hasClass("firstfocuselementinmodal")&&9==(t.which||t.keyCode)&&t.shiftKey&&(t.preventDefault(),e.find(".lastfocuselementinmodal").focus())})},close:function(){this.$modal&&this.$modal.modal("hide")},cleanup:function(){this.view.remove(),this.$modal.remove(),InfinniUI.ModalWindowService.modalWasClosed(this.$modal)}}),window.InfinniUI.global.culture=new Culture(InfinniUI.config.lang),window.InfinniUI.Culture=Culture,InfinniUI.localizations["ru-RU"].dateTimeFormatInfo={monthNames:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],abbreviatedMonthNames:["янв","фев","мар","апр","май","июн","июл","авг","сен","окт","ноя","дек"],dayNames:["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],abbreviatedDayNames:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],dateSeparator:".",timeSeparator:":",amDesignator:"",pmDesignator:"",firstDayOfWeek:1},InfinniUI.localizations["en-US"].dateTimeFormatInfo={monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dateSeparator:"/",timeSeparator:":",amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0};var localized=InfinniUI.localizations[InfinniUI.config.lang];InfinniUI.localizations["ru-RU"].numberFormatInfo={numberDecimalDigits:2,numberDecimalSeparator:",",numberGroupSeparator:" ",numberNegativePattern:"-n",numberPositivePattern:"n",percentDecimalDigits:2,percentDecimalSeparator:",",percentGroupSeparator:" ",percentSymbol:"%",percentNegativePattern:"-p%",percentPositivePattern:"p%",currencyDecimalDigits:2,currencyDecimalSeparator:",",currencyGroupSeparator:" ",currencySymbol:"р.",currencyNegativePattern:"-c$",currencyPositivePattern:"c$",negativeInfinitySymbol:"-бесконечность",positiveInfinitySymbol:"бесконечность",NaNSymbol:"NaN"},InfinniUI.localizations["en-US"].numberFormatInfo={numberDecimalDigits:2,numberDecimalSeparator:".",numberGroupSeparator:",",numberNegativePattern:"-n",numberPositivePattern:"n",percentDecimalDigits:2,percentDecimalSeparator:".",percentGroupSeparator:",",percentSymbol:"%",percentNegativePattern:"-p %",percentPositivePattern:"p %",currencyDecimalDigits:2,currencyDecimalSeparator:".",currencyGroupSeparator:",",currencySymbol:"$",currencyNegativePattern:"($c)",currencyPositivePattern:"$c",negativeInfinitySymbol:"-Infinity",positiveInfinitySymbol:"Infinity",NaNSymbol:"NaN"},InfinniUI.localizations["ru-RU"].patternDateFormats={f:"dd MMMM yyyy г. HH:mm",F:"dd MMMM yyyy г. HH:mm:ss",g:"dd.MM.yyyy HH:mm",G:"dd.MM.yyyy HH:mm:ss",d:"dd.MM.yyyy",D:"dd MMMM yyyy г.",t:"H:mm",T:"HH:mm:ss",y:"MMMM yyyy",Y:"MMMM yyyy",m:"MMMM yy",M:"MMMM yy",s:"yyyy-MM-ddTHH:mm:ss",u:"yyyy-MM-dd HH:mm:ssZ"},InfinniUI.localizations["en-US"].patternDateFormats={f:"dddd, MMMM dd, yyyy h:%m tt",F:"dddd, MMMM dd, yyyy h:%m:%s tt",g:"M/%d/yyyy h:%m tt",G:"M/%d/yyyy h:%m:%s tt",d:"M/%d/yyyy",D:"dddd, MMMM dd, yyyy",t:"h:%m tt",T:"h:%m:%s tt",y:"MMMM, yyyy",Y:"MMMM, yyyy",m:"MMMM yy",M:"MMMM yy",s:"yyyy-MM-ddTHH:mm:ss",u:"yyyy-MM-dd HH:mm:ssZ"},window.InfinniUI.ScriptBuilder=ScriptBuilder,ScriptBuilder.prototype.build=function(e,t){var n=t.metadata,i=n.Name,o=n.Body,r=new Function("context","args",o);return function(e,t){var n;try{n=r.call(void 0,e,t)}catch(a){console.groupCollapsed("%2$s: %1$c%3$s","color: #ff0000",i,a.message),console.error(o),console.groupEnd()}return n}},window.InfinniUI.ScriptExecutor=ScriptExecutor,ScriptExecutor.prototype.executeScript=function(e,t){var n,i,o,r=this.parent,a=r.getContext();return"{"==e.substr(0,1)?(i=e.substr(1,e.length-2),o=this.buildScriptByBody(i)):(o=r.getScripts().getById(e),o&&(o=o.func)),a&&o&&(n=o.call(void 0,a,t)),n},ScriptExecutor.prototype.buildScriptByBody=function(e){var t=this.parent.getContext(),n={metadata:{Body:e,Name:"InlineScript"}},i=new ScriptBuilder;return i.build(t,n)},InfinniUI.ModalWindowService=function(){function e(){var e=window.InfinniUI.global.messageBus;e.send("OnChangeLayout",{})}var t=[];return{modalWasOpened:function(e){if(0!=t.length){var n=t[t.length-1];n.modal.hide(),n.background.hide()}t.push(e)},modalWasClosed:function(n){for(var i=0,o=t.length;i0&&(s("on"),c())},l=function(t,n,i){o[t]||(o[t]=[],e&&e.on(t,d(t))),o[t].push({context:i,callback:n}),!r&&e&&c()},s=function(t){for(var n in o)"on"===t?e.on(n,d(n)):e.off(n)},u=function(t,n){if(n){for(var i=o[t],r=0,a=i.lenght;r0?_.debounce(this.onRequestsChanged.bind(this),50):this.onRequestsChanged.bind(this);this.on("change:requests",i)},onDataLoading:function(){var e=this.get("requests");this.set("requests",e+1)},onDataLoaded:function(){var e=this.get("requests");this.set("requests",e-1)},onRequestsChanged:function(e,t){this.set("progress",t>0)}}),AjaxLoaderIndicatorView=Backbone.View.extend({className:"pl-ajaxloader",template:InfinniUI.Template["services/ajaxLoaderIndicator/template/template.tpl.html"],hiddenClassName:"hidden",initialize:function(){this.listenTo(this.model,"change:progress",this.updateProgress)},render:function(){return this.$el.html(this.template()),this.updateProgress(),this},updateProgress:function(){var e=this.model.get("progress");this.$el.toggleClass(this.hiddenClassName,!e)}});InfinniUI.ContextMenuService=function(){function e(e){return e.control.controlView.$el}function t(e,t){e.on("contextmenu",function(e){e.preventDefault(),n.send(messageTypes.onOpenContextMenu.name,{x:e.pageX,y:e.pageY})})}var n=window.InfinniUI.global.messageBus;n.subscribe(messageTypes.onContextMenu.name,function(n,i){var o=i.value;t(e(o.source),o.content)})}();var MessageBox=Backbone.View.extend({tagName:"div",className:"modal fade messagebox",UI:{firstfocuselementinmodal:".firstfocuselementinmodal",lastfocuselementinmodal:".lastfocuselementinmodal"},events:{"click .btn":"onClickButtonHandler","focusin .lastfocuselementinmodal":"onFocusinLastElement",keydown:"onKeydownHandler"},template:InfinniUI.Template["services/messageBox/template/default.tpl.html"],initialize:function(e){this.setOptions(e),$(document.activeElement).blur(),this.render(),this.bindUIElements(),this.$el.modal({show:!0})},setOptions:function(e){this.options=this.applyDefaultOptions(e)},onFocusinLastElement:function(){this.ui.firstfocuselementinmodal.focus()},onKeydownHandler:function(e){document.activeElement===this.ui.lastfocuselementinmodal[0]&&9==(e.which||e.keyCode)&&(e.preventDefault(),this.ui.firstfocuselementinmodal.focus()),document.activeElement===this.ui.firstfocuselementinmodal[0]&&9==(e.which||e.keyCode)&&e.shiftKey&&(e.preventDefault(),this.ui.lastfocuselementinmodal.focus())},render:function(){var e=this.options.$parent||$("body"),t=this.template(this.options);return this.$el.html(t),this.subscribeToDialog(),e.append(this.$el),this},subscribeToDialog:function(){var e=this;this.$el.on("shown.bs.modal",function(t){e.ui.firstfocuselementinmodal.focus()}),this.$el.on("hidden.bs.modal",function(){e.remove()})},onClickButtonHandler:function(e){e.preventDefault();var t=$(e.target),n=parseInt(t.data("index"),10),i=this.options.buttons[n].onClick;i&&i.apply(null),this.close()},close:function(){"function"==typeof this.options.onClose&&this.options.onClose.call(null),this.$el.modal("hide")},applyDefaultOptions:function(e){var t=_.defaults({},e,{type:"default",buttons:[]});return this.applyDefaultButtonsOptions(t),t},applyDefaultButtonsOptions:function(e){return e.buttons.filter(function(e){return"undefined"==typeof e.type}).forEach(function(e){e.type="default"}),e}});_.extend(MessageBox.prototype,bindUIElementsMixin),InfinniUI.MessageBox=MessageBox;var routerService=function(e){if(!e)return null;var t=function(e){var t={};t.routes={};for(var n=0,o=e.length;n/g;r=l.exec(e[n].Path);)a=r[0].replace(/\s+/g,"").slice(2,-2),e[n].Path=e[n].Path.slice(0,r.index)+":"+a+e[n].Path.slice(r.index+r[0].length),l.lastIndex=r.index+a.length;t.routes[e[n].Path.slice(1)]=e[n].Name,t[e[n].Name]=i(e[n].Name,e[n].Action)}return t},n=function(t,n){for(var i=n||"yes",o=0,r=e.length;ot?1:0}Array.isArray(e)||(e=[]),this._items=e.map(function(e,t){return this.createCollectionItem(e,t)},this),this._idProperty=t,this._comparator=n||i,this.events=new CollectionEventManager}function CollectionEventManager(){}function BasePathOfProperty(e,t,n){this.isRelativeProperty(e)?this.basePathOfProperty=n.basePathOfProperty+this.excludeFirstChar(e):this.basePathOfProperty=e,n?(this.indexesInParentLists=n.indexesInParentLists?n.indexesInParentLists.slice():[],this.indexesInParentLists.push(t),this.parentBasePath=n):void 0!==t&&null!==t&&(this.indexesInParentLists=[t],this.basePathOfProperty+=t)}function EventsManager(){this.handlers={}}function HashMap(){this._keys=[],this._values=[]}function hiddenScreen(){this.middleElement=$("
").css({position:"absolute",top:"-10000px"})}function Logger(e){this.messages=[],this.setLevel(e||LOG_LEVEL.debug),this.showMessages=!0}function guid(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random()|0,n="x"==e?t:3&t|8;return n.toString(16)})}function MessageBus(e){function t(e){return"object"==typeof e&&"undefined"!=typeof e.name&&(e=e.name),e}var n={};this.send=function(i,o){if(i=t(i),n[i]){var r;e&&e.getContext&&(r=e.getContext()),_.each(n[i],function(e){e(r,{value:o})})}},this.subscribe=function(e,i){e=t(e),n[e]||(n[e]=[]),n[e].push(i)},this.unsubscribeByType=function(e){e=t(e),n[e]&&delete n[e]},this.getView=function(){return e}}function ContainerControl(e){_.superClass(ContainerControl,this,e)}function ListEditorBaseControl(e){_.superClass(ListEditorBaseControl,this,e),this.initialize_editorBaseControl()}function TextEditorBaseControl(e){_.superClass(TextEditorBaseControl,this,e),this.initialize_editorBaseControl()}function EventManager(){this.handlers={}}function TextEditorModelBaseModeStrategy(){}function TextEditorModelDisplayModeStrategy(){TextEditorModelBaseModeStrategy.call(this)}function TextEditorModelEditModeStrategy(){TextEditorModelBaseModeStrategy.call(this)}function TextBoxControl(e){_.superClass(TextBoxControl,this,e)}function DateTimePickerControl(e){_.superClass(DateTimePickerControl,this,e)}function DatePickerControl(e){_.superClass(DatePickerControl,this,e)}function TimePickerControl(e){_.superClass(TimePickerControl,this,e)}function getUserInfo(e){var t=new AuthenticationProvider(InfinniUI.config.serverUrl);t.getCurrentUser(function(t){e.model.set("result",t)},function(e){showObject("#signInInternalResult",e)})}function refreshUserInfo(){var e=new AuthenticationProvider(InfinniUI.config.serverUrl);e.getCurrentUser(function(e){InfinniUI.user.onReadyDeferred.resolve(e)},function(e){InfinniUI.user.onReadyDeferred.resolve(null)})}function changePassword(){var e=new AuthenticationProvider(InfinniUI.config.serverUrl);e.changePassword($("#oldPassword").val(),$("#newPassword").val(),function(e){refreshUserInfo()},function(e){showObject("#changePasswordResult",e)})}function changeProfile(){var e=new AuthenticationProvider(InfinniUI.config.serverUrl);e.changeProfile($("#displayName").val(),$("#description").val(),function(e){refreshUserInfo()},function(e){showObject("#changeProfileResult",e)})}function changeActiveRole(){var e=new AuthenticationProvider(InfinniUI.config.serverUrl);e.changeActiveRole($("#activeRole").val(),function(e){refreshUserInfo()},function(e){showObject("#сhangeActiveRoleResult",e)})}function getLinkExternalLoginForm(){var e=new AuthenticationProvider(InfinniUI.config.serverUrl);e.getLinkExternalLoginForm(getAbsoluteUri("/Home/SignInSuccess"),getAbsoluteUri("/Home/SignInFailure"),function(e){$("#linkExternalLoginForm").append(e)},function(e){showObject("#linkExternalLoginResult",e)})}function unlinkExternalLogin(e,t){var n=new AuthenticationProvider(InfinniUI.config.serverUrl);n.unlinkExternalLogin(e,t,function(e){refreshUserInfo()},function(e){showObject("#unlinkExternalLoginResult",e)})}function signOut(e){var t=new AuthenticationProvider(InfinniUI.config.serverUrl);onSuccessSignOut(getHomePageContext()),t.signOut(function(t){window.getCurrentUserName=function(){return null},e.model.set("result",null),location.reload()},function(e){showObject("#getCurrentUserResult",e.responseJSON)})}function setUserInfo(e){if(null!==e.Logins&&void 0!==e.Logins)for(var t=$("#externalLogins"),n=0;n-1&&toastr.error("Неверный логин или пароль","Ошибка!"),showObject("#signInInternalResult",e)})}function getSignInExternalForm(){var e=new AuthenticationProvider(InfinniUI.config.serverUrl);e.getSignInExternalForm(getAbsoluteUri("/Home/SignInSuccess"),getAbsoluteUri("/Home/SignInFailure"),function(e){$("#signInExternalForm").append(e)},function(e){showObject("#signInExternalResult",e)})}function getAbsoluteUri(e){return location.protocol+"//"+location.host+e}function showObject(e,t){var n=formatObject(t);$(e).text(n)}function formatObject(e){return JSON.stringify(e,null,4)}function AuthenticationProvider(e){this.baseAddress=e}function ButtonControl(e){_.superClass(ButtonControl,this,e)}function ButtonEditControl(e){_.superClass(ButtonEditControl,this,e)}function ComboBoxBaseViewStrategy(e){this.dropdownView=e}function ComboBoxGroupViewStrategy(e){ComboBoxBaseViewStrategy.call(this,e)}function ComboBoxPlainViewStrategy(e){ComboBoxBaseViewStrategy.call(this,e)}function DataGridControl(){_.superClass(DataGridControl,this)}function DataGridRowControl(){_.superClass(DataGridRowControl,this)}function DataNavigationButtonFactory(e){this._dataNavigation=e}function DataNavigationControl(e){_.superClass(DataNavigationControl,this,e)}function ListBoxViewGroupStrategy(e){this.listbox=e}function ListBoxViewPlainStrategy(e){this.listbox=e}function ListBoxControl(e){_.superClass(ListBoxControl,this,e)}function PopupButtonControl(e){_.superClass(PopupButtonControl,this,e)}function StackPanelControl(e){_.superClass(StackPanelControl,this,e)}function StackPanelViewGroupStrategy(e){this.stackPanel=e}function StackPanelViewPlainStrategy(e){this.stackPanel=e}function TablePanelControl(e){_.superClass(TablePanelControl,this,e)}function CellControl(e){_.superClass(CellControl,this,e)}function RowControl(e){_.superClass(RowControl,this,e)}function TabPanelControl(e){_.superClass(TabPanelControl,this,e)}function TabPageControl(e){_.superClass(TabPageControl,this,e)}function TreeViewControl(){_.superClass(TreeViewControl,this)}function CheckBoxControl(e){_.superClass(CheckBoxControl,this,e),this.initialize_editorBaseControl()}function ComboBoxControl(e){_.superClass(ListBoxControl,this,e)}function ContextMenuControl(){_.superClass(ContextMenuControl,this)}function DividerControl(e){_.superClass(DividerControl,this,e)}function FileBoxControl(e){_.superClass(FileBoxControl,this,e),this.initialize_editorBaseControl()}function FormControl(e){_.superClass(FormControl,this,e)}function GridPanelControl(e){_.superClass(GridPanelControl,this,e)}function IconControl(){_.superClass(IconControl,this)}function ImageBoxControl(e){_.superClass(ImageBoxControl,this,e),this.initialize_editorBaseControl()}function IndeterminateCheckBoxControl(e){_.superClass(IndeterminateCheckBoxControl,this,e),this.initialize_editorBaseControl()}function LinkElementControl(){_.superClass(LinkElementControl,this)}function MenuBarControl(e){_.superClass(MenuBarControl,this,e)}function NumericBoxControl(e){_.superClass(NumericBoxControl,this,e)}function PanelControl(e){_.superClass(PanelControl,this,e)}function ScrollPanelControl(e){_.superClass(ScrollPanelControl,this,e)}function ToggleButtonControl(e){_.superClass(ToggleButtonControl,this,e),this.initialize_editorBaseControl()}function ToolBarControl(e){_.superClass(ToolBarControl,this,e)}function ViewControl(e){_.superClass(ViewControl,this,e)}function Container(e,t){_.superClass(Container,this,e,t)}function ContainerBuilder(){_.superClass(ContainerBuilder,this)}function ListEditorBase(e,t){_.superClass(ListEditorBase,this,e,t),this.initialize_editorBase()}function ListEditorBaseBuilder(){_.superClass(ListEditorBaseBuilder,this),this.initialize_editorBaseBuilder()}function TextEditorBase(e){_.superClass(TextEditorBase,this,e),this.initialize_editorBase()}function TextEditorBaseBuilder(){_.superClass(TextEditorBaseBuilder,this),this.initialize_editorBaseBuilder()}function ListBox(e,t){_.superClass(ListBox,this,e,t)}function ListBoxBuilder(){_.superClass(ListBoxBuilder,this)}function TextBox(e){_.superClass(TextBox,this,e)}function TextBoxBuilder(){_.superClass(TextBoxBuilder,this)}function DateTimePicker(e){_.superClass(DateTimePicker,this,e)}function DateTimePickerBuilder(){_.superClass(DateTimePickerBuilder,this)}function DatePicker(e){_.superClass(DatePicker,this,e),this.setMode("DatePicker"),this.setTimeZone()}function DatePickerBuilder(){_.superClass(DatePickerBuilder,this)}function TimePicker(e){_.superClass(TimePicker,this,e),this.setMode("TimePicker"),this.setTimeZone()}function TimePickerBuilder(){_.superClass(TimePickerBuilder,this)}function StackPanel(e,t){_.superClass(StackPanel,this,e,t)}function StackPanelBuilder(){_.superClass(StackPanelBuilder,this)}function Button(e,t){_.superClass(Button,this,e,t),this.buttonInit()}function ButtonBuilder(){_.superClass(ButtonBuilder,this)}function ButtonEdit(e){_.superClass(ButtonEdit,this,e)}function ButtonEditBuilder(){_.superClass(ButtonEditBuilder,this)}function CheckBox(e){_.superClass(CheckBox,this,e),this.initialize_editorBase()}function CheckBoxBuilder(){_.superClass(CheckBoxBuilder,this),this.initialize_editorBaseBuilder()}function ComboBox(e){_.superClass(ComboBox,this,e)}function ComboBoxBuilder(){_.superClass(ComboBoxBuilder,this)}function ContextMenu(e){_.superClass(ContextMenu,this,e)}function ContextMenuBuilder(){_.superClass(ContextMenuBuilder,this)}function DataGrid(e){_.superClass(DataGrid,this,e)}function DataGridBuilder(){_.superClass(DataGridBuilder,this),this.columnBuilder=new DataGridColumnBuilder}function DataGridColumn(){this._values=Object.create(null)}function DataGridColumnBuilder(){}function DataGridRowBuilder(){_.superClass(DataGridRowBuilder,this)}function DataNavigation(e){_.superClass(DataNavigation,this,e)}function DataNavigationBuilder(){_.superClass(DataNavigationBuilder,this)}function Divider(e){_.superClass(Divider,this,e)}function DividerBuilder(){_.superClass(DividerBuilder,this)}function ExtensionPanel(e){_.superClass(ExtensionPanel,this,e)}function ExtensionPanelBuilder(){}function FileBox(e){_.superClass(FileBox,this,e),this.initialize_editorBase()}function FileBoxBuilder(){_.superClass(FileBoxBuilder,this),this.initialize_editorBaseBuilder()}function FileBoxValueConverter(e){this._element=e}function Form(e){_.superClass(Form,this,e)}function FormBuilder(){_.superClass(FormBuilder,this)}function Frame(){_.superClass(Frame,this),this.initialize_editorBase()}function FrameBuilder(){_.superClass(TextEditorBaseBuilder,this),this.initialize_editorBaseBuilder()}function GridPanel(e){_.superClass(GridPanel,this,e)}function GridPanelBuilder(){_.superClass(GridPanelBuilder,this)}function Icon(e){_.superClass(Icon,this,e)}function IconBuilder(){_.superClass(ButtonBuilder,this)}function ImageBox(e){_.superClass(ImageBox,this,e),this.initialize_editorBase()}function ImageBoxBuilder(){_.superClass(ImageBoxBuilder,this),this.initialize_editorBaseBuilder()}function ImageBoxValueConverter(e){this._element=e}function IndeterminateCheckBox(e){_.superClass(IndeterminateCheckBox,this,e),this.initialize_editorBase()}function IndeterminateCheckBoxBuilder(){_.superClass(IndeterminateCheckBoxBuilder,this),this.initialize_editorBaseBuilder()}function Label(e,t){_.superClass(Label,this,e,t),this.initialize_editorBase()}function LabelBuilder(){_.superClass(TextEditorBaseBuilder,this),this.initialize_editorBaseBuilder()}function Link(e){_.superClass(Link,this,e)}function LinkBuilder(){_.superClass(LinkBuilder,this)}function MenuBar(e){_.superClass(MenuBar,this,e)}function MenuBarBuilder(){_.superClass(MenuBarBuilder,this)}function NumericBox(e){_.superClass(NumericBox,this,e)}function NumericBoxBuilder(){_.superClass(NumericBoxBuilder,this)}function Panel(e){_.superClass(Panel,this,e)}function PanelBuilder(){_.superClass(PanelBuilder,this)}function PasswordBox(e){_.superClass(PasswordBox,this,e),this.initialize_editorBase()}function PasswordBoxBuilder(){_.superClass(PasswordBoxBuilder,this),this.initialize_editorBaseBuilder()}function PopupButton(e,t){_.superClass(PopupButton,this,e,t),this.buttonInit()}function PopupButtonBuilder(){_.superClass(PopupButtonBuilder,this)}function RadioGroupBuilder(){_.superClass(RadioGroupBuilder,this)}function ScrollPanel(e){_.superClass(ScrollPanel,this,e)}function ScrollPanelBuilder(){_.superClass(ScrollPanelBuilder,this)}function TabPanel(e){_.superClass(TabPanel,this,e)}function TabPanelBuilder(){_.superClass(TabPanelBuilder,this)}function TablePanel(e){_.superClass(TablePanel,this,e)}function TablePanelBuilder(){_.superClass(TablePanelBuilder,this)}function ToggleButton(e){_.superClass(ToggleButton,this,e),this.initialize_editorBase()}function ToggleButtonBuilder(){_.superClass(ToggleButtonBuilder,this),this.initialize_editorBaseBuilder()}function ToolBarBuilder(){_.superClass(ToolBarBuilder,this)}function TooltipBuilder(){_.superClass(TooltipBuilder,this)}function TreeView(e){_.superClass(TreeView,this,e)}function TreeViewBuilder(){_.superClass(TreeViewBuilder,this)}function View(e){_.superClass(View,this,e);var t=this;this.eventManager=new EventManager,this.openStrategy=new OpenModeDefaultStrategy,this.openStrategy.setView(this),this.members={},this.membersDeferreds={},this.handlers={onBeforeLoaded:$.Deferred(),onLoaded:$.Deferred(),onSelectedElementChange:null},this._initContext();var n=this.getView();n&&(n.onClosing&&n.onClosing(function(e,n){if(!t.isRemoved)return t.eventManager.trigger("onClosing",t.getContext(),t._getScriptArgs())}),n.onClosed&&n.onClosed(function(e,n){t.close(null,null,!0)})),this.control.get("dataSources").onChange(function(){t._initDataSourceHandlers()})}function ViewBuilder(){_.superClass(ViewBuilder,this)}function ViewPanel(e){_.superClass(ViewPanel,this,e)}function ViewPanelBuilder(){}function DataGridRow(){_.superClass(DataGridRow,this),this._transformRowProperties({rowBackground:"background",rowForeground:"foreground",rowTextStyle:"textStyle",rowStyle:"style"})}function TabPage(e){_.superClass(TabPage,this,e),this.events=new EventsManager;var t=this;this.control.on("close",function(){t.close()})}function TabPageBuilder(){_.superClass(TabPageBuilder,this)}function Cell(e){_.superClass(Cell,this,e)}function CellBuilder(){_.superClass(CellBuilder,this)}function Row(e){_.superClass(Row,this,e)}function RowBuilder(){_.superClass(RowBuilder,this)}function BaseAction(e){this.parentView=e,this._properties=Object.create(null),_.defaults(this._properties,this.defaults),this.initDefaultValues()}function BaseEditAction(e){_.superClass(BaseEditAction,this,e)}function AcceptAction(e){_.superClass(AcceptAction,this,e)}function AcceptActionBuilder(){}function AddAction(e){_.superClass(AddAction,this,e)}function AddActionBuilder(){}function CancelAction(e){_.superClass(CancelAction,this,e)}function CancelActionBuilder(){}function DeleteAction(e){_.superClass(DeleteAction,this,e)}function DeleteActionBuilder(){}function EditAction(e){_.superClass(EditAction,this,e)}function EditActionBuilder(){}function OpenAction(e){_.superClass(OpenAction,this,e)}function OpenActionBuilder(){}function RouteToAction(){_.superClass(RouteToAction,this),this.href=""}function RouteToActionBuilder(){}function SaveAction(e){_.superClass(SaveAction,this,e)}function SaveActionBuilder(){}function SelectAction(e){_.superClass(SelectAction,this,e)}function SelectActionBuilder(){}function DownloadExecutor(e,t,n){this.guid=guid(),this.options={timeout:6e4,poll:100},this.resultCallback=e,this.successCallback=t,this.failCallback=n}function ServerAction(e){_.superClass(ServerAction,this,e),this.provider=window.InfinniUI.providerRegister.build("ServerActionProvider"),this.updateContentTypeStrategy(),this.on("change:contentType",this.updateContentTypeStrategy)}function ServerActionBuilder(){}function UpdateAction(e){_.superClass(UpdateAction,this,e)}function UpdateActionBuilder(){}function ApplicationBuilder(){this.builder||(this.builder=new Builder,this.registerElementBuilders()),window.InfinniUI.global.factory=this}function Builder(){var e=[];this.appView=null,this.register=function(t,n){e[t]=n},this.buildType=function(t,n,i){if(i=i||{},void 0===e[t])return null;var o=_.extend({builder:this,metadata:n},i),r=i.parentView?i.parentView.getContext():{};return e[t].build(r,o)},this.build=function(e,t){var n,i,o=null;t=t||{};for(var r in e){n=r;break}return"undefined"==typeof n||null===n?console.error("Builder: Не переданы метаданные"):(i=e[n],o=this.buildType(n,i,t)),o},this.buildMany=function(e,t){var n=[];if(e)for(var i=0;i0;return e.forEach(function(e){var n=this.createCollectionItem(e,t.length);t.push(n)},this),n&&this.events.onAdd(e),n},Collection.prototype.insert=function(e,t){var n=this.createCollectionItem(t,e);return this._items.splice(e,0,n),this.events.onAdd([t],e),!0},Collection.prototype.insertAll=function(e,t){if(!Array.isArray(t))return!1;var n=this._items,i=t.length>0;return t.forEach(function(t,i){var o=e+i,r=this.createCollectionItem(t,o);n.splice(o,0,r)},this),i&&this.events.onAdd(t,e),i},Collection.prototype.reset=function(e){var t,n;return!!Array.isArray(e)&&(t=this._items.length!==e.length,n=e.map(function(e,n){return t||(t=!this.isEqual(e,this.getCollectionItemValue(n))),this.createCollectionItem(e,n)},this),this._items.length=0,Array.prototype.push.apply(this._items,n),t&&this.events.onReset(),t)},Collection.prototype.set=function(e,t){var n=this._items;if(!Array.isArray(e))return!1;var i=n.length!==e.length,o=e.slice();return o.forEach(function(e,t){t=this._items.length)return!1;var t=this.getCollectionItemValue(e);return this._items.splice(e,1),this.events.onRemove([t],e),!0},Collection.prototype.removeAll=function(e){ +if(!Array.isArray(e))return!1;var t,n=this._items,i=[];if(e.forEach(function(e){i=n.filter(function(t){return this.isEqual(e,this.getItemValue(t))},this),i.forEach(function(e){var t=n.indexOf(e);n.splice(t,1)})},this),t=i.length>0){var o=i.map(function(e){return this.getItemValue(e)},this);this.events.onRemove(o)}return t},Collection.prototype.removeRange=function(e,t){var n,i=this._items;if(e>=i.length)return!1;"undefined"==typeof t&&(t=i.length-e);var o=i.splice(e,t);if(n=o.length>0){var r=o.map(function(e){return this.getItemValue(e)},this);this.events.onRemove(r,e)}return n},Collection.prototype.removeEvery=function(e,t){if("function"!=typeof e)return!1;var n,i=this._items,o=i.filter(function(n,i){var o=this.getItemValue(n);return e.call(t,o,i,this)},this);if(o.forEach(function(e){var t=i.indexOf(e);i.splice(t,1)}),n=o.length>0){var r=o.map(function(e){return this.getItemValue(e)},this);this.events.onRemove(r)}return n},Collection.prototype.clear=function(){var e=this._items,t=e.length>0,n=e.map(function(e){return this.getItemValue(e)},this);return e.length=0,t&&this.events.onRemove(n,0),t},Collection.prototype.getById=function(e){if(!this.hasIdProperty)return!1;for(var t,n,i=this._items,o=0;o=n.length)return-1;for(var o=t;o>0;o-=1){var r=this.getItemValue(n[o]);if(this.isEqual(e,r)){i=o;break}}return i},Collection.prototype.findIndex=function(e,t){if("function"!=typeof e)return!1;var n=this._items,i=-1,o=n.some(function(n,o){var r=this.getItemValue(n);return i=o,e.call(t,r,o,this)},this);return o?i:-1},Collection.prototype.contains=function(e,t){t=t||0;for(var n=!1,i=this._items,o=t;o=i.length||e===t)return!1;n=i.splice(e,1).pop(),e>t?i.splice(t,0,n):i.splice(t-1,0,n);var o=i[e]!==n;if(o){var r=this.getItemValue(n);this.events.onMove([r],[r],e,t)}return o},Collection.prototype.sort=function(e){"function"!=typeof e&&(e=this._comparator);var t=this._items,n=this,i=t.slice(),o=!1;t.sort(function(t,i){return e(n.getItemValue(t),n.getItemValue(i))});for(var r=0;r0?"-":"+",c=[h(Math.floor(u/60),2),h(u%60,2)].join(":");return o+"T"+r+"."+l+d+c}function u(e){var t,n=null;return e&&e.constructor===String?t=new Date(e):e&&e.constructor===Date&&(t=e),t&&(t.setUTCHours(0,0,0,0),n=t.getTime()/1e3),n}function d(e){var t,n,i=null;return e&&e.constructor===String?t=new Date(e):e&&e.constructor===Date&&(t=e),t&&(n=new Date(0),n.setUTCHours(t.getUTCHours(),t.getUTCMinutes(),t.getUTCSeconds(),t.getUTCMilliseconds()),i=n.getTime()/1e3),i}function c(e){var t;return t=typeof e===Date?new Date(e.getTime()):"number"==typeof e?new Date(1e3*e):"undefined"==typeof e||null===e?null:r(e)}function p(){return f}function h(e,t){var n=""+e,i="";return n.length0&&setTimeout(function(){i.whenReady(e,t,n-1)},510)}};window.InfinniUI.ObjectUtils=function(){function e(e,t){if(null!==e&&void 0!==e&&null!==t&&void 0!==t){for(var n=e,r=t.length,l=0;l=0?o(n,u):a(n,s)}return n}return e}function t(e,t,n){for(var s=e,u=t.length-1,d=t[0],c=i(d),p=0;p=0?o(s,c):a(s,d),m=t[p+1],f=i(m);f>=0?($.isArray(h)||(h=[]),r(s,c,h)):($.isPlainObject(h)||(h={}),l(s,d,h)),s=h,d=m,c=f}c>=0?r(s,c,n):l(s,d,n)}function n(e){return _.isEmpty(e)?null:e.split(".")}function i(e){var t=-1;if("$"===e)t=0;else{var n=parseInt(e);isNaN(n)||(t=n)}return t}function o(e,t){return null!==e&&void 0!==e&&"[object Array]"===Object.prototype.toString.call(e)&&t>=0&&t=0&&t1&&(","===t[0].slice(-1)||")"===t[0].slice(-1))&&(t[0]=t[0].slice(0,-1)),t[0].length>1&&"'"===t[0].slice(0,1)&&(t[0]=t[0].slice(1,-1)),t[0].search(/tmpRE/)!==-1&&(t[0]=t[0].slice(1,-1).split(","),t[0][0]=r),m.push(t);for(;t=d.exec(e);)m.push(t);return m.sort(function(e,t){return e.index-t.index}),m},n=function(e){for(var t,n,i,o,r=[],a=[],l=[],s=0,u=0,d=e.length;ue[o].range[0]&&t[n].indexe[n].range[0]&&e[t].range[1]e[t].range[0]){e[n].children.unshift(e[t]),e.splice(t,1),t-=1;break}e[n].children.push(e[t]),e.splice(t,1),t-=1;break}return e[0]};return e.buildUpFilterTree=function(e){var r;return r=t(e),r=n(r),r=i(r[0],r[1]),o(r)},e}(),filterItems.filterMethods=function(){var e={};return e.eq=function(e,t,n){for(var i,o,r=[],a=InfinniUI.ObjectUtils,l=0,s=t.length;le[1]&&i.push(t[l]);o===i.length&&r.push(t[l])}else a.getPropertyValue(t[l],e[0])>e[1]&&r.push(t[l]);return r},e.gte=function(e,t,n){for(var i,o,r=[],a=InfinniUI.ObjectUtils,l=0,s=t.length;l=e[1]&&i.push(t[l]);o===i.length&&r.push(t[l])}else a.getPropertyValue(t[l],e[0])>=e[1]&&r.push(t[l]);return r},e.lt=function(e,t,n){for(var i,o,r=[],a=InfinniUI.ObjectUtils,l=0,s=t.length;le[1]){o.push(t[a]);break}}return o},e.anyGte=function(e,t,n){for(var i,o=[],r=InfinniUI.ObjectUtils,a=0,l=t.length;a=e[1]){o.push(t[a]);break}}return o},e.anyLt=function(e,t,n){for(var i,o=[],r=InfinniUI.ObjectUtils,a=0,l=t.length;ae[1]&&o.push(t[a]);return o},e.sizeGte=function(e,t,n){for(var i,o=[],r=InfinniUI.ObjectUtils,a=0,l=t.length;a=e[1]&&o.push(t[a]);return o},e.sizeLt=function(e,t,n){for(var i,o=[],r=InfinniUI.ObjectUtils,a=0,l=t.length;a=this.KeyCode.NUMPAD_0&&e<=this.KeyCode.NUMPAD_9)n=e-48;else switch(e){case 110:n=this.KeyCode.DELETE;break;case 107:n=this.KeyCode.PLUS;break;case 109:n=this.KeyCode.MINUS;break;case 106:n=this.KeyCode.ASTERISK;break;case 111:n=this.KeyCode.SLASH;break;case 188:n=44;break;case 173:n=45;break;case 190:n=46;break;case 191:n=47;break;case 192:n=96;break;case 219:n=91;break;case 220:n=92;break;case 221:n=93;break;case 222:n=39;break;default:n=e}t=String.fromCharCode(n)}return t}};var layoutManager={windowHeight:0,clientHeight:0,exchange:null,times:[],setOuterHeight:function(e,t,n){var i=0;"border-top-width,border-bottom-width,padding-top,padding-bottom,margin-top,margin-bottom".split(",").forEach(function(t){i+=parseInt(e.css(t))});var o=t-i;return n&&(o+=n),e.height(o),o},getModalSelector:function(){return".modal-scrollable"},getSelector:function(){return".verticalAlignmentStretch:not(:hidden)"},buildTree:function(e,t,n,i,o){var e=_.where(o,{parent:t}),r=this;return{isElement:_.indexOf(i,t)!==-1,element:t,$element:n,child:_.map(e,function(t){return r.buildTree(e,t.element,t.$element,i,o)})}},formTree:function(e,t,n){for(var i,o,r,a=[],l=0,s=e.length;l0&&this.goThroughTree(e,n))},goThroughTree:function(e,t){var n=this;e.$element.parentsUntil(".modal").length&&e.$element.attr("data-height-original",e.element.style.height);var i=e.$element.children(":not(:hidden):not(.modal-scrollable):not(.modal-backdrop):not(.pl-dropdown-container)"),o=_.chain(i).filter(function(e){var t=$(e).css("position");return["absolute","fixed"].indexOf(t)===-1}).groupBy("offsetTop").value(),r=[];_.each(o,function(t,n){var i=[];_.each(t,function(t){var n=_.find(e.child,function(e){return e.element===t});n&&i.push(n)}),r.push(i.length?0:_.reduce(t,function(e,t){return Math.max(e,$(t).outerHeight(!0))},0)),o[n]=i},this);var a=_.reduce(r,function(e,t){return e+t},0),l=_.reduce(o,function(e,t){return t.length?e+1:e},0),s=Math.floor((t-a)/l);_.each(o,function(e){0!==e.length&&_.each(e,function(e){n.defineWay(e,s)},this)},this)},resize:function(e,t){var n=Date.now(),i=$(e),o=(this.setOuterHeight(i,t),i.find(this.getSelector()));if(0!==o.length){var r=this.formTree(o,e,i);this.defineWay(r,t);var a=Date.now();this.timeWatcher(a-n)}},timeWatcher:function(e){e>=20&&this.times.push(e)},getTimes:function(){return this.times},resizeView:function(e,t){var n=$("#page-content",e),i=this.setOuterHeight(n,t);this.resize(n.get(0),i)},resizeDialog:function(){var e=$(this.getModalSelector()).last();this._resizeDialog(e),this.resetDialogHeight(e)},resetDialogHeight:function(e){if(e.children()){var t=e.children(),n=$(".modal-header",t),i=$(".modal-body",t),o=$(this.getSelector(),e);o.parentsUntil(".modal").css("height","auto"),t.css("top",(this.windowHeight-n.outerHeight(!0)-i.outerHeight(!0))/2),e.children(".modal:not(.messagebox)").height(i.outerHeight(!0)+n.outerHeight(!0))}},_resizeDialog:function(e){var t=10,n=e.children();n.css("margin-top",0);var i=$(".modal-header",n),o=$(".modal-body",n),r=i.outerHeight(!0);o.css("max-height",this.windowHeight-r),n.css("margin-top",0);var a=$(this.getSelector(),e);if(0!==a.length){var l=this.setOuterHeight(e,this.windowHeight-2*t),s=this.setOuterHeight(n,l)-i.outerHeight();this.resize(o[0],s)}},init:function(e){return window.InfinniUI.config.disableLayoutManager!==!0&&(e=e||document,$("#page-content").addClass("page-content-overflow-hidden"),this.windowHeight=$(window).height(),this.onChangeLayout(e),void(null===this.exchange&&(this.exchange=window.InfinniUI.global.messageBus,this.exchange.subscribe("OnChangeLayout",_.debounce(this.onChangeLayout.bind(this),42)))))},onChangeLayout:function(e){_.isEmpty(e)&&(e=document);var t=this.windowHeight-$("#page-top:not(:hidden)",e).outerHeight()-$("#page-bottom:not(:hidden)",e).outerHeight()-$("#menu-area:not(:hidden)",e).outerHeight();this.resizeView(e,t),this.resizeDialog()}};window.InfinniUI.LayoutManager=layoutManager;var LOG_LEVEL={debug:1,info:2,warn:3,error:4,trace:5};_.extend(Logger.prototype,{getLevel:function(){return this.level},setLevel:function(e){this.level=e},addMessage:function(e,t){this.messages.push({type:e,message:t})},debug:function(e){this.level>LOG_LEVEL.debug||(this.showMessages&&console.debug(e.message||e),this.addMessage(LOG_LEVEL.debug,e))},info:function(e){this.level>LOG_LEVEL.info||(this.showMessages&&console.info(e.message||e),this.addMessage(LOG_LEVEL.info,e))},warn:function(e){this.level>LOG_LEVEL.warn||(this.showMessages&&console.warn(e.message||e),this.addMessage(LOG_LEVEL.warn,e))},error:function(e){this.level>LOG_LEVEL.error||(this.showMessages&&console.error(e.message||e),this.addMessage(LOG_LEVEL.error,e))},trace:function(e){this.level>LOG_LEVEL.trace||(this.showMessages&&console.error(e.message||e),this.addMessage(LOG_LEVEL.trace,e))}}),window.InfinniUI.global.logger=new Logger,InfinniUI.Metadata=InfinniUI.Metadata||{},InfinniUI.Metadata.isValidValue=function(e,t){var n=!1;for(var i in t)if(t[i]===e){n=!0;break}return n},InfinniUI.Metadata.isBindingMetadata=function(e){return $.isPlainObject(e)&&"Source"in e},Number.isInteger=Number.isInteger||function(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e},String.prototype.includes||(String.prototype.includes=function(){return String.prototype.indexOf.apply(this,arguments)!==-1});var stringUtils={format:function(e,t){return e.replace(/{(\d+)}/g,function(e,n){return"undefined"!=typeof t[n]?t[n]:e})},formatProperty:function(e,t){if(!t||0==t.length||""==e)return e; +for(var n=e.split("."),i=t.length-1,o=n.length-1;o>=0;o--)"#"==n[o]&&i>=0?(n[o]=t[i],i--):("$"==n[o]||stringUtils.isNumeric(n[o]))&&i--;return n.join(".")},padLeft:function(e,t,n){"undefined"!=typeof n&&null!==n||(n=" ");var i=String(e);return i.length0&&(e=location.href.indexOf(n),e>0&&(t=location.href.substr(0,e))),t&&history.pushState(null,null,t)},setParameter:function(e,t){var n=location.search,i=_.isEmpty(n)?stringUtils.format("?{0}={1}",[e,t]):stringUtils.format("{0}&{1}={2}",[n,e,t]),o=stringUtils.format("{0}//{1}{2}{3}{4}",[location.protocol,location.host,location.pathname,i,location.hash]);history.pushState(null,null,o)},deleteParameter:function(e){function t(e){var t=[];return _.mapObject(e,function(e,n){var i=stringUtils.format("{0}={1}",[n,e]);t.push(i)}),_.isEmpty(t)?"":"?"+t.join("&")}var n=urlManager.getParams();delete n[e];var i=t(n),o=stringUtils.format("{0}//{1}{2}{3}{4}",[location.protocol,location.host,location.pathname,i,location.hash]);history.pushState(null,null,o)}};window.InfinniUI.UrlManager=urlManager,window.InfinniUI.global.messageBus=new MessageBus,window.messageTypes={onViewBuildError:{name:"onViewBuildError"},onViewCreated:{name:"onViewCreated"},onChangeLayout:{name:"OnChangeLayout"},onNotifyUser:{name:"onNotifyUser"},onToolTip:{name:"onToolTip"},onRemove:{name:"onRemove"},onContextMenu:{name:"onContextMenu"},onOpenContextMenu:{name:"onOpenContextMenu"},onDataLoading:{name:"onDataLoading"},onDataLoaded:{name:"onDataLoaded"},onToolTipDestroy:{name:"onToolTipDestroy"},onToolTipInit:{name:"onToolTipInit"}};var ajaxRequestMixin=function(e){function t(e,t){var n;return"function"==typeof e&&(n=e.apply(null,Array.prototype.slice.call(t))),n}return{onBeforeRequest:function(n){return function(){return e.send(messageTypes.onDataLoading,{}),t(n,arguments)}},onSuccessRequest:function(n){return function(){return e.send(messageTypes.onDataLoaded,{success:!0}),t(n,arguments)}},onErrorRequest:function(n){return function(){return e.send(messageTypes.onDataLoaded,{success:!1}),t(n,arguments)}}}}(window.InfinniUI.global.messageBus),bindUIElementsMixin={bindUIElements:function(){if(this.ui={},"undefined"!=typeof this.UI)for(var e in this.UI)this.UI.hasOwnProperty(e)&&(this.ui[e]=this.$(this.UI[e]))}},eventHandlerMixin={addEventHandler:function(e,t){if(this.initEventHandlerMixin(),null===e||"undefined"==typeof e)return!1;if(null===t||"undefined"==typeof t)return!1;"undefined"==typeof this.eventHandlers[e]&&(this.eventHandlers[e]=[]);var n=this.eventHandlers[e];n.indexOf(t)===-1&&n.push(t)},callEventHandler:function(e){if("undefined"!=typeof this.eventHandlers&&null!==e&&"undefined"!=typeof e){var t=this.eventHandlers[e];if("undefined"!=typeof t){var n,i=Array.prototype.slice.call(arguments,1),o=i.pop();"function"==typeof o&&(n=o),o=i.pop(),_.each(t,function(e){var t=e.apply(void 0,o);"undefined"!=typeof n&&n(t)})}}},initEventHandlerMixin:function(){"undefined"==typeof this.eventHandlers&&(this.eventHandlers={})}},Control=function(e){this.controlModel=this.createControlModel(),this.controlView=this.createControlView(this.controlModel,e),this.initHandlers()};_.extend(Control.prototype,{createControlModel:function(){throw"Не перегружен абстрактный метод Control.createControlModel()"},createControlView:function(e,t){throw"Не перегружен абстрактный метод Control.createControlView()"},initHandlers:function(){this.controlView.on("onLoaded",function(){this.controlModel.set("isLoaded",!0)},this)},set:function(e,t){this.controlModel.set(e,t)},get:function(e){return this.controlModel.get(e)},on:function(e,t){return this.controlModel.on(e,t)},render:function(){return this.controlView.render().$el},getChildElements:function(){return[]},onLoaded:function(e){this.controlModel.on("change:isLoaded",function(t){t&&e()})},isLoaded:function(){return this.controlModel.get("isLoaded")},onBeforeClick:function(e){this.controlView.on("beforeClick",e)},onClick:function(e){this.controlView.$el.on("click",e)},onDoubleClick:function(e){this.controlView.$el.on("dblclick",e)},onMouseDown:function(e){this.controlView.$el.on("mousedown",e)},onMouseUp:function(e){this.controlView.$el.on("mouseup",e)},onMouseEnter:function(e){this.controlView.$el.on("mouseenter",e)},onMouseLeave:function(e){this.controlView.$el.on("mouseleave",e)},onMouseMove:function(e){this.controlView.$el.on("mousemove",e)},onMouseWheel:function(e){this.controlView.$el.on("mousewheel DOMMouseScroll",e)},onKeyDown:function(e){this.controlView.$el.on("keydown",e)},onKeyUp:function(e){this.controlView.$el.on("keyup",e)},onRemove:function(e){this.controlView.on(messageTypes.onRemove.name,e)},remove:function(){this.controlView.remove()},setFocus:function(){this.controlView.setFocus()}}),InfinniUI.Control=Control;var ControlModel=Backbone.Model.extend({defaults:{text:null,name:null,enabled:!0,parentEnabled:!0,visible:!0,textHorizontalAlignment:InfinniUI.TextHorizontalAlignment.left,horizontalAlignment:"Stretch",verticalAlignment:"Top",textStyle:null,background:null,foreground:null,isLoaded:!1,validationState:"success",validationMessage:"",focusable:!0,focused:!1},initialize:function(){this.set("guid",guid(),{silent:!0}),this.on("change:focused",function(e,t){this.trigger(t?"OnGotFocus":"OnLostFocus")})},set:function(e,t,n){var i,o=this.defaults;if(null==e)return this;"object"==typeof e?(i=e,n=t):(i={})[e]=t;for(var r in i)"undefined"!=typeof i[r]&&null!==i[r]||r in o&&(i[r]=o[r]);return Backbone.Model.prototype.set.call(this,i,n)}});InfinniUI.ControlModel=ControlModel;var ControlView=Backbone.View.extend({initialize:function(){this.wasRendered=!1,this.once("render",this.initHandlersForProperties,this),this._initDomHandlers()},classNameFocused:"pl-focused",_initDomHandlers:function(){var e=this,t=this.$el;t[0].addEventListener("click",function(t){e.trigger("beforeClick",null,{value:t})},!0)},initHandlersForProperties:function(){this.listenTo(this.model,"change:visible",this.updateVisible),this.listenTo(this.model,"change:horizontalAlignment",this.updateHorizontalAlignment),this.listenTo(this.model,"change:textHorizontalAlignment",this.updateTextHorizontalAlignment),this.listenTo(this.model,"change:verticalAlignment",this.updateVerticalAlignment),this.listenTo(this.model,"change:enabled",this.updateEnabled),this.listenTo(this.model,"change:name",this.updateName),this.listenTo(this.model,"change:style",this.updateStyle),this.listenTo(this.model,"change:text",this.updateText),this.listenTo(this.model,"change:textStyle",this.updateTextStyle),this.listenTo(this.model,"change:background",this.updateBackground),this.listenTo(this.model,"change:foreground",this.updateForeground),this.listenTo(this.model,"change:validationState",this.updateValidationState),this.listenTo(this.model,"change:focusable",this.updateFocusable),this.listenTo(this.model,"change:focused",this.updateFocused),this.initFocusHandlers()},initFocusHandlers:function(){function e(e){o.set("focused",!0)}function t(e){i.isControlElement(e.relatedTarget)?o.set("focused",!0):o.set("focused",!1)}var n=this.$el,i=(this.el,this),o=this.model;n.on("focusin",e).on("focusout",t)},isControlElement:function(e){return this.el===e||$.contains(this.el,e)},updateProperties:function(){this.updateVisible(),this.updateTextHorizontalAlignment(),this.updateHorizontalAlignment(),this.updateVerticalAlignment(),this.updateEnabled(),this.updateName(),this.updateText(),this.updateStyle(),this.updateTextStyle(),this.updateBackground(),this.updateForeground(),this.updateValidationState(),this.updateFocusable(),this.updateFocused(),this.updateViewMode()},updateFocusable:function(){},getElementForFocus:function(){return this.$el},updateFocused:function(){var e=this.model.get("focused");if(e){var t=this.getElementForFocus();t&&t.length}this.$el.toggleClass(this.classNameFocused,e)},onFocusHandler:function(e){},updateVisible:function(){var e=this.model.get("visible");this.$el.toggleClass("hidden",!e),this.onUpdateVisible()},onUpdateVisible:function(){this.updateLayout()},updateLayout:function(){var e=window.InfinniUI.global.messageBus;e.send("OnChangeLayout",{})},updateEnabled:function(){var e=this.model.get("enabled");this.$el.toggleClass("pl-disabled",!e)},updateVerticalAlignment:function(){this.switchClass("verticalAlignment",this.model.get("verticalAlignment"),this.$el,!1)},updateTextHorizontalAlignment:function(){this.switchClass("pl-text-horizontal",this.model.get("textHorizontalAlignment"))},updateHorizontalAlignment:function(){this.switchClass("pl-horizontal",this.model.get("horizontalAlignment"))},updateName:function(){var e=this.model.get("name"),t=this.$el.attr("data-pl-name");e!=t&&"string"==typeof e&&this.$el.attr("data-pl-name",e)},updateText:function(){},updateTextStyle:function(){var e=this.model.get("textStyle");this.currentTextStyle&&this.$el.removeClass(this.valueToTextClassName(this.currentTextStyle)),e&&this.$el.addClass(this.valueToTextClassName(e)),this.currentTextStyle=e},updateBackground:function(){var e=this.model.get("background");this.currentBackground&&this.$el.removeClass(this.valueToBackgroundClassName(this.currentBackground)),e&&this.$el.addClass(this.valueToBackgroundClassName(e)),this.currentBackground=e},updateForeground:function(){var e=this.model.get("foreground");this.currentForeground&&this.$el.removeClass(this.valueToForegroundClassName(this.currentForeground)),e&&this.$el.addClass(this.valueToForegroundClassName(e)),this.currentForeground=e},updateStyle:function(){var e=this.model.get("style");this.currentStyle&&this.$el.removeClass(this.currentStyle),e&&this.$el.addClass(e),this.currentStyle=e},updateViewMode:function(){"FormGroup"==this.viewMode&&this.$el.addClass("pl-form-group")},updateValidationState:function(){var e=this.model.get("validationState"),t=this.model.get("validationMessage");switch(e){case"success":this.$el.removeClass("has-warning has-error"),this.hideErrorMessage();break;case"warning":this.$el.removeClass("has-error").addClass("has-warning"),this.showErrorMessage(t);break;case"error":this.$el.removeClass("has-warning").addClass("has-error"),this.showErrorMessage(t)}},showErrorMessage:function(e){var t=$(_.template('')({message:e}));this.hideErrorMessage(),this.$el.find(".form-control:first").before(t),t.tooltip({container:"body"})},hideErrorMessage:function(){this.$el.find(".error-icn").remove()},rerender:function(){this.wasRendered&&this.render()},prerenderingActions:function(){this.wasRendered=!0},postrenderingActions:function(e){this.delegateEvents(),e=void 0===e||e,e&&this.trigger("onLoaded")},remove:function(){this.trigger(messageTypes.onRemove.name),Backbone.View.prototype.remove.apply(this,Array.prototype.slice.call(arguments))},switchClass:function(e,t,n,i){"undefined"==typeof i?i="-":i===!1&&(i="");var o=e+i,r=new RegExp("(^|\\s)"+o+"\\S+","ig"),a=n||this.$el;a.removeClass(function(e,t){return(t.match(r)||[]).join(" ")}).addClass(o+t)},valueToBackgroundClassName:function(e){return"pl-"+e.toLowerCase()+"-bg"},valueToForegroundClassName:function(e){return"pl-"+e.toLowerCase()+"-fg"},valueToTextClassName:function(e){return"pl-"+e.toLowerCase()},renderTemplate:function(e){var t=this.getData();this.$el.html(e(t)),this.bindUIElements()},getData:function(){var e=this.model;return{name:e.get("name"),text:e.get("text"),focusable:e.get("focusable"),focused:e.get("focused"),enabled:e.get("enabled"),visible:e.get("visible"),horizontalAlignment:e.get("horizontalAlignment"),verticalAlignment:e.get("verticalAlignment"),textHorizontalAlignment:e.get("textHorizontalAlignment"),textVerticalAlignment:e.get("textVerticalAlignment"),textStyle:e.get("textStyle"),foreground:e.get("foreground"),background:e.get("background")}},setFocus:function(){this.$el.focus()}});_.extend(ControlView.prototype,bindUIElementsMixin,eventHandlerMixin),InfinniUI.ControlView=ControlView;var buttonControlMixin={click:function(){this.controlView.$el.click()}};_.inherit(ContainerControl,Control),_.extend(ContainerControl.prototype,{});var ContainerModel=ControlModel.extend({defaults:_.defaults({itemTemplate:null},ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments)),this.set("items",new Collection)}}),ContainerView=ControlView.extend({initialize:function(e){ControlView.prototype.initialize.call(this,e),this.childElements=[],this.listenTo(this.model,"change:groupValueSelector",this.updateGrouping),this.updateGrouping()},updateGrouping:function(){throw"ContainerView.updateGrouping В потомке ContainerView не реализовано обновление группировок."},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this);var e=this;this.model.get("items").onChange(function(t){switch(t.action){case"replace":break;default:e.rerender()}})},removeChildElements:function(){for(var e=0,t=this.childElements.length;e0?t.deleteSelectedText(this.getCaretPosition(),this.getSelectionLength(),o):t.setCharAt(o,this.getCaretPosition(),this.getSelectionLength()),this.model.setText(t.getText()),n!==!1&&this.setCaretPosition(n)}}}},onKeyupHandler:function(e){this.trigger("onKeyDown",{keyCode:e.which,value:this.model.getValue()})},onClickHandler:function(e){this.checkCurrentPosition()},onPasteHandler:function(e){var t=e.originalEvent,n=t.clipboardData.getData("text/plain"),i=this.model.getEditMask();i&&(e.preventDefault(),this.textTyping(n))},OnDragstartHandler:function(e){var t=e.originalEvent;t.dataTransfer.effectAllowed="copy",this.$el.attr("data-dragged",!0)},OnDragendHandler:function(){this.$el.removeAttr("data-dragged",!1)},OnDragoverHandler:function(e){e.preventDefault()},OnDragenterHandler:function(e){var t=this.$el.attr("data-dragged");!t&&this.getCanChange()&&this.model.setEditMode()},OnDragleaveHandler:function(e){var t=this.$el.attr("data-dragged");t||this.model.setDisplayMode()},onDropHandler:function(e){e.preventDefault(),e.stopPropagation();var t=this.$el.attr("data-dragged");if(!t&&this.getCanChange()){var n=e.originalEvent,i=n.dataTransfer.getData("text/plain");this.textTyping(i,0),this.$el.focus()}},getCanChange:function(){var e=this.$el.prop("disabled");return e===!1},textTyping:function(e,t){var n=this.model.getEditMask(),i=e;n&&(e.split("").reduce(function(e,t){return n.setCharAt(t,e)},_.isNumber(t)?t:this.getCaretPosition()),i=n.getText()),this.model.setText(i)},checkCurrentPosition:function(e){if(this.canCaretPosition()){var t=this.model.getEditMask();if(t){"undefined"==typeof e&&(e=this.getCaretPosition());var n=0===e?t.moveToPrevChar(0):t.moveToNextChar(e-1);n!==e&&this.setCaretPosition(n)}}},getSelectionLength:function(){var e=this.el,t=0;if(this.canCaretPosition()){var n=parseInt(e.selectionStart,10),i=parseInt(e.selectionEnd,10);isNaN(n)||isNaN(i)||(t=i-n)}return t},canCaretPosition:function(){return/text|password|search|tel|url/.test(this.el.type)},setCaretPosition:function(e){if(_.isNumber(e)&&this.canCaretPosition()){var t=this.el;"undefined"!=typeof t.selectionStart&&t.setSelectionRange(e,e)}},getCaretPosition:function(){var e=this.el,t=0;return this.canCaretPosition()&&(t=e.selectionStart),t},initialize:function(){this.applyAutocomplete(),this.listenTo(this.model,"change:mode",this.onChangeModeHandler),this.listenTo(this.model,"change:text",this.onChangeTextHandler),this.listenTo(this.model,"invalid",this.onInvalidHandler)},applyAutocomplete:function(){var e=this.model.getEditMask();e&&this.$el.attr("autocomplete","off")},onInvalidHandler:function(e,t){this.$el.toggleClass(this.classNameError,!0)},onFocusinHandler:function(){this.model.setEditMode(),setTimeout(this.setCaretPosition.bind(this,0),4)},onFocusoutHandler:function(){this.model.setDisplayMode()},onChangeModeHandler:function(e,t){this.checkCurrentPosition()},onChangeTextHandler:function(e,t){var n=this.$el,i=this.getCaretPosition();n.toggleClass(this.classNameError,!1),n.val()!==t&&n.val(t);var o=this.model.getEditMask();o&&n.is(":focus")&&this.checkCurrentPosition(i)}});TextEditorModelBaseModeStrategy.prototype.updateText=function(e){},TextEditorModelBaseModeStrategy.prototype.setText=function(e,t,n){},TextEditorModelBaseModeStrategy.prototype.onChangeTextHandler=function(e,t,n){},TextEditorModelDisplayModeStrategy.prototype=Object.create(TextEditorModelBaseModeStrategy.prototype),TextEditorModelDisplayModeStrategy.prototype.constructor=TextEditorModelDisplayModeStrategy,TextEditorModelDisplayModeStrategy.prototype.updateText=function(e){var t,n=e.getDisplayFormat(),i=e.get("value");t=_.isFunction(n)?n.call(null,null,{value:i}):i,e.set("text",t)},TextEditorModelDisplayModeStrategy.prototype.setText=function(e,t,n){n&&e.set("text",t,{ui:n})},TextEditorModelDisplayModeStrategy.prototype.onChangeTextHandler=function(e,t,n){if(n.ui){var i=e.convertValue(t);e.set("value",i,{ui:n.ui})}e.applyChanges()},TextEditorModelEditModeStrategy.prototype=Object.create(TextEditorModelBaseModeStrategy.prototype),TextEditorModelEditModeStrategy.prototype.constructor=TextEditorModelBaseModeStrategy,TextEditorModelEditModeStrategy.prototype.updateText=function(e){var t,n=e.getEditMask(),i=e.get("value");n?(n.reset(i),t=n.getText()):t=i,"undefined"==typeof t||null===t?e.set("text",""):e.set("text",t.toString())},TextEditorModelEditModeStrategy.prototype.setText=function(e,t,n){e.set("text",t,{ui:n})},TextEditorModelEditModeStrategy.prototype.onChangeTextHandler=function(e,t,n){var i=e.getEditMask(),o=i?i.getData():t;e.set("value",e.convertValue(o),{silent:!!i,ui:n.ui})},_.inherit(TextBoxControl,TextEditorBaseControl),_.extend(TextBoxControl.prototype,{createControlModel:function(){return new TextBoxModel},createControlView:function(e){return new TextBoxView({model:e})}});var TextBoxModel=TextEditorBaseModel.extend({defaults:_.extend({},TextEditorBaseModel.prototype.defaults,{multiline:!1,inputType:"text"}),initialize:function(){TextEditorBaseModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),TextBoxView=TextEditorBaseView.extend({template:{oneline:InfinniUI.Template["controls/textBox/template/oneline.tpl.html"],multiline:InfinniUI.Template["controls/textBox/template/multiline.tpl.html"]},className:"pl-textbox form-group",UI:_.extend({},TextEditorBaseView.prototype.UI),events:_.extend({},TextEditorBaseView.prototype.events,{}),initHandlersForProperties:function(){TextEditorBaseView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:multiline",this.updateMultiline),this.listenTo(this.model,"change:lineCount",this.updateLineCount)},updateProperties:function(){TextEditorBaseView.prototype.updateProperties.call(this),this.updateLineCount()},updateMultiline:function(){this.rerender()},updateLineCount:function(){var e=this.model.get("lineCount");this.ui.editor.attr("rows",e)},render:function(){this.prerenderingActions();var e=this.model,t=e.get("multiline")?this.template.multiline:this.template.oneline;return this.renderTemplate(t),this.renderTextBoxEditor(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},getData:function(){var e=TextEditorBaseView.prototype.getData.call(this),t=this.model;return _.extend(e,{multiline:t.get("multiline"),lineCount:t.get("lineCount")})},renderTextBoxEditor:function(){this.renderControlEditor()}}),dateTimePickerModeDate={getTemplate:function(){return InfinniUI.Template["controls/dateTimePicker/template/date.tpl.html"]},onClickDropdownHandler:function(e){var t=this.model,n=new SelectDate({model:t});n.render(),$("body").append(n.$el),n.updatePosition(this.el),this.listenTo(n,"date",function(e){t.set("value",this.convertValue(e))})},convertValue:function(e){return InfinniUI.DateUtils.toISO8601(e,{timezoneOffset:this.model.get("timeZone")})}},dateTimePickerModeDateTime={getTemplate:function(){return InfinniUI.Template["controls/dateTimePicker/template/dateTime.tpl.html"]},onClickDropdownHandler:function(e){var t=this.model,n=new SelectDateTime({model:t});n.render(),$("body").append(n.$el),n.updatePosition(this.el),this.listenTo(n,"date",function(e){t.set("value",this.convertValue(e))})},convertValue:function(e){return InfinniUI.DateUtils.toISO8601(e,{timezoneOffset:this.model.get("timeZone")})}},dateTimePickerModeTime={getTemplate:function(){return InfinniUI.Template["controls/dateTimePicker/template/time.tpl.html"]},onClickDropdownHandler:function(e){var t=this.model,n=new SelectTime({model:t});n.render(),$("body").append(n.$el),n.updatePosition(this.el),this.listenTo(n,"date",function(e){t.set("value",this.convertValue(e))})},convertValue:function(e){return InfinniUI.DateUtils.toISO8601(e,{timezoneOffset:this.model.get("timeZone")})}},SelectComponent=Backbone.View.extend({modelClass:Backbone.Model,initialize:function(e){var t=this.modelClass;return this.model=new t({today:e.today||new Date,value:e.value,date:e.value||e.today,max:e.max,min:e.min}),this.render(),this},show:function(){this.$el.css("display","block")},hide:function(){this.$el.css("display","none")},setDate:function(e){this.model.setDate(e)}});_.extend(SelectComponent.prototype,bindUIElementsMixin);var SelectComponentModel=Backbone.Model.extend({defaults:function(){var e=new Date;return{today:e,todayMonth:e.getMonth(),todayDay:e.getDate(),todayYear:e.getFullYear(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}},initialize:function(){this.updateDateParts(),this.on("change:date",this.onChangeDateHandler,this)},updateDateParts:function(){var e=this.get("date");e instanceof Date?this.set({year:e.getFullYear(),month:e.getMonth(),day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}):this.set({year:null,month:null,day:null,hour:null,minute:null,second:null,millisecond:null})},onChangeDateHandler:function(e,t){"undefined"!=typeof t&&null!==t?e.set({year:moment(t).year(),month:moment(t).month(),day:moment(t).date(),hour:moment(t).hour(),minute:moment(t).minute(),second:moment(t).second(),millisecond:moment(t).millisecond()}):e.set({year:null,month:null,day:null,hour:null,minute:null,second:null,millisecond:null})},updateDatePart:function(e,t,n){var i=this.get("date"),o=InfinniUI.DateUtils.createDate(i)||this.get("today"),r=this.toJSON();switch(e){case"hour":case"minute":case"second":o.setHours(r.hour,r.minute,r.second);break;case"year":case"month":case"day":o.setFullYear(r.year,r.month,r.day)}this.set("date",o)},checkRange:function(e,t){var n=this.get("min"),i=this.get("max");return InfinniUI.DateUtils.checkRangeDate(e,n,i,t)},keepDateInRange:function(){if(!this.isValid()){var e=InfinniUI.DateUtils.getNearestDate(this.get("date"),this.get("min"),this.get("max"));this.set("date",e)}},setDate:function(e){if("undefined"==typeof e||null===e){var t=this.get("value"),n=this.get("date");e=t||n}e instanceof Date&&(e=new Date(e.getTime())),this.set("date",e)}}),SelectDaysModel=SelectComponentModel.extend({initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:year",this.updateDatePart.bind(this,"year")),this.on("change:month",this.updateDatePart.bind(this,"month")),this.on("change:day",this.updateDatePart.bind(this,"day"))},today:function(){this.set({year:this.get("todayYear"),month:this.get("todayMonth")})},nextMonth:function(){var e=this.get("month"),t=this.get("year");this.set({month:11===e?0:e+1,year:11===e?t+1:t}),this.keepDateInRange()},prevMonth:function(){var e=this.get("month"),t=this.get("year");this.set({month:0===e?11:e-1,year:0===e?t-1:t}),this.keepDateInRange()}}),SelectDays=SelectComponent.extend({modelClass:SelectDaysModel,template:InfinniUI.Template["controls/dateTimePicker/template/date/days.tpl.html"],UI:{headerDays:".weekdays-head .day",calendarDays:".day-calendar",year:".years-year",month:".years-month"},events:{"click .years":"onYearsClickHandler","click .btn-month-prev":"prevMonth","click .btn-month-next":"nextMonth","click .today-date":"showToday",'click .day-calendar:not(".day-unavailable")':"useDay","click .time":"showTime"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.fillLegend(),this.fillCalendar(),this.renderMonth(),this.renderYear(),this.initOnChangeHandlers()},initOnChangeHandlers:function(){this.listenTo(this.model,"change:month",this.onChangeMonthHandler),this.listenTo(this.model,"change:year",this.onChangeYearHandler),this.listenTo(this.model,"change:day",this.onChangeDayHandler)},renderMonth:function(){var e=this.model.get("month"),t=localized.dateTimeFormatInfo;this.ui.month.text(t.monthNames[e])},renderYear:function(){var e=this.model.get("year");this.ui.year.text(e)},onChangeMonthHandler:function(e,t){this.renderMonth(),this.fillCalendar()},onChangeYearHandler:function(e,t){this.renderYear(),this.fillCalendar()},fillLegend:function(){function e(e,t){e.toggleClass("day-weekend",0===t||6===t)}var t=localized.dateTimeFormatInfo,n=t.firstDayOfWeek,i=t.abbreviatedDayNames.map(function(e,t){return t});n>0&&(i=i.splice(n).concat(i)),this.ui.headerDays.each(function(n,o){var r=$(o),a=i[n];r.text(t.abbreviatedDayNames[a]),e(r,a)}),this.ui.calendarDays.each(function(t,n){var o=$(n),r=i[t%7];e(o,r)})},fillCalendar:function(){function e(e,t){e.toggleClass("day-inactive",!t)}function t(e,t){var n=t.getMonth()===o.get("todayMonth")&&t.getFullYear()===o.get("todayYear")&&t.getDate()===o.get("todayDay");e.toggleClass("day-today",n)}function n(e,t){var n=!1;r&&(n=moment(r).isSame(t,"day")),e.toggleClass("day-selected",n)}function i(e,t){e.toggleClass("day-unavailable",!o.checkRange(t,"day"))}var o=this.model,r=o.get("value"),a=o.get("month"),l=o.get("year"),s=(o.get("day"),o.get("min"),o.get("max"),new Date(l,a)),u=s.getDay(),d=localized.dateTimeFormatInfo,c=d.firstDayOfWeek,p=[0,1,2,3,4,5,6];Array.prototype.push.apply(p,p.splice(0,c));var h=new Date(l,a,1-p.indexOf(u)),m=h.getFullYear(),f=h.getMonth(),g=h.getDate();this.ui.calendarDays.each(function(o,r){var l=$(r),s=new Date(m,f,g+o);l.text(s.getDate()),l.attr("data-date",s),e(l,s.getMonth()===a),t(l,s),n(l,s),i(l,s)})},onYearsClickHandler:function(e){var t=this.model.get("date");this.trigger("year",t)},prevMonth:function(){this.model.prevMonth()},nextMonth:function(){this.model.nextMonth()},showToday:function(){this.today()},today:function(){this.model.today()},showTime:function(){this.trigger("time",this.model.get("date"))},useDay:function(e){var t=$(e.target),n=new Date(t.attr("data-date"));this.model.set({year:n.getFullYear(),month:n.getMonth(),day:n.getDate()}),this.trigger("date",this.model.get("date"))}}),SelectHoursModel=SelectComponentModel.extend({initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:hour",this.updateDatePart.bind(this,"hour"))}}),SelectHours=SelectComponent.extend({modelClass:SelectHoursModel,template:InfinniUI.Template["controls/dateTimePicker/template/time/hours.tpl.html"],events:{"click .hour:not('.hour-unavailable')":"useHour"},UI:{hour:".hour"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.fillHoursTable(),this.initOnChangeHandlers()},fillHoursTable:function(){function e(e,t){e.toggleClass("hour-selected",o.getHours()===t)}function t(e,t){var n=moment(r).isSame(t,"hour");e.toggleClass("hour-today",n)}function n(e,t){var n=moment(i.get("date")).hour(t);e.toggleClass("hour-unavailable",!i.checkRange(n,"hour"))}var i=this.model,o=i.get("date")||i.get("today"),r=new Date;this.ui.hour.each(function(i,o){var r=$(o),a=stringUtils.padLeft(i,2,"0");r.attr("data-hour",i),r.text(a),t(r,i),e(r,i),n(r,i)})},initOnChangeHandlers:function(){this.listenTo(this.model,"change:date",this.fillHoursTable)},useHour:function(e){var t=$(e.target),n=this.model,i=n.get("date"),o=parseInt(t.attr("data-hour"),10),r=InfinniUI.DateUtils.cloneDate(i);r.setHours(o),n.set("date",r),this.trigger("hour",r)}}),SelectMinutesModel=SelectComponentModel.extend({initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:minute",this.updateDatePart.bind(this,"minute"))}}),SelectMinutes=SelectComponent.extend({modelClass:SelectMinutesModel,template:InfinniUI.Template["controls/dateTimePicker/template/time/minutes.tpl.html"],events:{"click .minute:not('.minute-unavailable')":"useMinute"},UI:{minute:".minute"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.fillMinutesTable(),this.initOnChangeHandlers()},fillMinutesTable:function(){function e(e,t){e.toggleClass("minute-selected",t===i)}function t(e,t){var i=moment(n.get("date")).minute(t);e.toggleClass("minute-unavailable",!n.checkRange(i,"minute"))}var n=this.model,i=n.get("minute");this.ui.minute.each(function(n,i){var o=$(i),r=o.attr("data-minute");e(o,parseInt(r,10)),t(o,parseInt(r,10))})},initOnChangeHandlers:function(){this.listenTo(this.model,"change:date",this.fillMinutesTable)},useMinute:function(e){var t=$(e.target),n=this.model,i=n.get("date"),o=parseInt(t.attr("data-minute"),10),r=InfinniUI.DateUtils.cloneDate(i);r.setMinutes(o),this.trigger("minute",r)}}),SelectMonthsModel=SelectComponentModel.extend({initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:month",this.updateDatePart.bind(this,"month")),this.on("change:year",this.updateDatePart.bind(this,"year"))},nextYear:function(){var e=this.get("year");this.set("year",e+1),this.keepDateInRange()},prevYear:function(){var e=this.get("year");this.set("year",e-1),this.keepDateInRange()},today:function(){this.set({month:this.get("todayMonth"),year:this.get("todayYear")})}}),SelectMonths=SelectComponent.extend({modelClass:SelectMonthsModel,template:InfinniUI.Template["controls/dateTimePicker/template/date/months.tpl.html"],events:{"click .btn-year-prev":"prevYear","click .btn-year-next":"nextYear","click .month:not('.month-unavailable')":"useMonth","click .year":"selectYear","click .today-month":"showToday"},UI:{month:".month",year:".year"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.fillMonthsTable(),this.initOnChangeHandlers()},fillMonthsTable:function(){function e(e,t){var n=moment([i.get("year"),t]),o=i.get("today");e.toggleClass("month-today",moment(n).isSame(o,"month"))}function t(e,t){var n=moment([i.get("year"),t]),o=i.get("value");e.toggleClass("month-selected",moment(n).isSame(o,"month"))}function n(e,t){var n=moment([i.get("year"),t]);e.toggleClass("month-unavailable",!i.checkRange(n,"month"))}this.ui.year.text(this.model.get("year"));var i=this.model,o=localized.dateTimeFormatInfo;i.get("todayMonth"),i.get("month");this.ui.month.each(function(i,r){var a=$(r);a.text(o.abbreviatedMonthNames[i]),a.attr("data-month",i),e(a,i),t(a,i),n(a,i)})},initOnChangeHandlers:function(){this.listenTo(this.model,"change:year",this.fillMonthsTable)},prevYear:function(){this.model.prevYear()},nextYear:function(){this.model.nextYear()},useMonth:function(e){var t=$(e.target),n=this.model;n.set({year:parseInt(n.get("year"),10),month:parseInt(t.attr("data-month"),10)}),this.trigger("month",n.get("date"))},selectYear:function(){var e=this.model;this.trigger("year",e.get("data"))},showToday:function(){this.today()},today:function(){this.model.today()}}),SelectSecondsModel=SelectComponentModel.extend({initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:second",this.updateDatePart.bind(this,"second"))}}),SelectSeconds=SelectComponent.extend({modelClass:SelectSecondsModel,template:InfinniUI.Template["controls/dateTimePicker/template/time/seconds.tpl.html"],events:{"click .second:not('.second-unavailable')":"useSecond"},UI:{second:".second"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.fillSecondsTable(),this.initOnChangeHandlers()},fillSecondsTable:function(){function e(e,t){e.toggleClass("second-selected",t===i)}function t(e,t){var i=moment(n.get("date")).seconds(t);e.toggleClass("second-unavailable",!n.checkRange(i))}var n=this.model,i=n.get("second");this.ui.second.each(function(n,i){var o=$(i),r=o.attr("data-second");e(o,parseInt(r,10)),t(o,parseInt(r,10))})},initOnChangeHandlers:function(){this.listenTo(this.model,"change:date",this.fillSecondsTable)},useSecond:function(e){var t=$(e.target),n=this.model,i=n.get("date"),o=parseInt(t.attr("data-second"),10),r=InfinniUI.DateUtils.cloneDate(i);r.setSeconds(o),this.trigger("second",r)}}),SelectTimesModel=SelectComponentModel.extend({initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:hour",this.updateDatePart.bind(this,"hour")),this.on("change:minute",this.updateDatePart.bind(this,"minute")),this.on("change:second",this.updateDatePart.bind(this,"second")),this.on("change:millisecond",this.updateDatePart.bind(this,"millisecond"))},nextHour:function(){var e=this.get("hour");e+=1,e>23||(this.set("hour",e),this.keepDateInRange())},prevHour:function(){var e=this.get("hour");e-=1,e<0||(this.set("hour",e),this.keepDateInRange())},nextMinute:function(){var e=this.get("minute");e+=1,e>=60||(this.set("minute",e),this.keepDateInRange())},prevMinute:function(){var e=this.get("minute");e-=1,e<0||(this.set("minute",e),this.keepDateInRange())},nextSecond:function(){var e=this.get("second");e+=1,e>=60||(this.set("second",e),this.keepDateInRange())},prevSecond:function(){var e=this.get("second");e-=1,e<0||(this.set("second",e),this.keepDateInRange())},validate:function(e,t){var n=InfinniUI.DateUtils.cloneDate(e.date);if(n.setHours(e.hour,e.minute,e.second,e.millisecond),!this.checkRange(n))return"Out of range"}}),SelectTimes=SelectComponent.extend({modelClass:SelectTimesModel,template:InfinniUI.Template["controls/dateTimePicker/template/time/time.tpl.html"],events:{"click .time-spin-down.time-spin-hour":"prevHour","click .time-spin-up.time-spin-hour":"nextHour","click .time-spin-down.time-spin-minute":"prevMinute","click .time-spin-up.time-spin-minute":"nextMinute","click .time-spin-down.time-spin-second":"prevSecond","click .time-spin-up.time-spin-second":"nextSecond","click .time-segment-hour":"selectHour","click .time-segment-minute":"selectMinute","click .time-segment-second":"selectSecond","click .days":"selectDay"},UI:{month:".month",year:".year",hour:".time-segment-hour",minute:".time-segment-minute",second:".time-segment-second"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.updateHour(),this.updateMinute(),this.updateSecond(),this.initOnChangeHandlers()},selectHour:function(){var e=this.model,t=e.get("date"),n=e.get("hour"),i=e.get("minute"),o=e.get("second");t.setHours(n,i,o),this.trigger("hour",t)},selectMinute:function(){var e=this.model,t=e.get("date"),n=e.get("hour"),i=e.get("minute"),o=e.get("second");t.setHours(n,i,o),this.trigger("minute",t)},selectSecond:function(){var e=this.model,t=e.get("date"),n=e.get("hour"),i=e.get("minute"),o=e.get("second");t.setHours(n,i,o),this.trigger("second",t)},initOnChangeHandlers:function(){this.listenTo(this.model,"change:hour",this.updateHour),this.listenTo(this.model,"change:minute",this.updateMinute),this.listenTo(this.model,"change:second",this.updateSecond),this.listenTo(this.model,"change:date",this.useTime)},updateHour:function(){var e=this.model.get("hour");this.ui.hour.text(stringUtils.padLeft(e,2,"0"))},updateMinute:function(){var e=this.model.get("minute");this.ui.minute.text(stringUtils.padLeft(e,2,"0"))},updateSecond:function(){var e=this.model.get("second");this.ui.second.text(stringUtils.padLeft(e,2,"0"))},prevHour:function(){this.model.prevHour()},nextHour:function(){this.model.nextHour()},prevMinute:function(){this.model.prevMinute()},nextMinute:function(){this.model.nextMinute()},prevSecond:function(){this.model.prevSecond()},nextSecond:function(){this.model.nextSecond()},useTime:function(){var e=this.model.get("date");this.trigger("date",e)},selectDay:function(){var e=this.model.get("date");this.trigger("day",e)}}),SelectYearsModel=SelectComponentModel.extend({defaults:function(){var e=SelectComponentModel.prototype.defaults.call(this);return _.defaults({pageSize:20,page:0},e)},initialize:function(){SelectComponentModel.prototype.initialize.call(this),this.on("change:year",this.updateDatePart.bind(this,"year")),this.on("change:year",this.onChangeYearHandler)},prevPage:function(){var e=this.get("page");this.set("page",e-1)},nextPage:function(){var e=this.get("page");this.set("page",e+1)},resetPage:function(){this.set("page",0)},onChangeYearHandler:function(e,t){this.keepDateInRange(),e.set("page",0)}}),SelectYears=SelectComponent.extend({modelClass:SelectYearsModel,template:InfinniUI.Template["controls/dateTimePicker/template/date/years.tpl.html"],events:{"click .btn-year-prev":"prevPage","click .btn-year-next":"nextPage","click .today-year":"showTodayYear",'click .year:not(".year-unavailable")':"useYear"},UI:{years:".year",yearBegin:".year-begin",yearEnd:".year-end"},initOnChangeHandlers:function(){this.listenTo(this.model,"change:page",this.fillYearsTable),this.listenTo(this.model,"change:year",this.fillYearsTable)},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.fillYearsTable(),this.initOnChangeHandlers()},fillYearsTable:function(){function e(e,t){e.toggleClass("year-today",t===l)}function t(e,t){e.toggleClass("year-selected",t===a)}function n(e,t){var n=moment([t]);e.toggleClass("year-unavailable",!i.checkRange(n,"year"))}var i=this.model,o=i.get("page"),r=i.get("pageSize"),a=i.get("year"),l=i.get("todayYear"),s=Math.ceil(a-r/2)+o*r;this.ui.years.each(function(i,o){var r=$(o),a=s+i;r.text(a),r.attr("data-year",a),e(r,a),t(r,a),n(r,a)}),this.ui.yearBegin.text(s),this.ui.yearEnd.text(s+r-1)},prevPage:function(){this.model.prevPage()},nextPage:function(){this.model.nextPage()},showTodayYear:function(){this.today()},today:function(){this.model.resetPage()},useYear:function(e){var t=$(e.target),n=this.model;n.set({year:parseInt(t.attr("data-year"),10)}),this.trigger("year",n.get("date"))}});window.InfinniUI.DateTimePickerControl=DateTimePickerControl,_.inherit(DateTimePickerControl,TextEditorBaseControl),_.extend(DateTimePickerControl.prototype,{createControlModel:function(){return new DateTimePickerModel},createControlView:function(e){return new DateTimePickerView({model:e})}});var DateTimePickerModel=TextEditorBaseModel.extend({defaults:_.extend({},TextEditorBaseModel.prototype.defaults,{mode:"Date"}),initialize:function(){TextEditorBaseModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments)),this.set("today",new Date),this.set("timeZone",InfinniUI.DateUtils.getDefaultTimeZone())},validate:function(e,t){e.minValue,e.maxValue;return InfinniUI.DateUtils.checkRangeDate(e.value,e.minValue,e.maxValue)}}),dateTimePickerStrategy=function(){return{Date:dateTimePickerModeDate,DateTime:dateTimePickerModeDateTime,Time:dateTimePickerModeTime}}(),DateTimePickerView=TextEditorBaseView.extend({className:"pl-datepicker form-group",template:InfinniUI.Template["controls/dateTimePicker/template/date.tpl.html"],UI:_.extend({},TextEditorBaseView.prototype.UI,{dropdownButton:".pl-datepicker-calendar",controlWrap:".control-wrap",editorWrap:".editor-wrap"}),events:_.extend({},TextEditorBaseView.prototype.events,{"click .pl-datepicker-calendar":"onClickDropdownHandler"}),initialize:function(){TextEditorBaseView.prototype.initialize.apply(this,Array.prototype.slice.call(arguments)),this.updateMode(),this.listenTo(this.model,"change:mode",this.updateMode)},initHandlersForProperties:function(){TextEditorBaseView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:minValue",this.updateMinValue),this.listenTo(this.model,"change:maxValue",this.updateMaxValue)},updateProperties:function(){TextEditorBaseView.prototype.updateProperties.call(this)},updateMode:function(){var e=this.model.get("mode");_.extend(this,dateTimePickerStrategy[e]),this.rerender()},updateMinValue:function(){var e=this.model.get("mode");_.extend(this,dateTimePickerStrategy[e]),this.rerender()},updateMaxValue:function(){var e=this.model.get("mode");_.extend(this,dateTimePickerStrategy[e]),this.rerender()},updateEnabled:function(){TextEditorBaseView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");this.ui.dropdownButton.prop("disabled",!e)},render:function(){return this.prerenderingActions(),this.renderTemplate(this.getTemplate()),this.updateProperties(),this.renderDateTimePickerEditor(),this.trigger("render"),this.postrenderingActions(),this},getData:function(){var e=this.model;return _.extend({},TextEditorBaseView.prototype.getData.call(this),{minValue:e.get("minValue"),maxValue:e.get("maxValue"),mode:e.get("mode")})},renderDateTimePickerEditor:function(){this.model;return this.renderControlEditor(),this},getTemplate:function(){throw new Error("Не перекрыт getTemplate")},onClickDropdownHandler:function(e){}}),SelectDate=Backbone.View.extend({className:"pl-datepicker-dropdown pl-dropdown-container",template:InfinniUI.Template["controls/dateTimePicker/template/select.date.tpl.html"],UI:{days:".days",months:".months",years:".years"},events:{"click .backdrop":"onClickBackdropHandler","click .datepicker-clear":"onClickClearValueHandler","click .today-date":"onClickTodayHandler"},render:function(){var e=this.template();this.$el.html(e),this.bindUIElements(),this.renderComponents()},renderComponents:function(){var e=this.model,t=InfinniUI.DateUtils.createDate(e.get("value")),n=InfinniUI.DateUtils.createDate(e.get("today")),i=e.get("timeZone"),o=moment(t);t=o.isValid()?o.toDate():null,t=InfinniUI.DateUtils.changeTimezoneOffset(t,i);var r={value:t,today:n||new Date,max:e.get("maxValue"),min:e.get("minValue")};r.el=this.ui.months;var a=new SelectMonths(r);r.el=this.ui.years;var l=new SelectYears(r);r.el=this.ui.days;var s=new SelectDays(r);this.months=a,this.years=l,this.days=s,this.workflow(s,a,l,t)(t)},onClickBackdropHandler:function(e){this.remove()},onClickClearValueHandler:function(){this.clearValue()},clearValue:function(){this.useValue(null)},useValue:function(e){var t=this.model,n=t.get("timeZone"),i=t.get("minValue"),o=t.get("maxValue");InfinniUI.DateUtils.checkRangeDate(e,i,o)||(e=InfinniUI.DateUtils.getNearestDate(e,i,o)),this.trigger("date",InfinniUI.DateUtils.restoreTimezoneOffset(e,n)),this.remove()},workflow:function(e,t,n){function i(i){e.setDate(i),n.hide(),t.hide(),e.show()}function o(i){t.setDate(i),e.hide(),n.hide(),t.show()}function r(i){n.setDate(i),e.hide(),t.hide(),n.show()}return this.listenTo(e,"date",this.useValue).listenTo(e,"year",function(e){r(e)}).listenTo(n,"year",function(e){o(e)}).listenTo(t,"year",function(e){r(e)}).listenTo(t,"month",function(e){i(e)}),i},onClickTodayHandler:function(){this.useValue(new Date)},updatePosition:function(e){var t=this.getDropdownDirection(e);this.setPositionFor(e,t)},setPositionFor:function(e,t){clearInterval(this._intervalId),this.applyStyle(e,t),this._intervalId=setInterval(this.applyStyle.bind(this,e,t),100)},remove:function(){return clearInterval(this._intervalId),Backbone.View.prototype.remove.apply(this,arguments)},getDropdownDirection:function(e){var t=$(window).height(),n=e.getBoundingClientRect(),i=this.$el.height(),o="bottom";return n.bottom+i+30>t&&n.bottom>t/2&&n.top>i&&(o="top"),o},applyStyle:function(e,t){var n=e.getBoundingClientRect(),i=this.el.getBoundingClientRect(),o={position:"absolute",left:window.pageXOffset+n.right-Math.round(i.width)};"bottom"===t?o.top=window.pageYOffset+n.bottom:o.top=window.pageYOffset+n.top-this.$el.height(),this.$el.css(o)}});_.extend(SelectDate.prototype,bindUIElementsMixin);var SelectDateTime=SelectDate.extend({className:"pl-datepicker-dropdown pl-dropdown-container",template:InfinniUI.Template["controls/dateTimePicker/template/select.dateTime.tpl.html"],UI:{days:".days",months:".months",years:".years",times:".times",hours:".hours",minutes:".minutes"},onClickToggleDateHandler:function(){this.trigger("days")},onClickToggleTimeHandler:function(){this.trigger("time")},renderComponents:function(){var e=this.model,t=InfinniUI.DateUtils.createDate(e.get("value")),n=InfinniUI.DateUtils.createDate(e.get("today")),i=e.get("timeZone"),o=moment(t);t=o.isValid()?o.toDate():null,t=InfinniUI.DateUtils.changeTimezoneOffset(t,i);var r={value:t,today:n||new Date,max:e.get("maxValue"),min:e.get("minValue")};r.el=this.ui.months;var a=new SelectMonths(r);r.el=this.ui.years;var l=new SelectYears(r);r.el=this.ui.days;var s=new SelectDays(r);r.el=this.ui.times;var u=new SelectTimes(r);r.el=this.ui.hours;var d=new SelectHours(r);r.el=this.ui.minutes;var c=new SelectMinutes(r);this.workflow(s,a,l,u,d,c)(t)},useTime:function(e){ +var t=this.model,n=t.get("timeZone"),i=t.get("minValue"),o=t.get("maxValue");return InfinniUI.DateUtils.checkRangeDate(e,i,o)||(e=InfinniUI.DateUtils.getNearestDate(e,i,o)),this.trigger("date",InfinniUI.DateUtils.restoreTimezoneOffset(e,n)),e},workflow:function(e,t,n,i,o,r){function a(e){m.forEach(function(t){t!==e&&t.hide()}),e.show()}function l(t){e.setDate(t),a(e)}function s(e){t.setDate(e),a(t)}function u(e){n.setDate(e),a(n)}function d(e){o.setDate(e),a(o)}function c(e){r.setDate(e),a(r)}function p(e){i.setDate(e),a(i)}var h=this.useTime.bind(this),m=Array.prototype.slice.call(arguments);return this.listenTo(e,"date",this.useValue).listenTo(e,"year",function(e){u(e)}).listenTo(e,"time",function(e){p(e)}).listenTo(n,"year",function(e){s(e)}).listenTo(t,"year",function(e){u(e)}).listenTo(t,"month",function(e){l(e)}),this.listenTo(i,"hour",function(e){d(e)}).listenTo(i,"minute",function(e){c(e)}).listenTo(i,"day",function(e){l(e)}).listenTo(i,"date",function(e){h(e)}).listenTo(o,"hour",function(e){var t=h(e);p(t)}).listenTo(r,"minute",function(e){var t=h(e);p(t)}),this.on("days",function(e){l(e)}).on("time",function(e){p(e)}),l}}),SelectTime=SelectDate.extend({className:"pl-timepicker-dropdown pl-dropdown-container",template:InfinniUI.Template["controls/dateTimePicker/template/select.time.tpl.html"],UI:{times:".times",hours:".hours",minutes:".minutes",seconds:".seconds"},renderComponents:function(){var e=this.model,t=InfinniUI.DateUtils.createDate(e.get("value")),n=InfinniUI.DateUtils.createDate(e.get("today")),i=e.get("timeZone"),o=moment(t);t=o.isValid()?o.toDate():null,t=InfinniUI.DateUtils.changeTimezoneOffset(t,i);var r={value:t,today:n,max:e.get("maxValue"),min:e.get("minValue")};r.el=this.ui.times;var a=new SelectTimes(r);r.el=this.ui.hours;var l=new SelectHours(r);r.el=this.ui.minutes;var s=new SelectMinutes(r);r.el=this.ui.seconds;var u=new SelectSeconds(r);this.workflow(a,l,s,u)(t)},useTime:function(e){var t=this.model,n=t.get("timeZone"),i=t.get("minValue"),o=t.get("maxValue");return InfinniUI.DateUtils.checkRangeDate(e,i,o)||(e=InfinniUI.DateUtils.getNearestDate(e,i,o)),this.trigger("date",InfinniUI.DateUtils.restoreTimezoneOffset(e,n)),e},workflow:function(e,t,n,i){function o(e){d.forEach(function(t){t!==e&&t.hide()}),e.show()}function r(e){t.setDate(e),o(t)}function a(e){n.setDate(e),o(n)}function l(e){i.setDate(e),o(i)}function s(t){e.setDate(t),o(e)}var u=this.useTime.bind(this),d=Array.prototype.slice.call(arguments);return this.listenTo(e,"hour",function(e){r(e)}).listenTo(e,"minute",function(e){a(e)}).listenTo(e,"second",function(e){l(e)}).listenTo(e,"date",function(e){u(e)}).listenTo(t,"hour",function(e){var t=u(e);s(t)}).listenTo(n,"minute",function(e){var t=u(e);s(t)}).listenTo(i,"second",function(e){var t=u(e);s(t)}),s}});_.inherit(DatePickerControl,DateTimePickerControl),_.extend(DatePickerControl.prototype,{createControlModel:function(){return new DatePickerModel},createControlView:function(e){return new DatePickerView({model:e})}});var DatePickerModel=DateTimePickerModel.extend({initialize:function(){DateTimePickerModel.prototype.initialize.apply(this,arguments)}}),DatePickerView=DateTimePickerView.extend({});console.assert(dateTimePickerModeDate,"dateTimePickerModeDate is undefined");var dateTimePickerModeDatePicker=_.extend({},dateTimePickerModeDate,{convertValue:function(e){var t=null;return e&&e.constructor===Date&&(t=InfinniUI.DateUtils.dateToTimestamp(e)),t}});dateTimePickerStrategy.DatePicker=dateTimePickerModeDatePicker,console.assert(dateTimePickerModeTime,"dateTimePickerModeTime is undefined");var dateTimePickerModeTimePicker=_.extend({},dateTimePickerModeTime,{convertValue:function(e){var t=null;return e&&e.constructor===Date&&(t=InfinniUI.DateUtils.dateToTimestampTime(e)),t}});dateTimePickerStrategy.TimePicker=dateTimePickerModeTimePicker,_.inherit(TimePickerControl,DateTimePickerControl),_.extend(TimePickerControl.prototype,{createControlModel:function(){return new TimePickerModel},createControlView:function(e){return new TimePickerView({model:e})}});var TimePickerModel=DateTimePickerModel.extend({initialize:function(){DateTimePickerModel.prototype.initialize.apply(this,arguments);var e=new Date;e.setFullYear(1970,0,1),this.set("today",e)}}),TimePickerView=DateTimePickerView.extend({className:"pl-datepicker pl-timepicker form-group"}),StatusBarControl=function(){_.superClass(StatusBarControl,this)};_.inherit(StatusBarControl,Control),_.extend(StatusBarControl.prototype,{createControlModel:function(){return new StatusBarModel},createControlView:function(e){return new StatusBarView({model:e})}});var StatusBarModel=ControlModel.extend({defaults:_.defaults({},ControlModel.prototype.defaults,{time:"",date:"",result:null})}),StatusBarView=ControlView.extend({className:"pl-status-bar",events:{"click .signIn":"signInHandler","click .signOut":"signOutHandler","click .status-bar-menu":"openMenuHandler"},template:InfinniUI.Template["controls/application/statusBar/template.tpl.html"],loginTemplate:InfinniUI.Template["controls/application/statusBar/authentication/loginTemplate.tpl.html"],enterTemplate:InfinniUI.Template["controls/application/statusBar/authentication/enterTemplate.tpl.html"],successTemplate:InfinniUI.Template["controls/application/statusBar/authentication/successTemplate.tpl.html"],initialize:function(){var e=this;e.model.set("time",moment().format("HH:mm")),e.model.set("date",moment().format("D MMMM")),window.setInterval(function(){e.model.set("time",moment().format("HH:mm")),e.model.set("date",moment().format("D MMMM")),e.dateRender()},1e4),getUserInfo(this),this.listenTo(this.model,"change:result",this.render)},dateRender:function(){this.$el.find(".time").text(this.model.get("time")),this.$el.find(".date").text(this.model.get("date"))},signInHandler:function(){var e=this;this.$modal||(this.$modal=$(this.loginTemplate({})),this.$modal.appendTo("body")),this.$modal.modal("show"),this.$modal.on("hidden.bs.modal",function(){$(this).find("#password, #userName").val(""),$(this).find("#remember").attr("checked",!1)}),this.$modal.find(".post").on("click",function(){signInInternal(e)})},openMenuHandler:function(){var e=$(".app-area").find(".pl-menu"),t=e.closest(".app-area");e.length&&t.length&&($(t).is(":visible")?t.css({display:"none"}):t.css({position:"absolute",width:"100%",display:"block",overflow:"hidden"}))},signOutHandler:function(){signOut(this)},render:function(){var e,t=this.model.get("result"),n=InfinniUI.config.configName,i=$(this.template({header:n})),o=this;return window.adjustLoginResult(t).then(function(n){e=t?$(o.successTemplate({displayName:n.UserName,activeRole:n.ActiveRole,roles:_.pluck(t.Roles,"DisplayName").join(", ")})):$(o.enterTemplate({})),i.find(".page-header-inner").prepend(e),o.$el.empty().append(i)}),this.$el.find(".calendar").datepicker({todayHighlight:!0,language:"ru"}),this.$el.find(".dropdown-toggle").on("click.bs.dropdown",function(){var e=$(this).data("clicks");e?$(this).parent(".dropdown").off("hide.bs.dropdown"):$(this).parent(".dropdown").on("hide.bs.dropdown",function(){return!1}),$(this).data("clicks",!e)}),this}});jQuery(document).ready(function(){InfinniUI.config.disableGetCurrentUser!==!1&&(InfinniUI.user={onReadyDeferred:$.Deferred(),onReady:function(e){this.onReadyDeferred.done(e)}},refreshUserInfo())}),jQuery(document).ready(function(){InfinniUI.config.disableSignInExternalForm!==!1&&getSignInExternalForm()}),_.extend(AuthenticationProvider.prototype,{handlers:{onActiveRoleChanged:$.Callbacks(),onSignInInternal:$.Callbacks(),onSignOut:$.Callbacks()},getCurrentUser:function(e,t){this.sendPostRequestForServiceResult("/Auth/GetCurrentUser",{},e,t)},changePassword:function(e,t,n,i){var o={OldPassword:e,NewPassword:t};this.sendPostRequestForServiceResult("/Auth/ChangePassword",o,n,i)},changeProfile:function(e,t,n,i){var o={DisplayName:e,Description:t};this.sendPostRequestForServiceResult("/Auth/ChangeProfile",o,n,i)},changeActiveRole:function(e,t,n){var i={ActiveRole:e};this.sendPostRequestForServiceResult("/Auth/ChangeActiveRole",i,function(){var n=_.toArray(arguments);n.push(e),t&&t.apply(this,n),this.handlers.onActiveRoleChanged.fire.apply(this.handlers.onActiveRoleChanged,n)},n)},signInInternal:function(e,t,n,i,o){var r={UserName:e,Password:t,Remember:n};this.sendPostRequestForServiceResult("/Auth/SignInInternal",r,i,o)},getSignInExternalForm:function(e,t,n,i){this.getExternalLoginForm("/Auth/SignInExternal",e,t,n,i)},getLinkExternalLoginForm:function(e,t,n,i){this.getExternalLoginForm("/Auth/LinkExternalLogin",e,t,n,i)},unlinkExternalLogin:function(e,t,n,i){var o={Provider:e,ProviderKey:t};this.sendPostRequest("/Auth/UnlinkExternalLogin",o,n,i)},signOut:function(e,t){this.sendPostRequestForServiceResult("/Auth/SignOut",null,function(){InfinniUI.user.onReadyDeferred=$.Deferred(),InfinniUI.user.onReadyDeferred.resolve(null);var t=_.toArray(arguments);e&&e.apply(this,t),this.handlers.onSignOut.fire.apply(this.handlers.onSignOut,t)}.bind(this),t)},getExternalLoginForm:function(e,t,n,i,o){var r=this.baseAddress+e;this.sendPostRequest("/Auth/GetExternalProviders",{},function(e){var o=$(document.createElement("form"));o.attr("method","POST"),o.attr("action",r);var a=$(document.createElement("input"));a.attr("type","hidden"),a.attr("name","SuccessUrl"),a.attr("value",t),o.append(a);var l=$(document.createElement("input"));if(l.attr("type","hidden"),l.attr("name","FailureUrl"),l.attr("value",n),o.append(l),null!==e&&void 0!==e)for(var s=0;s0},function(){"Right"==t?e.addClass("pull-right"):e.removeClass("pull-right")})}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.Button.menuItem",MenuItemButtonView),_.inherit(ButtonEditControl,TextBoxControl),_.extend(ButtonEditControl.prototype,{createControlModel:function(){return new ButtonEditModel},createControlView:function(e){return new ButtonEditView({model:e})},onButtonClick:function(e){this.controlView.on("buttonClick",e)}});var ButtonEditModel=TextBoxModel.extend({defaults:_.defaults({showClear:!0,readOnly:!0},TextBoxModel.prototype.defaults),initialize:function(){TextBoxModel.prototype.initialize.apply(this,arguments)},clearValue:function(){var e=this.get("enabled");e&&this.set("value",null)}}),ButtonEditView=TextBoxView.extend({template:{oneline:InfinniUI.Template["controls/buttonEdit/template/textBoxInput.tpl.html"],multiline:InfinniUI.Template["controls/buttonEdit/template/textBoxArea.tpl.html"]},className:"pl-button-edit form-group",UI:_.extend({},TextBoxView.prototype.UI,{iconAction:".pl-button-edit-button__icon_action",buttonClear:".pl-button-edit-button_clear",buttons:".pl-button-edit-button"}),events:_.extend({},TextBoxView.prototype.events,{"click .pl-button-edit-button_action":"onClickButtonHandler","click .pl-button-edit-button_clear":"onClickClearHandler"}),initHandlersForProperties:function(){TextBoxView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:icon",this.updateIcon),this.listenTo(this.model,"change:showClear",this.updateShowClear),this.listenTo(this.model,"change:readOnly",this.updateReadOnly)},updateProperties:function(){TextBoxView.prototype.updateProperties.call(this),this.updateIcon(),this.updateShowClear(),this.updateReadOnly()},updateIcon:function(){var e=this.model.get("icon");this.switchClass("fa",e,this.ui.iconAction)},updateShowClear:function(){var e=this.model.get("showClear"),t=this.model.get("value");this.ui.buttonClear.toggleClass("hidden",!e||_.isEmpty(t))},updateReadOnly:function(){var e=this.model.get("readOnly");this.ui.control.prop("readonly",e)},updateEnabled:function(){var e=this.model.get("enabled");TextBoxView.prototype.updateEnabled.call(this),this.ui.buttons.toggleClass("pl-button-edit-button_disabled",!e)},updateValue:function(){TextBoxView.prototype.updateValue.call(this),this.updateShowClear()},onClickButtonHandler:function(e){var t=this.model.get("enabled");t&&this.trigger("buttonClick",e)},onClickClearHandler:function(e){this.model.clearValue()}}),ComboBoxDropdownView=Backbone.View.extend({className:"pl-dropdown-container",events:{"click .backdrop":"onClickBackdropHandler","keyup .pl-combobox-filter-text":"onKeyUpHandler","keydown .pl-combobox-filter-text":"onFilterKeyDownHandler"},UI:{items:".pl-combobox-items",filter:".pl-combobox-filter",text:".pl-combobox-filter-text",noItems:".pl-combobox-items-empty",search:".pl-combobox-items-empty > span"},initialize:function(){var e=null!=this.model.get("groupValueSelector");e?this.strategy=new ComboBoxGroupViewStrategy(this):this.strategy=new ComboBoxPlainViewStrategy(this),this.listenTo(this.model,"change:dropdown",this.onChangeDropdownHandler),this.listenTo(this.model,"change:autocompleteValue",this.onChangeSearchHandler),this.listenTo(this.model,"change:autocomplete",this.updateAutocomplete),this.listenTo(this.model,"change:selectedItem",this.onChangeSelectedItem),this.listenTo(this.strategy,"click",this.onClickItemHandler),this.listenTo(this.strategy,"mouseenter",this.onMouseEnterItemHandler),this.model.onValueChanged(this.onChangeValueHandler.bind(this));var t=this.model.get("items"),n=this;t.onChange(function(){n.renderItems()})},updateProperties:function(){this.updateAutocomplete()},render:function(){var e=this.strategy.getTemplate();return this.$el.html(e({multiSelect:this.model.get("multiSelect")})),this.bindUIElements(),this.updateProperties(),this.renderItems(),this.$el},renderItems:function(){this.$el.hide();var e=this.strategy.renderItems();this.$items=e;var t=this.model.get("items"),n=t&&0==t.length;this.ui.noItems.toggleClass("hidden",!n),this.markSelectedItems(),this.markCheckedItems(),this.trigger("itemsRendered2"),this.$el.show()},setItemsContent:function(e){var t=this.ui.items;t.empty(),t.append(e)},close:function(){this.model.set("dropdown",!1)},setSearchFocus:function(){this.ui.text.focus()},onClickBackdropHandler:function(){this.close()},onChangeValueHandler:function(){this.markCheckedItems()},markSelectedItems:function(){var e=this.model;if(Array.isArray(this.$items)){var t=(this.ui.items,this.$items),n=e.getSelectedItem();t.forEach(function(e){var t=n===e.data("pl-data-item");e.toggleClass("pl-combobox-selected",t)}),this.ensureVisibleSelectedItem()}},ensureVisibleSelectedItem:function(){function e(e,t){var n,i=e.scrollTop(),o=t.position().top,r=t.outerHeight(),a=e.innerHeight();o+r>a?n=i+o+r-a:o<0&&(n=i+o),"undefined"!=typeof n&&e.scrollTop(n)}var t=this.model;if(Array.isArray(this.$items)){var n=this.ui.items,i=this.$items,o=t.getSelectedItem();i.some(function(t){var i=o===t.data("pl-data-item");return i&&e(n,t),i})}},markCheckedItems:function(){var e=this.model,t=e.getValue();if(Array.isArray(this.$items)){var n=this.$items,i=!!e.get("multiSelect"),o=[];o=i&&Array.isArray(t)?t.map(function(t){return e.itemByValue(t)}):[e.itemByValue(t)],n.forEach(function(e){var t=o.indexOf(e.data("pl-data-item"))!==-1;e.toggleClass("pl-combobox-checked",t)})}},onChangeDropdownHandler:function(e,t){t||this.remove()},updateAutocomplete:function(){var e=this.model.get("autocomplete");this.ui.filter.toggleClass("hidden",!e)},onMouseEnterItemHandler:function(e){this.model.setSelectedItem(e)},onClickItemHandler:function(e){var t=!this.model.isDisabledItem(e);t&&(this.model.toggleItem(e),this.close())},onKeyUpHandler:function(e){var t=this.ui.text.val();this.trigger("search",t)},onKeyDownHandler:function(e){this.model;e.preventDefault(),this.onFilterKeyDownHandler(e)},onFilterKeyDownHandler:function(e){var t=this.model;switch(e.which){case 36:t.selectFirstItem();break;case 35:t.selectLastItem();break;case 38:t.selectPrevItem();break;case 40:t.selectNextItem();break;case 13:this.onClickItemHandler(t.getSelectedItem());break;case 9:this.close();break;case 27:this.close(),e.stopPropagation()}},onChangeSearchHandler:function(e,t){this.ui.search.text(t)},onChangeSelectedItem:function(e,t){this.markSelectedItems()},updatePosition:function(e){var t=this.getDropdownDirection(e);this.setPositionFor(e,t)},setPositionFor:function(e,t){clearInterval(this._intervalId),this.applyStyle(e,t),this._intervalId=setInterval(this.applyStyle.bind(this,e,t),100)},remove:function(){return clearInterval(this._intervalId),Backbone.View.prototype.remove.apply(this,arguments)},getDropdownDirection:function(e){var t=$(window).height(),n=e.getBoundingClientRect(),i=this.$el.height(),o="bottom";return n.bottom+i+30>t&&n.bottom>t/2&&(o="top"),o},applyStyle:function(e,t){var n=e.getBoundingClientRect(),i={left:window.pageXOffset+n.left,width:Math.round(n.width)-1};"bottom"===t?i.top=window.pageYOffset+n.bottom:i.top=window.pageYOffset+n.top-this.$el.height(),this.$el.css(i)}});_.extend(ComboBoxDropdownView.prototype,bindUIElementsMixin),ComboBoxBaseViewStrategy.prototype.getModelAttribute=function(e){var t=this.dropdownView.model;return t.get(e)},ComboBoxBaseViewStrategy.prototype.isEnabledItem=function(e){return!this.dropdownView.model.isDisabledItem(e)},ComboBoxBaseViewStrategy.prototype.renderItems=function(){throw new Error("Method renderItems not implemented")},ComboBoxBaseViewStrategy.prototype.getTemplate=function(){},ComboBoxBaseViewStrategy.prototype._renderItems=function(e){var t,n=this.getModelAttribute("items"),i=this.getModelAttribute("itemTemplate");return t=e.map(function(e){var t=i(void 0,{value:e,index:n.indexOf(e)}),o=t.render();return"undefined"!=typeof e&&o.data("pl-data-item",e),this.addOnClickEventListener(o,e),this.addOnHoverEventListener(o,e),t.setEnabled(this.isEnabledItem(e)),o},this)},ComboBoxBaseViewStrategy.prototype.addOnClickEventListener=function(e){var t=e[0],n=Array.prototype.slice.call(arguments,1),i=this.trigger.bind(this,"click");t.addEventListener("click",function(){i.apply(this,n)})},ComboBoxBaseViewStrategy.prototype.addOnHoverEventListener=function(e){var t=(e[0],Array.prototype.slice.call(arguments,1)),n=this.trigger.bind(this,"mouseenter");e.on("mouseenter",function(){n.apply(this,t)})},_.extend(ComboBoxBaseViewStrategy.prototype,Backbone.Events),ComboBoxGroupViewStrategy.prototype=Object.create(ComboBoxBaseViewStrategy.prototype),ComboBoxGroupViewStrategy.prototype.constructor=ComboBoxGroupViewStrategy,ComboBoxGroupViewStrategy.prototype.template=InfinniUI.Template["controls/comboBox/dropdown/template/group/template.tpl.html"],ComboBoxGroupViewStrategy.prototype.renderItems=function(){var e,t=this.getModelAttribute("items"),n=this.getModelAttribute("groupValueSelector"),i={};return t.forEach(function(e,t){var o=n(void 0,{value:e,index:t});o in i||(i[o]=[]),i[o].push(e)}),e=this.renderGroups(i)},ComboBoxGroupViewStrategy.prototype.renderGroups=function(e){var t,n=this.getModelAttribute("groupItemTemplate"),i=this.getModelAttribute("items"),o=[],r=[];for(var a in e){var l=e[a],s=n(void 0,{index:i.indexOf(l[0]),item:l[0]}),t=this._renderItems(l),u=new ComboBoxGroupView({header:s.render(),items:t});Array.prototype.push.apply(o,t),r.push(u.render())}return this.dropdownView.setItemsContent(r),o},ComboBoxGroupViewStrategy.prototype.getTemplate=function(){return this.template},ComboBoxPlainViewStrategy.prototype=Object.create(ComboBoxBaseViewStrategy.prototype),ComboBoxPlainViewStrategy.prototype.constructor=ComboBoxPlainViewStrategy,ComboBoxPlainViewStrategy.prototype.renderItems=function(){var e=[],t=this.getModelAttribute("items");return t&&(e=this._renderItems(t.toArray())),this.dropdownView.setItemsContent(e),e},ComboBoxPlainViewStrategy.prototype.template=InfinniUI.Template["controls/comboBox/dropdown/template/plain/template.tpl.html"],ComboBoxPlainViewStrategy.prototype.getTemplate=function(){return this.template};var ComboBoxGroupView=Backbone.View.extend({template:InfinniUI.Template["controls/comboBox/dropdown/group/template/template.tpl.html"],UI:{header:".pl-combobox-group__header",items:".pl-combobox-group__items"},initialize:function(e){this.options={header:e.header,items:e.items}},render:function(){var e=this.options;return this.$el.html(this.template()),this.bindUIElements(),this.ui.header.append(e.header),this.ui.items.append(e.items),this.$el}});_.extend(ComboBoxGroupView.prototype,bindUIElementsMixin);var ComboBoxValueModel=Backbone.Model.extend({}),ComboBoxValue=Backbone.View.extend({template:InfinniUI.Template["controls/comboBox/values/template/value.tpl.html"],tagName:"li",className:"pl-combobox-value",events:{"click .pl-combobox-value-remove":"onClickRemoveHandler"},UI:{item:".pl-combobox-value-item"},initialize:function(e){this.model=new ComboBoxValueModel(e)},render:function(){this.$el.html(this.template()),this.bindUIElements();var e=this.model.get("$value");return this.ui.item.append(e),this.$el},onClickRemoveHandler:function(){var e=this.model.get("value");this.trigger("remove",e)}});_.extend(ComboBoxValue.prototype,bindUIElementsMixin);var ComboBoxValuesModel=Backbone.Model.extend({defaults:{enabled:!0},initialize:function(){this.items=[]}}),ComboBoxValues=Backbone.View.extend({tagName:"ul",className:"pl-combobox-values",template:InfinniUI.Template["controls/comboBox/values/template/values.tpl.html"],events:{"keypress .pl-combobox-search-text":"onKeyPressHandler","keydown .pl-combobox-search-text":"onKeyDownHandler","keyup .pl-combobox-search-text":"onKeyUpHandler",click:"onClickHandler"},UI:{search:".pl-combobox-search",text:".pl-combobox-search-text"},initialize:function(e){this.model=new ComboBoxValuesModel(e)},render:function(){this.$el.empty(),this.$el.html(this.template()),this.bindUIElements();var e=this.model,t=e.get("items").map(function(e){var t=new ComboBoxValue({$value:e.$value,value:e.value});return this.listenTo(t,"remove",this.onRemoveValueHandler),t.render()},this);return this.ui.search.before(t),this.$el},KeyCode:{enter:13,backspace:8,left:37,right:39,home:36,end:35,tab:9},setFocus:function(){this.ui.text.focus()},onKeyPressHandler:function(e){var t=e.which;t===this.KeyCode.enter,console.log("onKeyPressHandler",e.which,this.ui.text.val())},onKeyDownHandler:function(e){var t=e.which;t===this.KeyCode.left,console.log("onKeyDownHandler",e.which,this.ui.text.val())},onKeyUpHandler:function(e){var t=this.ui.text.val();this.trigger("search",t)},onRemoveValueHandler:function(e){this.trigger("remove",e)},onClickHandler:function(e){this.setFocus()}});_.extend(ComboBoxValues.prototype,bindUIElementsMixin),_.inherit(DataGridControl,ListEditorBaseControl),_.extend(DataGridControl.prototype,{createControlModel:function(){return new DataGridModel},createControlView:function(e){return new DataGridView({model:e})},onCheckAllChanged:function(e){this.controlModel.onCheckAllChanged(e)},setEnabled:function(e){this.controlModel.set("enabled",e)},onRowClick:function(e){this.controlView.$el.on("click","tbody .pl-datagrid-row",e)},onRowDoubleClick:function(e){this.controlView.$el.on("dblclick","tbody .pl-datagrid-row",e)}});var DataGridModel=ListEditorBaseModel.extend({defaults:_.defaults({showSelectors:!0,checkAllVisible:!1,checkAll:!1,focusable:!1,sortedColumn:null},ListEditorBaseModel.prototype.defaults),initialize:function(){ListEditorBaseModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments)),this.initColumns()},toggleCheckAll:function(){this.set("checkAll",!this.get("checkAll"))},onCheckAllChanged:function(e){this.on("change:checkAll",function(t,n){e.call(null,{value:n})})},initColumns:function(){this.set("columns",new Collection)}}),DataGridView=ListEditorBaseView.extend({template:{grid:InfinniUI.Template["controls/dataGrid/template/dataGrid.tpl.html"],gridStretched:InfinniUI.Template["controls/dataGrid/template/dataGridStretched.tpl.html"],headerCell:InfinniUI.Template["controls/dataGrid/template/headerCell.tpl.html"],sizeCell:InfinniUI.Template["controls/dataGrid/template/sizeCell.tpl.html"]},className:"pl-datagrid",events:_.extend({},ListEditorBaseView.prototype.events,{"click .pl-datagrid-toggle_all":"onClickCheckAllHandler","click thead .pl-datagrid-row__cell":"onClickToHeaderCellHandler"}),UI:_.defaults({body:".pl-datagrid__body",head:".pl-datagrid__head",headContainer:".pl-datagrid-container_head",header:".pl-datagrid-row_header",firstRows:".pl-datagrid-row_first",toggleCell:".pl-toggle-cell",checkAll:".pl-datagrid-toggle__button",items:"tbody"},ListEditorBaseView.prototype.UI),initialize:function(e){ListEditorBaseView.prototype.initialize.call(this,e),this.rowElements=new HashMap},initHandlersForProperties:function(){ListEditorBaseView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:showSelectors",this.updateShowSelectors),this.listenTo(this.model,"change:checkAllVisible",this.updateCheckAllVisible),this.listenTo(this.model,"change:checkAll",this.updateCheckAll);var e=this.rowElements;this.model;this.model.get("items").onChange(function(t){"replace"===t.action&&t.oldItems.forEach(function(n,i){e.add(t.newItems[i],e.get(n)),e.remove(n)})})},updateProperties:function(){ListEditorBaseView.prototype.updateProperties.call(this),this.updateShowSelectors(),this.updateCheckAllVisible(),this.updateCheckAll(),this.updateDisabledItem()},updateShowSelectors:function(){var e=this.model.get("showSelectors");this.$el.toggleClass("pl-datagrid_selectors_show",e),this.$el.toggleClass("pl-datagrid_selectors_hide",!e)},updateGrouping:function(){},updateVerticalAlignment:function(){ListEditorBaseView.prototype.updateVerticalAlignment.call(this),this.switchClass("verticalAlignment",this.model.get("verticalAlignment"),this.ui.body,!1)},updateCheckAll:function(){var e=this.model.get("checkAll");this.ui.checkAll.prop("checked",e)},getHorizontalScrollBarWidth:function(){if("undefined"==typeof DataGridView.scrollbarWidth){var e=document.createElement("div"),t=document.body;e.className="modal-scrollbar-measure";var n={position:"absolute",top:"-9999px",width:"50px",height:"50px",overflow:"scroll"};for(var i in n)e.style[i]=n[i];t.appendChild(e),DataGridView.scrollbarWidth=e.offsetWidth-e.clientWidth,t.removeChild(e)}return DataGridView.scrollbarWidth},updateCheckAllVisible:function(){var e=this.model.get("checkAllVisible");this.ui.checkAll.toggleClass("hidden",!e)},updateMultiSelect:function(){ListEditorBaseView.prototype.updateMultiSelect.call(this);var e=this.model.get("multiSelect");this.$el.toggleClass("pl-datagrid_select_multi",e===!0),this.$el.toggleClass("pl-datagrid_select_single",e!==!0)},updateValue:function(){var e=this.model,t=e.get("value"),n=[],i=e.get("items");e.get("multiSelect")||void 0===t||null===t||(t=[t]),Array.isArray(t)&&(n=t.map(function(t){return e.itemIndexByValue(t)}).filter(function(e){return e!==-1})),this.rowElements.forEach(function(e,t){var o=i.indexOf(t),r=n.indexOf(o)!==-1;e.toggle(r)})},updateSelectedItem:function(){var e=this.model,t=e.get("selectedItem");this.rowElements.forEach(function(e,n){e.setSelected(n===t)})},updateDisabledItem:function(){var e,t=this.model,n=t.get("disabledItemCondition");null!=n?this.rowElements.forEach(function(i,o){e=!n(void 0,{value:o}),i.getSelected()===o&&e===!1&&t.set("selectedItem",null),i.setEnabled(e)}):this.rowElements.forEach(function(e,t){e.setEnabled(!0)})},updateEnabled:function(){var e=this.model.get("enabled");e?this.updateDisabledItem():this.disableDataGridItems()},disableDataGridItems:function(){this.model.set("selectedItem",null),this.rowElements.forEach(function(e,t){e.setEnabled(!1)})},render:function(){var e=this;this.prerenderingActions();var t=this.model.get("verticalAlignment"),n="Stretch"===t?this.template.gridStretched:this.template.grid;return this.$el.html(n()),this.bindUIElements(),this.renderHeaders(),this.renderItems(),this.trigger("render"),this.applyColumnWidth(),this.syncBodyAndHead(),this.postrenderingActions(), +setTimeout(function(){e.updateProperties()},0),this},applyColumnWidth:function(){var e=this.model.get("columns"),t=!1;this.ui.firstRows.children().each(function(n,i){var o=n%(e.length+1);if(0!==o){var r=e.getByIndex(o-1),a=r&&r.getWidth();a&&($(i).css("width",a),t=!0)}}),this.$el.toggleClass("pl-datagrid_layout_fixed",t)},syncBodyAndHead:function(){var e=this.ui.head;e.css("padding-right",this.getHorizontalScrollBarWidth()+"px"),this.ui.body.off("scroll").on("scroll",this.onScrollBodyHandler.bind(this))},onScrollBodyHandler:function(){this.ui.headContainer.scrollLeft(this.ui.body.scrollLeft())},renderHeaders:function(){var e=this,t=this.model.get("columns"),n=[],i=this.template.sizeCell(),o=t.toArray().map(function(t){n.push(i);var o=$(''),r=t.getHeaderTemplate(),a=t.getHeader();o.data("pl-column",t),t.getSortable()&&(o.addClass("sortable"),t.getSortDirection()&&setTimeout(function(){e.setUpColumnSort(t,o,t.getSortDirection(),!1)},0));var l;return r?(l=r(null,{value:a}),o.append(l.render())):o.append(a),o});this.ui.header.append(o),this.ui.firstRows.append(n)},renderItems:function(){var e=this.model,t=e.get("valueSelector"),n=e.get("itemTemplate"),i=e.get("items"),o=this.ui.items,r=this;this.removeRowElements(),i.forEach(function(i,a){setTimeout(function(){var l=n(void 0,{index:a,item:i});l.onBeforeClick(function(){var t=e.get("items"),n=t.getByIndex(a),i=r.rowElements.get(n);i.getEnabled()!==!1&&e.set("selectedItem",n)}),l.onToggle(function(){var n=this.model.get("enabled"),i=e.get("items");n&&e.toggleValue(t(void 0,{value:i.getByIndex(a)}))}),r.addRowElement(i,l);var s=l.render();o.append(s)},0)},this)},updateFocusable:function(){var e=this.model.get("focusable");this.rowElements.values.forEach(function(t){e?t.control.controlView.$el.attr("tabindex",0):t.control.controlView.$el.removeAttr("tabindex")})},addRowElement:function(e,t){this.addChildElement(t),this.rowElements.add(e,t)},removeRowElements:function(){this.removeChildElements(),this.rowElements.clear()},onClickCheckAllHandler:function(){this.model.toggleCheckAll()},onClickToHeaderCellHandler:function(e){var t=$(e.currentTarget),n=t.data("pl-column");n&&n.isSortable()&&(null===n.getSortDirection()?(this.resetSort(),this.setUpColumnSort(n,t,"asc")):"asc"===n.getSortDirection()?(this.resetSort("asc"),this.setUpColumnSort(n,t,"desc")):"desc"===n.getSortDirection()&&(this.resetSort("desc"),this.setUpColumnSort(n,t,"asc")))},setUpColumnSort:function(e,t,n,i){e.setSortDirection(n),this.model.set("sortedColumn",e),e.getIsHeaderTemplateEmpty()?t.addClass("sorted sorted-"+n):t.addClass("sorted headerTemplate-sorted-"+n),i!==!1&&e.trigger("onSort",{sortDirection:n})},resetSort:function(e){if(e){var t=this.$el.find(".sorted");t.removeClass("headerTemplate-sorted-"+e+" sorted-"+e)}else{var t=this.$el.find(".sorted");t.removeClass("sorted headerTemplate-sorted-asc headerTemplate-sorted-desc sorted-asc sorted-desc");var n=this.model.get("sortedColumn");n&&n.setSortDirection(null)}}});_.inherit(DataGridRowControl,Control),_.extend(DataGridRowControl.prototype,{onToggle:function(e){this.controlView.on("toggle",e)},createControlModel:function(){return new DataGridRowModel},createControlView:function(e){return new DataGridRowView({model:e})}});var DataGridRowModel=ControlModel.extend({}),DataGridRowView=ControlView.extend({className:"pl-datagrid-row pl-datagrid-row_data",classNameSelected:"info",tagName:"tr",events:{},template:{singleSelect:InfinniUI.Template["controls/dataGrid/dataGridRow/template/singleSelect.tpl.html"],multiSelect:InfinniUI.Template["controls/dataGrid/dataGridRow/template/multiSelect.tpl.html"],dataCell:InfinniUI.Template["controls/dataGrid/dataGridRow/template/dataCell.tpl.html"]},UI:{toggleCell:".pl-datagrid-row__cell_toggle",toggle:".pl-datagrid-toggle",toggleControl:".pl-datagrid-toggle input"},initialize:function(){ControlView.prototype.initialize.call(this),this.on("render",function(){this.ui.toggleCell.on("click",this.onToggleHandler.bind(this))},this)},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:toggle",this.updateToggle),this.listenTo(this.model,"change:selected",this.updateSelected)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),this.updateToggle(),this.updateSelected(),this.updateShowSelectors()},updateVerticalAlignment:function(){},render:function(){this.prerenderingActions();var e=this.$el,t=this.model.get("multiSelect")?"multiSelect":"singleSelect",n=this.template[t];e.html(n()),this.bindUIElements();var i=this.model.get("cellElements");return Array.isArray(i)&&i.forEach(function(t,n){var i=$('');i.append(t.render()),e.append(i)}),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},updateShowSelectors:function(){var e=this.model.get("showSelectors");this.ui.toggleCell.toggleClass("hidden",!e)},updateToggle:function(){var e=this.model.get("toggle");this.ui.toggleControl.prop("checked",!!e)},updateSelected:function(){var e=this.model.get("selected");this.$el.toggleClass(this.classNameSelected,!!e)},updateEnabled:function(){ControlView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");this.ui.toggleControl.attr("disabled",e?null:"disabled")},onToggleHandler:function(e){this.trigger("toggle")}}),DataNavigationBaseButtonModel=Backbone.Model.extend({initialize:function(){this.on("change:parent",this.subscribeToParent,this)},subscribeToParent:function(){}}),DataNavigationBaseButton=Backbone.View.extend({tagName:"li",initialize:function(e){Backbone.View.prototype.initialize.call(this,e),this.once("render",function(){this.initHandlersForProperties()},this)},initHandlersForProperties:function(){},updateProperties:function(){},getData:function(){return this.model.toJSON()},setParent:function(e){this.model.set("parent",e),this.subscribeForParent(e)},render:function(){var e=this.template(this.getData());return this.$el.html(e),this.trigger("render"),this.updateProperties(),this},subscribeForParent:function(e){}}),DataNavigationNextButton=DataNavigationBaseButton.extend({template:InfinniUI.Template["controls/dataNavigation/buttons/template/next.tpl.html"],events:{click:"onClickHandler"},initialize:function(e){this.model=new DataNavigationBaseButtonModel,DataNavigationBaseButton.prototype.initialize.call(this,e)},onClickHandler:function(e){this.trigger("command","next")}}),DataNavigationPageButton=DataNavigationBaseButton.extend({template:InfinniUI.Template["controls/dataNavigation/buttons/template/page.tpl.html"],events:{click:"onClickHandler"},initialize:function(e){this.model=new DataNavigationPageButtonModel,DataNavigationBaseButton.prototype.initialize.call(this,e),this.model.set("pageNumber",e.pageNumber)},initHandlersForProperties:function(){DataNavigationBaseButton.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:isCurrent",this.updateIsCurrent)},updateProperties:function(){DataNavigationBaseButton.prototype.updateProperties.call(this),this.updateIsCurrent()},updateIsCurrent:function(){this.$el.toggleClass("active",this.model.get("isCurrent"))},onClickHandler:function(e){this.trigger("command","page",{pageNumber:this.model.get("pageNumber")})}}),DataNavigationPageButtonModel=DataNavigationBaseButtonModel.extend({defaults:{isCurrent:!1},subscribeToParent:function(){DataNavigationBaseButtonModel.prototype.subscribeToParent.call(this);var e=this.get("parent");this.listenTo(e.model,"change:pageNumber",function(){this.updateIsCurrent()}),this.updateIsCurrent()},updateIsCurrent:function(){var e=this.get("parent"),t=e.model.get("pageNumber")===this.get("pageNumber");this.set("isCurrent",t)}}),DataNavigationPrevButton=DataNavigationBaseButton.extend({template:InfinniUI.Template["controls/dataNavigation/buttons/template/prev.tpl.html"],events:{click:"onClickHandler"},initialize:function(e){this.model=new DataNavigationBaseButtonModel,DataNavigationBaseButton.prototype.initialize.call(this,e)},onClickHandler:function(e){this.trigger("command","prev")}});DataNavigationButtonFactory.prototype.buttons={prev:DataNavigationPrevButton,page:DataNavigationPageButton,next:DataNavigationNextButton},DataNavigationButtonFactory.prototype.createButton=function(e,t){var n=this.buttons[e];if("function"!=typeof n)return void console.error("Wrong button type: "+e);var i=new n(t);return i.setParent(this._dataNavigation),i},_.inherit(DataNavigationControl,Control),_.extend(DataNavigationControl.prototype,{createControlModel:function(){return new DataNavigationModel},createControlView:function(e){return new DataNavigationView({model:e})},onPageNumberChanged:function(e){this.controlModel.onPageNumberChanged(e)},onPageSizeChanged:function(e){this.controlModel.onPageSizeChanged(e)}});var DataNavigationModel=ControlModel.extend({defaults:_.defaults({pageNumber:0,pageStart:0,_buttonsCount:5,_buttonsTemplate:["prev","page","next"],pageCount:null,isDataReady:!1},ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.set("availablePageSizes",new Collection),this.on("change:pageNumber",this.updatePageStart,this),this.on("change:pageSize",this.updatePageSize,this)},updatePageStart:function(){var e=this.get("pageNumber"),t=this.get("pageStart"),n=this.get("_buttonsCount");e+1>=t+n?t+=Math.floor(n/2):e===t?t=Math.max(0,t-Math.floor(n/2)):e+10&&this.set("pageNumber",e-1)},onPageNumberChanged:function(e){this.on("change:pageNumber",function(t,n){e.call(null,{value:n})})},onPageSizeChanged:function(e){this.on("change:pageSize",function(t,n){e.call(null,{value:n})})}}),DataNavigationView=ControlView.extend({template:InfinniUI.Template["controls/dataNavigation/template/dataNavigation.tpl.html"],className:"pl-data-navigation",UI:{buttons:"ul",sizes:".pl-page-size"},initialize:function(e){ControlView.prototype.initialize.call(this,e),this._childViews=[],this.buttonsFactory=new DataNavigationButtonFactory(this),this._pageSizes=new DataNavigationPageSizes,this._pageSizes.setParent(this)},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:pageStart",this.updateButtons),this.listenTo(this.model,"change:pageCount",this.updateButtons),this.listenTo(this.model,"change:isDataReady",this.updateButtons)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),this.updateButtons()},render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.updateProperties(),this.trigger("render"),this.renderPageSizes(),this.postrenderingActions(),this},renderPageSizes:function(){this.ui.sizes.append(this._pageSizes.render().$el)},renderButtons:function(){var e,t,n=this.model.get("_buttonsTemplate"),i=this.model.get("_buttonsCount"),o=this.model.get("pageCount"),r=(this.model.get("pageNumber"),this.model.get("pageStart")),a=this.model.get("isDataReady");if(this._removeChildViews(),a){var l=this.buttonsFactory;this.model;e=n.reduce(function(e,t){if("page"===t)for(var n=0;n=o&&(t=r+i-o+1,0==o&&(t+=1),e.splice(e.length-t,100));var s=e.map(function(e){return this.listenTo(e,"command",this.onCommandHandler),this._appendChildView(e),e.render().$el},this);this.ui.buttons.append(s)}},updateButtons:function(){this.renderButtons()},onCommandHandler:function(e,t){switch(e){case"prev":this.model.prevPage();break;case"next":this.model.nextPage();break;case"page":this.model.set("pageNumber",t.pageNumber)}},_removeChildViews:function(){this._childViews.forEach(function(e){this.stopListening(e),e.remove()},this),this._childViews.length=0},_appendChildView:function(e){this._childViews.push(e)}}),DataNavigationPageSizes=Backbone.View.extend({className:"btn-group",template:InfinniUI.Template["controls/dataNavigation/pageSizes/template/pageSizes.tpl.html"],events:{"click button":"onClickButtonHandler"},setParent:function(e){this.model=e.model;var t=this.model.get("availablePageSizes");t.onChange(this.onAvailablePageSizesChanged.bind(this)),this.model.on("change:pageSize",this.renderButtons,this)},render:function(){return this.renderButtons(),this},renderButtons:function(){var e=this.model.get("availablePageSizes"),t=this.model.get("pageSize"),n=e.toArray().map(function(e){return this.template({size:e,active:t===e})},this);this.$el.html(n)},onAvailablePageSizesChanged:function(){this.renderButtons()},onClickButtonHandler:function(e){var t=$(e.target),n=parseInt(t.attr("data-size"),10);this.model.set("pageSize",n)}}),CommonLabelView=ControlView.extend(_.extend({},editorBaseViewMixin,{className:"pl-label",template:InfinniUI.Template["controls/label/commonView/template/label.tpl.html"],UI:_.extend({},editorBaseViewMixin.UI,{control:".label-control"}),initialize:function(){ControlView.prototype.initialize.apply(this)},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),editorBaseViewMixin.initHandlersForProperties.call(this),this.listenTo(this.model,"change:displayFormat",this.updateDisplayFormat),this.listenTo(this.model,"change:textWrapping",this.updateTextWrapping),this.listenTo(this.model,"change:textTrimming",this.updateTextTrimming)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),editorBaseViewMixin.updateProperties.call(this),this.updateDisplayFormat(),this.updateTextWrapping(),this.updateTextTrimming()},updateFocusable:function(){var e=this.model.get("focusable");e?this.ui.control.attr("tabindex",0):this.ui.control.removeAttr("tabindex")},updateValue:function(){var e=this.model.get("escapeHtml"),t=e?"text":"html",n=this.getLabelText(),i=this.getLabelElement();i[t](n);var o=String(n);i.attr("title",o.replace(/<\/?[^>]+>/g,""))},updateDisplayFormat:function(){this.updateValue()},updateTextWrapping:function(){var e=this.model.get("textWrapping");this.getLabelElement().toggleClass("pl-text-wrapping",e)},updateTextTrimming:function(){var e=this.model.get("textTrimming");this.getLabelElement().toggleClass("pl-text-trimming",e)},updateText:function(){this.updateValue()},getData:function(){return _.extend({},ControlView.prototype.getData.call(this),editorBaseViewMixin.getData.call(this),{text:this.getLabelText()})},render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},getLabelText:function(){var e,t=this.model,n=t.get("value"),i=t.get("displayFormat");return"undefined"!=typeof n&&null!==n?e="function"==typeof i?i(null,{value:n}):n:(e=this.model.get("text"),"undefined"!=typeof e&&null!=e||(e="")),e},getLabelElement:function(){return this.ui.control}}));InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.Label.common",CommonLabelView);var LabelControl=function(e){_.superClass(LabelControl,this,e),this.initialize_editorBaseControl()};_.inherit(LabelControl,Control),_.extend(LabelControl.prototype,{createControlModel:function(){return new LabelModel},createControlView:function(e,t){t&&t in window.InfinniUI.viewModes.Label||(t="simple");var n=window.InfinniUI.viewModes.Label[t];return new n({model:e})},getDisplayValue:function(){return this.controlView.getLabelText()}},editorBaseControlMixin);var LabelModel=ControlModel.extend(_.extend({defaults:_.defaults({horizontalTextAlignment:"Left",verticalAlignment:"Top",textWrapping:!0,textTrimming:!0,escapeHtml:!0,focusable:!1},ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.initialize_editorBaseModel()}},editorBaseModelMixin)),SimpleLabelView=CommonLabelView.extend({tagName:"span",template:function(){return""},UI:_.extend({},editorBaseViewMixin.UI,{}),updateFocusable:function(){var e=this.model.get("focusable");e?this.$el.attr("tabindex",0):this.$el.removeAttr("tabindex")},getLabelElement:function(){return this.$el}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.Label.simple",SimpleLabelView);var BaseListBoxView=ListEditorBaseView.extend({template:{plain:InfinniUI.Template["controls/listBox/baseView/template/listBox.tpl.html"],grouped:InfinniUI.Template["controls/listBox/baseView/template/listBoxGrouped.tpl.html"]},className:"pl-listbox",events:{"change .pl-listbox-input":"onChangeHandler"},UI:_.defaults({items:".pl-listbox-i",checkingInputs:".pl-listbox-input input"},ListEditorBaseView.prototype.UI),initialize:function(e){ListEditorBaseView.prototype.initialize.call(this,e)},updateGrouping:function(){var e=null!=this.model.get("groupValueSelector");e?this.strategy=new ListBoxViewGroupStrategy(this):this.strategy=new ListBoxViewPlainStrategy(this)},updateValue:function(){this.ui.items.removeClass("pl-listbox-i-chosen"),this.ui.checkingInputs.prop("checked",!1);var e,t,n=this.model.get("value");if(this.isMultiselect()||void 0===n||null===n||(n=[n]),$.isArray(n))for(var i=0,o=n.length;i0&&(n=i.valueByItem(t.data("pl-data-item"))),this.model.set("value",n)},updateDisabledItem:function(){var e=this.model,t=e.get("disabledItemCondition");this.ui.items.removeClass("pl-disabled-list-item"),this.ui.checkingInputs.attr("disabled",null),null!=t&&this.ui.items.each(function(e,n){var i=$(n),o=i.data("pl-data-item"),r=t(void 0,{value:o});r&&(i.hasClass("pl-listbox-i-selected")&&this.model.set("selectedItem",null),i.toggleClass("pl-disabled-list-item",!0),i.find("input").attr("disabled","disabled"),i.find("button").attr("disabled","disabled"))})},disableAll:function(){this.ui.items.addClass("pl-disabled-list-item")},_getElementByItem:function(e){var t=_.find(this.ui.items,function(t){return $(t).data("pl-data-item")==e});return $(t)}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.ListBox.base",BaseListBoxView),_.extend(ListBoxViewGroupStrategy.prototype,{prepareItemsForRendering:function(){var e=this.listbox.getItems(),t="listbox-"+guid(),n={isMultiselect:this.listbox.isMultiselect(),focusable:this.listbox.isFocusable(),inputName:t,groups:[]},i={},o=this.listbox.getGroupValueSelector();e.forEach(function(e,t){var n=o(void 0,{value:e});n in i||(i[n]=[]),i[n].push({index:t,item:e})});for(var r in i)n.groups.push({items:i[r]});return n},getTemplate:function(){return this.listbox.template.grouped},appendItemsContent:function(e){var t,n,i,o,r,a=this.listbox.$el,l=this.listbox.getItemTemplate(),s=this.listbox.getGroupItemTemplate(),u=e.groups,d=this.listbox;a.find(".pl-listbox-group-i").each(function(e,a){r=u[e],i=s(void 0,{index:r.items[0].index,item:r}),d.addChildElement(i),o=$(a),o.find(".pl-listbox-group-title").append(i.render()),o.find(".pl-listbox-body").each(function(e,i){t=r.items[e].item,n=l(void 0,{index:r.items[e].index,item:t}),d.addChildElement(n),$(i).append(n.render()),$(i).parent().data("pl-data-item",t)})})}}),_.extend(ListBoxViewPlainStrategy.prototype,{prepareItemsForRendering:function(){var e=this.listbox.getItems(),t="listbox-"+guid(),n={isMultiselect:this.listbox.isMultiselect(),focusable:this.listbox.isFocusable(),inputName:t,items:e.toArray()};return n},getTemplate:function(){return this.listbox.template.plain},appendItemsContent:function(e){var t,n,i=this.listbox.$el,o=this.listbox.getItemTemplate(),r=e.items,a=this.listbox;i.find(".pl-listbox-body").each(function(e,i){n=$(i),t=o(void 0,{index:e,item:r[e]}),a.addChildElement(t),n.append(t.render()),n.parent().data("pl-data-item",r[e])})}}),_.inherit(ListBoxControl,ListEditorBaseControl),_.extend(ListBoxControl.prototype,{createControlModel:function(){return new ListBoxModel},createControlView:function(e,t){(!t||!t in window.InfinniUI.viewModes.ListBox)&&(t="common");var n=window.InfinniUI.viewModes.ListBox[t];return new n({model:e})},updateDisabledItem:function(){this.controlView.updateDisabledItem()},disableAll:function(){this.controlView.disableAll()}});var ListBoxModel=ListEditorBaseModel.extend({initialize:function(){ListEditorBaseModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),CheckingListBoxView=BaseListBoxView.extend({className:"pl-listbox",template:{plain:InfinniUI.Template["controls/listBox/checkingView/template/listBox.tpl.html"],grouped:InfinniUI.Template["controls/listBox/checkingView/template/listBoxGrouped.tpl.html"]},events:_.extend({},BaseListBoxView.prototype.events),initialize:function(e){BaseListBoxView.prototype.initialize.call(this,e),this.initDomHandlers()},updateEnabled:function(){ListEditorBaseView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");this.ui.checkingInputs.attr("disabled",!e)},initDomHandlers:function(){var e=this.$el,t=this;e.get(0).addEventListener("click",function(n){n=$.event.fix(n);var i,o,r,a=$(n.target);if(t.model.get("enabled")){for(;a.get(0)!=e.get(0);)a.hasClass("pl-listbox-i")&&(i=a),a=a.parent();i&&i.length>0&&(o=i.data("pl-data-item"),r=t.model.isDisabledItem(o),r||t.model.toggleValue(o),t.model.set("selectedItem",o))}},!0)}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.ListBox.checking",CheckingListBoxView);var CommonListBoxView=BaseListBoxView.extend({className:"pl-listbox pl-listbox-common-mode",events:_.extend({},BaseListBoxView.prototype.events),initialize:function(e){BaseListBoxView.prototype.initialize.call(this,e),this.initDomHandlers()},initDomHandlers:function(){var e=this.$el,t=this;e.get(0).addEventListener("click",function(n){n=$.event.fix(n);for(var i,o,r,a=$(n.target);a.get(0)!=e.get(0);)a.hasClass("pl-listbox-i")&&(i=a),a=a.parent();i.length>0&&(o=i.data("pl-data-item"),r=t.model.isDisabledItem(o),r||t.model.toggleValue(o),t.model.set("selectedItem",o))},!0)}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.ListBox.common",CommonListBoxView);var CommonPopupButtonView=ContainerView.extend({className:"pl-popup-button",template:InfinniUI.Template["controls/popupButton/commonView/template/popupButton.tpl.html"],dropdownTemplate:InfinniUI.Template["controls/popupButton/commonView/template/popupButton.dropdown.tpl.html"],events:{click:"onClickHandler"},UI:{button:".pl-popup-button__button",grip:".pl-popup-button__grip"},updateProperties:function(){ContainerView.prototype.updateProperties.call(this),this.updateContent()},updateContent:CommonButtonView.prototype.updateContent,updateText:CommonButtonView.prototype.updateText,getButtonElement:function(){return this.ui.button},render:function(){this.prerenderingActions();var e=this.model.get("items").toArray(),t=this.template;return this.removeChildElements(),this.$el.html(t({items:e})),this.bindUIElements(),this.$dropdown=this.renderDropdown(),this.$dropdown.on("click",this.close.bind(this)),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderDropdown:function(){var e=this.dropdownTemplate,t=this.model.get("items").toArray(),n=$(e({items:t}));return this.appendItemsContent(n,t),n},appendItemsContent:function(e,t){var n,i,o=this,r=this.model.get("itemTemplate");e.find(".pl-popup-button__item").each(function(e,a){i=$(a),n=r(void 0,{index:e,item:t[e]}),o.addChildElement(n),i.append(n.render())})},open:function(){$("body").append(this.$dropdown),this.$dropdown.addClass("open"),this.alignDropdown();this.$dropdown.add(this.ui.grip)},close:function(){this.$dropdown.removeClass("open"),this.$dropdown.detach()},alignDropdown:function(){var e=this.$el.offset(),t=this.$el.height(),n=this.$el.width(),i=this.$dropdown.find(".pl-popup-button__items")[0],o=i.offsetHeight,r=i.offsetWidth,a=e.left,l=e.top+t;e.left+r>=window.innerWidth&&(a+=n-r),l+o>=window.innerHeight&&(l-=t+o+2),this.$dropdown.offset({top:l,left:a})},toggle:function(){this.$dropdown.hasClass("open")?this.close():this.open()},onClickHandler:function(){this.toggle()},updateGrouping:function(){}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.PopupButton.common",CommonPopupButtonView),_.inherit(PopupButtonControl,ContainerControl),_.extend(PopupButtonControl.prototype,{createControlModel:function(){return new PopupButtonModel},createControlView:function(e,t){(!t||!t in window.InfinniUI.viewModes.PopupButton)&&(t="common");var n=window.InfinniUI.viewModes.PopupButton[t];return new n({model:e})}},buttonControlMixin);var PopupButtonModel=ContainerModel.extend({}),ForMenuPopupButtonView=CommonPopupButtonView.extend({tagName:"a",className:"pl-popup-button",attributes:{href:"javascript:;"},template:InfinniUI.Template["controls/popupButton/forMenuView/template/popupButton.tpl.html"],dropdownTemplate:InfinniUI.Template["controls/popupButton/commonView/template/popupButton.dropdown.tpl.html"],events:{click:"onClickGripHandler"},UI:{button:".pl-popup-button__button",grip:".pl-popup-button__grip"},updateProperties:function(){ContainerView.prototype.updateProperties.call(this),this.updateContent()},updateContent:CommonButtonView.prototype.updateContent,updateText:CommonButtonView.prototype.updateText,updateHorizontalAlignment:function(){var e,t=this.model.get("horizontalAlignment"),n=this;this.whenReady(function(){return e=n.$el.parent().parent(),e.length>0},function(){"Right"==t?e.addClass("pull-right"):e.removeClass("pull-right")})},getButtonElement:function(){return this.ui.button},render:function(){this.prerenderingActions();var e=this.model.get("items").toArray(),t=this.template;return this.removeChildElements(),this.$el.html(t({items:e})),this.bindUIElements(),this.$dropdown=this.renderDropdown(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderDropdown:function(){var e=this.dropdownTemplate,t=this.model.get("items").toArray(),n=$(e({items:t}));return this.appendItemsContent(n,t),n.on("click",function(){this.close()}.bind(this)),n},appendItemsContent:function(e,t){var n,i,o=this,r=this.model.get("itemTemplate");e.find(".pl-popup-button__item").each(function(e,a){i=$(a),n=r(void 0,{index:e,item:t[e]}),o.addChildElement(n),i.append(n.render())})},open:function(){var e=this,t=this.$el.parent();$("body").append(this.$dropdown),this.$dropdown.addClass("open"),t.addClass("open"),this.alignDropdown();var n=this.$dropdown.add(this.$el);new ActionOnLoseFocus(n,function(){e.close()})},close:function(){this.$dropdown.removeClass("open"),this.$el.parent().removeClass("open"),this.$dropdown.detach()},alignDropdown:function(){var e,t=this.model.get("horizontalAlignment"),n=this.$el.parent(),i=n.offset(),o=i.top+n.height()-2,r=this.$dropdown.find(".dropdown-menu");e="Right"==t?i.left-(r.width()-n.width()):i.left,this.$dropdown.offset({top:o,left:e})},onClickGripHandler:function(){this.toggle()},updateGrouping:function(){},whenReady:function(e,t,n){var i=this;void 0===n&&(n=100),e()?t():n>0&&setTimeout(function(){i.whenReady(e,t,n-1)},10)}});InfinniUI.ObjectUtils.setPropertyValueDirect(window.InfinniUI,"viewModes.PopupButton.forMenu",ForMenuPopupButtonView),_.inherit(StackPanelControl,ContainerControl),_.extend(StackPanelControl.prototype,{createControlModel:function(){return new StackPanelModel},createControlView:function(e,t){var n=new StackPanelView({model:e});return n.viewMode=t,n}});var StackPanelModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),StackPanelView=ContainerView.extend({tagName:"ul",className:"pl-stack-panel pl-clearfix",template:{plain:InfinniUI.Template["controls/stackPanel/baseView/template/stackPanel.tpl.html"],grouped:InfinniUI.Template["controls/stackPanel/baseView/template/stackPanelGrouped.tpl.html"]},UI:{items:".stackpanel-items"},initialize:function(e){ContainerView.prototype.initialize.call(this,e),this.initOrientation()},updateGrouping:function(){var e=null!=this.model.get("groupValueSelector");e?this.strategy=new StackPanelViewGroupStrategy(this):this.strategy=new StackPanelViewPlainStrategy(this)},render:function(){this.prerenderingActions(),this.removeChildElements();var e=this.strategy.prepareItemsForRendering(),t=this.strategy.getTemplate();return this.$el.html(t(e)),this.strategy.appendItemsContent(e),this.bindUIElements(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},initOrientation:function(){this.listenTo(this.model,"change:orientation",this.updateOrientation),this.updateOrientation()},updateOrientation:function(){var e=this.model.get("orientation");this.$el.toggleClass("horizontal-orientation","Horizontal"==e),this.$el.toggleClass("pl-stack-panel_horizontal","Horizontal"==e)},getItems:function(){return this.model.get("items")},getItemTemplate:function(){return this.model.get("itemTemplate")},getGroupValueSelector:function(){return this.model.get("groupValueSelector")},getGroupItemTemplate:function(){return this.model.get("groupItemTemplate")}});_.extend(StackPanelViewGroupStrategy.prototype,{groupTemplate:InfinniUI.Template["controls/stackPanel/baseView/template/stackPanelGroup.tpl.html"],prepareItemsForRendering:function(){var e=this.stackPanel.getItems(),t="listbox-"+guid(),n={inputName:t,groups:[]},i={},o=this.stackPanel.getGroupValueSelector();e.forEach(function(e,t){var n=o(void 0,{value:e});n in i||(i[n]=[]),i[n].push(e)});for(var r in i)i.hasOwnProperty(r)&&n.groups.push({items:i[r],indices:i[r].map(function(t){return e.indexOf(t)})});return n},getTemplate:function(){return this.stackPanel.template.grouped},appendItemsContent:function(e){var t,n=this.stackPanel,i=n.$el,o=this.groupTemplate,r=this.stackPanel.getGroupItemTemplate(),a=this.stackPanel.getItemTemplate(),l=e.groups;t=l.map(function(e,t){var i,l=e.items||[],s=e.indices||[],u=$(o({items:l})),d=r(null,{index:s[0],item:e});return n.addChildElement(d),i=l.map(function(e,t){var i=a(null,{index:s[t],item:e});return n.addChildElement(i),i.render()}),$(".pl-stack-panel-group__header",u).append(d.render()),$(".pl-stack-panel-list__item",u).each(function(e,t){$(t).append(i[e])}),u}),i.append(t)}}),_.extend(StackPanelViewPlainStrategy.prototype,{prepareItemsForRendering:function(){var e=this.stackPanel.getItems(),t={items:e.toArray()};return t},getTemplate:function(){return this.stackPanel.template.plain},appendItemsContent:function(e,t){var n,i,o=this.stackPanel.$el,r=this.stackPanel.getItemTemplate(),a=e.items,l=this.stackPanel;t=t||".pl-stack-panel-i",o.find(t).each(function(e,t){i=$(t),n=r(void 0,{ +index:e,item:a[e]}),l.addChildElement(n),i.append(n.render()),i.parent().data("pl-data-item",a[e])})}}),_.inherit(TablePanelControl,ContainerControl),_.extend(TablePanelControl.prototype,{createControlModel:function(){return new TablePanelModel},createControlView:function(e){return new TablePanelView({model:e})}});var TablePanelModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),TablePanelView=ContainerView.extend({className:"pl-table-panel",initialize:function(e){ContainerView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.renderItemsContents(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItemsContents:function(){var e,t=this.model.get("items"),n=this.model.get("itemTemplate"),i=this;t.forEach(function(t,o){e=n(void 0,{item:t,index:o}),i.addChildElement(e),i.$el.append(e.render())})},updateGrouping:function(){}});_.inherit(CellControl,ContainerControl),_.extend(CellControl.prototype,{createControlModel:function(){return new CellModel},createControlView:function(e){return new CellView({model:e})}});var CellModel=ContainerModel.extend({defaults:_.defaults({columnSpan:1},ContainerModel.prototype.defaults),initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),CellView=ContainerView.extend({className:"pl-cell",initialize:function(e){ContainerView.prototype.initialize.call(this,e),this.initColumnSpan()},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.renderItemsContents(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItemsContents:function(){var e,t=this.model.get("items"),n=this.model.get("itemTemplate"),i=this;t.forEach(function(t,o){e=n(void 0,{item:t,index:o}),i.addChildElement(e),i.$el.append(e.render())})},initColumnSpan:function(){this.listenTo(this.model,"change:columnSpan",this.updateColumnSpan),this.updateColumnSpan()},updateColumnSpan:function(){var e=this.model.get("columnSpan"),t=this.columnSpan;e!=t&&(t&&this.$el.removeClass("col-xs-"+t),this.$el.addClass("col-xs-"+e),this.columnSpan=e)},updateGrouping:function(){}});_.inherit(RowControl,ContainerControl),_.extend(RowControl.prototype,{createControlModel:function(){return new RowModel},createControlView:function(e){return new RowView({model:e})}});var RowModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),RowView=ContainerView.extend({className:"pl-row row",initialize:function(e){ContainerView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.renderItemsContents(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItemsContents:function(){var e,t=this.model.get("items"),n=this.model.get("itemTemplate"),i=this;t.forEach(function(t,o){e=n(void 0,{item:t,index:o}),i.addChildElement(e),i.$el.append(e.render())})},updateGrouping:function(){}});_.inherit(TabPanelControl,ContainerControl),_.extend(TabPanelControl.prototype,{setSelectedItem:function(e){var t=null,n=this.controlModel,i=this.controlView.childElements,o=n.get("items");if(e instanceof TabPage)n.set("selectedItem",e);else if(Array.isArray(i)){var r=o.indexOf(e);r!==-1&&(t=i[r]),this.controlModel.set("selectedItem",t)}},createControlModel:function(){return new TabPanelModel},createControlView:function(e){return new TabPanelView({model:e})}});var TabPanelModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))},defaults:_.defaults({headerLocation:InfinniUI.TabHeaderLocation.top,headerOrientation:InfinniUI.TabHeaderOrientation.horizontal},ContainerModel.prototype.defaults)}),TabPanelView=ContainerView.extend({className:"pl-tabpanel",template:{top:InfinniUI.Template["controls/tabPanel/template/tabPanel.top.tpl.html"],right:InfinniUI.Template["controls/tabPanel/template/tabPanel.right.tpl.html"],bottom:InfinniUI.Template["controls/tabPanel/template/tabPanel.bottom.tpl.html"],left:InfinniUI.Template["controls/tabPanel/template/tabPanel.left.tpl.html"],none:InfinniUI.Template["controls/tabPanel/template/tabPanel.none.tpl.html"]},UI:{header:".pl-tabpanel-header",content:".pl-tabpanel-content"},initHandlersForProperties:function(){ContainerView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:headerLocation",this.onChangeHeaderLocation),this.listenTo(this.model,"change:headerOrientation",this.updateHeaderOrientation),this.listenTo(this.model,"change:selectedItem",this.updateSelectedItem)},render:function(){return this.prerenderingActions(),this.renderTemplate(this.getTemplate()),this.renderItemsContents(),this.initSelectedItem(),this.postrenderingActions(),this.trigger("render"),this.updateProperties(),this},renderItemsContents:function(){var e=this.model.get("items");this.removeChildElements(),this.ui.content.empty(),this.model.set("selectedItemIndex",-1);var t=[];e.forEach(function(e,n){t.push({tabElement:this.renderTabContent(e,n),item:e,index:n})},this),this.renderTabHeaders(t)},renderTabHeaders:function(e){var t,n=this.model,i=n.get("items");n.get("selectedItem");if(Array.isArray(this.tabHeaders))for(;t=this.tabHeaders.pop();)this.stopListening(t),t.remove();this.tabHeaders=e.map(function(e){var t=i.indexOf(e.item)!==-1,o=this.renderTabHeader(e.tabElement,t);return this.listenTo(o,"selected",function(){var t=e.tabElement.getEnabled();t&&n.set("selectedItem",e.tabElement)}),this.listenTo(o,"close",function(){var t=e.tabElement.getEnabled();t&&e.tabElement.close()}),o},this)},renderTabHeader:function(e,t){var n=new TabHeaderView({text:e.getText(),canClose:e.getCanClose(),enabled:e.getEnabled(),selected:t}),i=this;return e.onPropertyChanged("text",function(){n.setText(e.getText())}),e.onPropertyChanged("canClose",function(){n.setCanClose(e.getCanClose())}),e.onPropertyChanged("enabled",function(){n.setEnabled(e.getEnabled());var t=i.model.get("selectedItem");e==t&&i.resetDefaultSelectedItem()}),this.ui.header.append(n.render().$el),n},renderTabContent:function(e,t){var n=this.model.get("itemTemplate"),i=n(void 0,{item:e,index:t});return this.addChildElement(i),this.ui.content.append(i.render()),i},getTemplate:function(){var e,t=this.model.get("headerLocation");switch(t){case InfinniUI.TabHeaderLocation.top:e=this.template.top;break;case InfinniUI.TabHeaderLocation.right:e=this.template.right;break;case InfinniUI.TabHeaderLocation.bottom:e=this.template.bottom;break;case InfinniUI.TabHeaderLocation.left:e=this.template.left;break;case InfinniUI.TabHeaderLocation.none:default:e=this.template.none}return e},updateProperties:function(){ContainerView.prototype.updateProperties.call(this),this.updateHeaderOrientation(),this.updateSelectedItem()},onChangeHeaderLocation:function(){this.rerender()},updateHeaderOrientation:function(){},initSelectedItem:function(){var e=this.model,t=this.childElements,n=e.get("selectedItem");if(Array.isArray(t)&&0!=t.length){if(t.indexOf(n)===-1){var i=this._getFirstEnabledPageIndex();i!=-1&&e.set("selectedItem",t[i])}}else e.set("selectedItem",null)},resetDefaultSelectedItem:function(){this.model.set("selectedItem",null),this.initSelectedItem()},_getFirstEnabledPageIndex:function(){for(var e=this.childElements,t=0;t0){var n=0;t&&(n=e.indexOf(t),n=n===-1?0:Math.min(e.length-1,n+1)),t=e.getByIndex(n)}else t=null;this.setSelectedItem(t),this.setSelectedItemToValue()},selectPrevItem:function(){var e=this.get("items"),t=this.getSelectedItem();if(e.length>0){var n=0;t&&(n=e.indexOf(t),n=n===-1?0:Math.max(0,n-1)),t=e.getByIndex(n)}this.setSelectedItem(t),this.setSelectedItemToValue()},selectFirstItem:function(){var e=this.get("items"),t=null;e.length>0&&(t=e.getByIndex(0)),this.setSelectedItem(t),this.setSelectedItemToValue()},selectLastItem:function(){var e=this.get("items"),t=null;e.length>0&&(t=e.getByIndex(e.length-1)),this.setSelectedItem(t),this.setSelectedItemToValue()},toggleItem:function(e,t){var n=this.valueByItem(e);this.toggleValue(n,t),this.trigger("toggle")}}),ComboBoxView=ListEditorBaseView.extend({className:"pl-combobox form-group",template:InfinniUI.Template["controls/comboBox/template/combobox.tpl.html"],events:{"click .pl-combobox__grip":"onClickGripHandler","click .pl-combobox__value":"onClickValueHandler","click .pl-combobox__clear":"onClickClearHandler","click .pl-control":"onClickValueHandler","keydown .pl-control":"onKeyDownControlHandler"},UI:_.defaults({control:".pl-control",label:".pl-control-label",value:".pl-combobox__value",clear:".pl-combobox__clear"},ListEditorBaseView.prototype.UI),isControlElement:function(e){var t=ListEditorBaseView.prototype.isControlElement.call(this,e);return t?t:!!this.dropDownView&&$.contains(this.dropDownView.el,e)},updateFocusable:function(){var e=this.model.get("focusable"),t=this.model.get("enabled");e&&t?this.ui.control.attr("tabindex",0):this.ui.control.removeAttr("tabindex")},initialize:function(e){ListEditorBaseView.prototype.initialize.call(this,e);var t=this.model,n=this;this.on("render",function(){n.renderValue(),t.on("change:dropdown",function(e,t){if(t){e.set("autocompleteValue",""),e.set("focused",!0),n.dropDownView&&n.dropDownView.remove();var i=new ComboBoxDropdownView({model:e});n.dropDownView=i,this.listenTo(i,"search",_.debounce(n.onSearchValueHandler.bind(n),300));var o=i.render();$("body").append(o),i.updatePosition(n.el),n.dropDownView.on("itemsRendered2",function(){i.updatePosition(n.el)}),e.get("autocomplete")?i.setSearchFocus():n.ui.control.focus(),setTimeout(i.ensureVisibleSelectedItem.bind(i),0)}else n.ui.control.focus()}),t.onValueChanged(this.onChangeValueHandler.bind(this))},this)},initHandlersForProperties:function(){ListEditorBaseView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:showClear",this.updateShowClear),this.listenTo(this.model,"change:labelText",this.updateLabelText)},render:function(){return this.prerenderingActions(),this.renderTemplate(this.getTemplate()),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},getTemplate:function(){return this.template},onKeyDownControlHandler:function(e){var t=this.model.get("enabled");if(!t)return void e.preventDefault();if(!e.ctrlKey&&!e.altKey){if(this.isDropdown())return this.dropDownView.onKeyDownHandler.call(this.dropDownView,e);switch(e.which){case 40:case 13:e.preventDefault(),this.toggleDropdown()}}},onClickClearHandler:function(){var e=this.model.get("enabled");e&&(this.model.set("value",null),this.ui.control.focus())},onClickGripHandler:function(){var e=this.model.get("enabled");e&&this.toggleDropdown()},updateProperties:function(){ListEditorBaseView.prototype.updateProperties.call(this),this.updateLabelText(),this.updateShowClear()},updateGrouping:function(){this.toggleDropdown(!1)},updateLabelText:function(){var e=this.model.get("labelText");e&&""!==e?this.ui.label.toggleClass("hidden",!1):this.ui.label.toggleClass("hidden",!0),this.ui.label.text(e)},updateEnabled:function(){ListEditorBaseView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");e?this.updateFocusable():this.ui.control.removeAttr("tabindex")},updateValue:function(){this.updateShowClear()},updateShowClear:function(){var e=this.model,t=e.get("showClear"),n=e.get("value"),i=null===n||"undefined"==typeof n;this.ui.clear.toggleClass("hidden",!t||i)},updateSelectedItem:function(){},updateDisabledItem:function(){this.toggleDropdown(!1)},isDropdown:function(){var e=this.model;return!!e.get("dropdown")},toggleDropdown:function(e){var t=this.model;"undefined"==typeof e&&(e=!t.get("dropdown")),t.set("dropdown",e)},onChangeValueHandler:function(){this.renderValue()},rerender:function(){},renderValue:function(){var e=this.model,t=e.get("multiSelect"),n=this.model.get("value"),i=[],o=this.model.get("valueTemplate");if(t&&Array.isArray(n)){var r=new ComboBoxValues({items:n.map(function(e,t){return{$value:o(null,{value:e,index:t}).render(),value:e,index:t}})});r.listenTo(e,"toggle",r.setFocus),this.listenTo(r,"remove",this.onRemoveValueHandler),this.listenTo(r,"search",_.debounce(this.onSearchValueHandler.bind(this),300)),i=r.render()}else i=o(null,{value:n}).render();this.ui.value.empty(),this.ui.value.append(i),editorBaseViewMixin.updateValueState.call(this)},onRemoveValueHandler:function(e){this.model.toggleValue(e,!1)},onSearchValueHandler:function(e){this.toggleDropdown(!0),this.model.set("autocompleteValue",e)},onClickValueHandler:function(e){var t=this.model.get("enabled");t&&this.toggleDropdown(!0)}});_.inherit(ContextMenuControl,ContainerControl),_.extend(ContextMenuControl.prototype,{createControlModel:function(){return new ContextMenuModel},createControlView:function(e){return new ContextMenuView({model:e})}});var ContextMenuModel=ContainerModel.extend({}),ContextMenuView=ContainerView.extend({contextMenuTemplate:InfinniUI.Template["controls/contextMenu/template/contextMenu.tpl.html"],updateHorizontalAlignment:function(){var e,t=this.model.get("horizontalAlignment"),n=this;this.whenReady(function(){return e=n.$el.parent().parent(),e.length>0},function(){"Right"==t?e.addClass("pull-right"):e.removeClass("pull-right")})},render:function(){var e=window.InfinniUI.global.messageBus,t=this;return this.prerenderingActions(),this.removeChildElements(),this.$el=this.renderDropdown(),this.bindUIElements(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),e.subscribe(messageTypes.onOpenContextMenu.name,function(e,n){t.open(n.value)}),this},renderDropdown:function(){var e=this.contextMenuTemplate,t=this.model.get("items").toArray(),n=$(e({items:t}));return this.appendItemsContent(n,t),n.on("click",function(){this.close()}.bind(this)),n.on("contextmenu",function(e){e.preventDefault()}.bind(this)),n},appendItemsContent:function(e,t){var n,i,o=this,r=this.model.get("itemTemplate");e.find(".pl-popup-button__item").each(function(e,a){i=$(a),n=r(void 0,{index:e,item:t[e]}),o.addChildElement(n),i.append(n.render())})},open:function(e){var t=this;$("body").append(this.$el);var n=this.$el.parent();this.$el.addClass("open"),n.addClass("open"),this.alignDropdown(e);var i=this.$el;new ActionOnLoseFocus(i,function(){t.close()})},close:function(){this.$el.removeClass("open"),this.$el.parent().removeClass("open"),this.$el.detach()},alignDropdown:function(e){var t=(this.model.get("horizontalAlignment"),this.$el.parent()),n={width:t.width(),height:t.height()},i={width:this.$el[0].children[0].clientWidth,height:this.$el[0].children[0].clientHeight};e.x+i.width>n.width&&(e.x-=i.width),e.y+i.height>n.height&&(e.y-=i.height),this.$el.offset({top:e.y,left:e.x})},updateGrouping:function(){},whenReady:function(e,t,n){var i=this;void 0===n&&(n=100),e()?t():n>0&&setTimeout(function(){i.whenReady(e,t,n-1)},10)}});_.inherit(DividerControl,Control),_.extend(DividerControl.prototype,{createControlModel:function(){return new DividerModel},createControlView:function(e){return new DividerView({model:e})}});var DividerModel=ControlModel.extend({initialize:function(){ControlModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),DividerView=ControlView.extend({tagName:"hr",className:"pl-divider",initialize:function(e){ControlView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this}}),ExtensionPanelControl=function(){_.superClass(ExtensionPanelControl,this)};_.inherit(ExtensionPanelControl,ContainerControl),_.extend(ExtensionPanelControl.prototype,{createControlModel:function(){return new ExtensionPanelModel},createControlView:function(e){return new ExtensionPanelView({model:e})}});var ExtensionPanelModel=ContainerModel.extend({defaults:_.defaults({extensionName:null,context:null},ContainerModel.prototype.defaults),initialize:function(){ContainerModel.prototype.initialize.apply(this)}}),ExtensionPanelView=ContainerView.extend({className:"pl-extension-panel",initialize:function(){ContainerView.prototype.initialize.apply(this),this.extensionObject=null},render:function(){return this.prerenderingActions(),this.extensionObject||this.initExtensionObject(),this.extensionObject.render(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},updateGrouping:function(){},initExtensionObject:function(){var e=this.model.get("extensionName"),t=this.model.get("context"),n=this.model.get("itemTemplate"),i=this.model.get("parameters"),o=this.model.get("items"),r=this.model.get("builder");this.extensionObject=new window[e](t,{$el:this.$el,parameters:i,itemTemplate:n,items:o,builder:r})}});_.inherit(FileBoxControl,Control),_.extend(FileBoxControl.prototype,{createControlModel:function(){return new FileBoxModel},createControlView:function(e){return new FileBoxView({model:e})}},editorBaseControlMixin);var FileBoxModel=ControlModel.extend(_.extend({defaults:_.defaults({},editorBaseModelMixin.defaults_editorBaseModel,ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.initialize_editorBaseModel(),this.set("acceptTypes",new Collection),this.on("change:file",this.onChangeFileHandler),this.on("change:value",function(e,t){t instanceof File&&e.set("fileName",t.name)}),this.on("invalid",function(e,t){this.set("errorText",t)})},validate:function(e,t){var n=e.file,i=this.get("maxSize"),o=this.get("acceptTypes");if(n){if(i&&n.size>i)return localized.strings.FileBox.fileSizeTooBig.replace(/\{chosen-size\}/g,(n.size/1048576).toFixed(1)).replace(/\{permitted-size\}/g,(i/1048576).toFixed(1));if(o.length){var r=o.contains(n.type),a=n.name.toLowerCase();if(!r)var l=a.length,r=o.some(function(e){return a.lastIndexOf(e.toLowerCase())===l-e.length});if(!r)return localized.strings.FileBox.incorrectFormat}}},setFile:function(e){this.set("file",e,{validate:!0})&&this.set("errorText","")},removeFile:function(){this.setFile(null)},onChangeFileHandler:function(e,t){t?(e.set("fileName",t.name),e.set("fileSize",t.size)):(e.set("fileName",null),e.set("fileSize",null)),e.set("value",t)}},editorBaseModelMixin)),FileBoxView=ControlView.extend(_.extend({},editorBaseViewMixin,{template:InfinniUI.Template["controls/fileBox/template/template.tpl.html"],className:"pl-file-box",UI:_.extend({},editorBaseViewMixin.UI,{label:".pl-control-label",btnRemove:".pl-filebox-btn-remove",btnPick:".pl-filebox-btn-pick",fileEmpty:".pl-filebox-file-empty",fileUpload:".pl-filebox-file-upload",fileDownload:".pl-filebox-file-download",fileDownloadUrl:".pl-filebox-file-download-url",edit:".pl-filebox-edit",control:".form-control",input:"input"}),events:{"change input":"onChangeFileHandler","click .pl-filebox-btn-remove":"onClickRemoveImageHandler"},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:labelText",this.updateLabelText),this.listenTo(this.model,"change:fileName",this.updateFileName),this.listenTo(this.model,"change:fileSize",this.updateFileSize),this.listenTo(this.model,"change:fileTime",this.updateFileTime), +this.listenTo(this.model,"change:fileType",this.updateFileType),this.listenTo(this.model,"change:value",this.updateValue),this.listenTo(this.model,"change:hintText",this.updateHintText),this.listenTo(this.model,"change:errorText",this.updateErrorText),this.listenTo(this.model,"change:warningText",this.updateWarningText),this.listenTo(this.model,"invalid",this.onInvalidHandler);var e=this.model.get("acceptTypes");e.onChange(this.updateAcceptTypes.bind(this))},updateProperties:function(){ControlView.prototype.updateProperties.call(this),this.updateLabelText(),this.updateFileName(),this.updateFileSize(),this.updateFileType(),this.updateFileTime(),this.updateAcceptTypes(),this.updateValue(),this.updateHintText(),this.updateErrorText(),this.updateWarningText()},updateLabelText:function(){var e=this.model.get("labelText");""!=e?this.ui.label.css({display:"inline-block"}).text(e):this.ui.label.css({display:"none"})},updateAcceptTypes:function(){var e=this.model.get("acceptTypes");if(0===e.length)this.ui.input.removeAttr("accept");else{var t=e.toArray().join(",");this.ui.input.attr("accept",t)}},updateFocusable:function(){var e=this.model.get("focusable");e?this.ui.control.attr("tabindex",0):this.ui.control.removeAttr("tabindex")},updateText:function(){var e=this.model.get("text");this.ui.btnPick.attr("title",e)},updateHintText:function(){var e=this.model.get("hintText");e?this.ui.hintText.text(e).removeClass("hidden"):this.ui.hintText.text("").addClass("hidden")},updateErrorText:function(){var e=this.model.get("errorText");e?this.ui.errorText.text(e).removeClass("hidden"):this.ui.errorText.text("").addClass("hidden")},updateWarningText:function(){var e=this.model.get("warningText");e?this.ui.warningText.text(e).removeClass("hidden"):this.ui.warningText.text("").addClass("hidden")},updateEnabled:function(){ControlView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");this.ui.input.prop("disabled",!e),this.ui.btnRemove.prop("disabled",!e),this.ui.btnPick.toggleClass("disabled",!e)},updateFileName:function(){var e=this.model.get("fileName");this.ui.fileUpload.text(e),this.ui.fileDownloadUrl.text(e)},updateFileSize:function(){},updateFileInfo:function(){return},updateFileTime:function(){this.model.get("fileTime")},updateFileType:function(){this.model.get("fileType")},updateValue:function(){var e=this.model,t=e.get("value"),n=!1,i=!1,o=!1;null===t||"undefined"==typeof t?(n=null===t||"undefined"==typeof t,this.ui.input.val(null),this.updateUrl(null)):t&&"object"==typeof t?(i=t&&"object"==typeof t,this.updateUrl(null)):(o=!0,this.updateUrl(t)),this.ui.fileEmpty.toggleClass("hidden",!n),this.ui.fileUpload.toggleClass("hidden",!i),this.ui.fileDownload.toggleClass("hidden",!o),this.ui.btnRemove.toggleClass("hidden",n),this.ui.btnPick.toggleClass("hidden",!n)},updateUrl:function(e){this.ui.fileDownloadUrl.attr("href",e);var t=null===e||"undefined"==typeof e;this.$el.toggleClass("pl-empty",t),this.updateFileInfo()},onClickRemoveImageHandler:function(){this.model.removeFile(),this.ui.input.val("")},onChangeFileHandler:function(){var e=null,t=this.ui.input[0].files;t&&t[0]&&(e=t[0]),this.model.setFile(e)},render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},onInvalidHandler:function(){this.ui.input.val(null)}}));_.inherit(FormControl,StackPanelControl),_.extend(FormControl.prototype,{createControlModel:function(){return new FormModel},createControlView:function(e){return new FormView({model:e})},onSubmit:function(e){this.controlView.$el.on("submit",e)},setSubmitFunction:function(e){this.controlModel.set("submitFunction",e)},getSubmitFunction:function(){return this.controlModel.get("submitFunction")},setMethod:function(e){this.controlModel.set("method",e)},getMethod:function(){return this.controlModel.get("method")},setAction:function(e){this.controlModel.set("action",e)},getAction:function(){return this.controlModel.get("action")}});var FormModel=StackPanelModel.extend({defaults:_.defaults({submitFunction:null,method:"",action:""},StackPanelModel.prototype.defaults)}),FormView=StackPanelView.extend({className:"pl-form",tagName:"form",template:{plain:InfinniUI.Template["controls/form/template/form.tpl.html"]},events:{submit:"onSubmit"},onSubmit:function(e){e.preventDefault()},initialize:function(e){StackPanelView.prototype.initialize.call(this,e),this.listenTo(this.model,"change:method",this.updateMethod),this.listenTo(this.model,"change:action",this.updateAction)},updateGrouping:function(){this.strategy=new StackPanelViewPlainStrategy(this)},render:function(){this.prerenderingActions(),this.removeChildElements();var e=this.strategy.prepareItemsForRendering(),t=this.strategy.getTemplate();return this.$el.html(t(e)),this.strategy.appendItemsContent(e,".pl-form-i"),this.bindUIElements(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},updateProperties:function(){StackPanelView.prototype.updateProperties.call(this),this.updateMethod(),this.updateAction()},updateMethod:function(){var e=this.model.get("method");this.$el.attr("method",e)},updateAction:function(){var e=this.model.get("action");this.$el.attr("action",e)}}),FrameControl=function(){_.superClass(FrameControl,this),this.initialize_editorBaseControl()};_.inherit(FrameControl,Control),_.extend(FrameControl.prototype,{createControlModel:function(){return new FrameModel},createControlView:function(e){return new FrameView({model:e})}},editorBaseControlMixin);var FrameModel=ControlModel.extend(_.extend({defaults:_.defaults({},editorBaseModelMixin.defaults_editorBaseModel,ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.initialize_editorBaseModel()}},editorBaseModelMixin)),FrameView=ControlView.extend(_.extend({},editorBaseViewMixin,{className:"pl-frame",template:InfinniUI.Template["controls/frame/template/frame.tpl.html"],UI:_.extend({},editorBaseViewMixin.UI,{iframe:"iframe"}),initialize:function(){ControlView.prototype.initialize.apply(this)},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),editorBaseViewMixin.initHandlersForProperties.call(this)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),editorBaseViewMixin.updateProperties.call(this)},updateValue:function(){var e=this.model.get("value");this.ui.iframe.attr("src",e)},getData:function(){return _.extend({},ControlView.prototype.getData.call(this),editorBaseViewMixin.getData.call(this),{})},render:function(){this.model;return this.prerenderingActions(),this.renderTemplate(this.template),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this}}));_.inherit(GridPanelControl,ContainerControl),_.extend(GridPanelControl.prototype,{createControlModel:function(){return new GridPanelModel},createControlView:function(e){return new GridPanelView({model:e})}});var GridPanelModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),GridPanelView=ContainerView.extend({className:"pl-grid-panel pl-clearfix",columnCount:12,template:{row:InfinniUI.Template["controls/gridPanel/template/row.tpl.html"]},initialize:function(e){ContainerView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.renderItemsContents(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItemsContents:function(){var e,t=this.model.get("items"),n=this.model.get("itemTemplate"),i=this,o=[],r=0;t.forEach(function(t,a){e=n(void 0,{item:t,index:a});var l=e.getColumnSpan();r+l>i.columnCount&&(i.renderRow(o),o.length=0,r=0),o.push(e),r+=l}),o.length&&i.renderRow(o)},renderRow:function(e){var t=this,n=$('
');n.append(e.map(function(e){return t.addChildElement(e),e.render()})),this.$el.append(n)},updateGrouping:function(){}});_.inherit(IconControl,Control),_.extend(IconControl.prototype,{createControlModel:function(){return new IconModel},createControlView:function(e){return new IconView({model:e})}});var IconModel=ControlModel.extend({defaults:_.defaults({value:null,focusable:!1},ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments)}}),IconView=ControlView.extend({className:"pl-icon fa",tagName:"i",render:function(){return this.prerenderingActions(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderIcon:function(){var e=this.model.get("value");this.switchClass("fa",e)},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:value",this.updateValue)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),this.updateValue()},updateFocusable:function(){var e=this.model.get("focusable");e?this.$el.attr("tabindex",0):this.$el.removeAttr("tabindex")},updateValue:function(){this.renderIcon()}});_.inherit(ImageBoxControl,Control),_.extend(ImageBoxControl.prototype,{createControlModel:function(){return new ImageBoxModel},createControlView:function(e){return new ImageBoxView({model:e})}},editorBaseControlMixin);var ImageBoxModel=ControlModel.extend(_.extend({defaults:_.defaults({text:localized.strings.ImageBox.chooseImage},editorBaseModelMixin.defaults_editorBaseModel,ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.initialize_editorBaseModel(),this.set("acceptTypes",new Collection),this.on("change:file",this.onChangeFileHandler),this.on("invalid",function(e,t){this.set("errorText",t)})},validate:function(e,t){var n=e.file,i=this.get("maxSize"),o=this.get("acceptTypes");if(n){if(i&&n.size>i)return localized.strings.ImageBox.imageSizeTooBig.replace(/\{chosen-size\}/g,(n.size/1048576).toFixed(1)).replace(/\{permitted-size\}/g,(i/1048576).toFixed(1));if(o.length&&!o.contains(n.type))return localized.strings.ImageBox.incorrectFormat}},setFile:function(e){this.set("file",e,{validate:!0})&&this.set("errorText","")},removeFile:function(){this.setFile(null)},onChangeFileHandler:function(e,t){}},editorBaseModelMixin)),ImageBoxView=ControlView.extend(_.extend({},editorBaseViewMixin,{className:"pl-imagebox",template:InfinniUI.Template["controls/imageBox/template/imageBox.tpl.html"],UI:_.extend({},editorBaseViewMixin.UI,{input:"input",img:"img",file:".pl-image-file",remove:".pl-image-remove",uploadButton:".pl-image-file-upload-button"}),events:{"change input":"onChangeFileHandler","click .pl-image-remove":"onClickRemoveImageHandler"},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:value",this.updateValue),this.listenTo(this.model,"change:hintText",this.updateHintText),this.listenTo(this.model,"change:errorText",this.updateErrorText),this.listenTo(this.model,"change:warningText",this.updateWarningText)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),this.updateValue(),this.updateHintText(),this.updateErrorText(),this.updateWarningText()},updateFocusable:function(){var e=this.model.get("focusable");e?this.ui.file.attr("tabindex",0):this.ui.file.removeAttr("tabindex")},updateText:function(){var e=this.model.get("text");this.ui.uploadButton.text(e)},updateEnabled:function(){ControlView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");this.ui.input.prop("disabled",!e)},updateValue:function(){var e=this.model,t=e.get("value");if(t&&"object"==typeof t){this.stopLoadingFile();var n=this.loadPreview(t);this.fileLoader=n,n.then(function(e,t){this.updateUrl(t)}.bind(this),function(e){console.log(e)})}else this.updateUrl(t)},updateUrl:function(e){this.ui.img.attr("src",e);var t=null===e||"undefined"==typeof e;this.$el.toggleClass("pl-empty",t)},stopLoadingFile:function(){var e=this.fileLoader;e&&"pending"===e.state()&&e.reject()},loadPreview:function(e){var t=$.Deferred(),n=new FileReader;return n.onload=function(e){return function(n){t.resolve(e,n.target.result)}}(e),n.onerror=function(e){t.reject(e)},n.readAsDataURL(e),t.promise()},onClickRemoveImageHandler:function(){this.model.removeFile(),this.ui.input.val("")},onChangeFileHandler:function(){var e=null,t=this.ui.input[0].files;t&&t[0]&&(e=t[0]),this.model.setFile(e)},render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this}}));_.inherit(IndeterminateCheckBoxControl,CheckBoxControl),_.extend(IndeterminateCheckBoxControl.prototype,{createControlModel:function(){return new IndeterminateCheckBoxModel},createControlView:function(e){return new IndeterminateCheckBoxView({model:e})}},editorBaseControlMixin);var IndeterminateCheckBoxModel=CheckBoxModel.extend({defaults:_.defaults({value:"unchecked"},CheckBoxModel.prototype.defaults)}),IndeterminateCheckBoxView=CheckBoxView.extend({className:"pl-indeterminate-checkbox",onClickHandler:function(){var e=this.model,t=e.get("enabled");if(t){var n=e.get("value");n="indeterminate"===n?"unchecked":"unchecked"===n?"checked":"unchecked",e.set("value",n)}},updateValue:function(){var e=this.model.get("value");"checked"===e?(this.ui.input.prop("indeterminate",!1),this.ui.input.prop("checked",!0)):"unchecked"===e?(this.ui.input.prop("indeterminate",!1),this.ui.input.prop("checked",!1)):"indeterminate"===e&&(this.ui.input.prop("checked",!1),this.ui.input.prop("indeterminate",!0))}});_.inherit(LinkElementControl,ButtonControl),_.extend(LinkElementControl.prototype,{createControlModel:function(){return new LinkElementModel},createControlView:function(e){return new LinkElementView({model:e})}});var LinkElementModel=ButtonModel.extend({defaults:_.defaults({href:"javascript:;",target:"self"},ButtonModel.prototype.defaults),initialize:function(){ButtonModel.prototype.initialize.apply(this,arguments)}}),LinkElementView=CommonButtonView.extend({tagName:"a",className:"pl-link",events:{click:"onClickHandler"},template:function(){return""},updateProperties:function(){CommonButtonView.prototype.updateProperties.call(this),this.updateHref(),this.updateTarget()},getButtonElement:function(){return this.$el},initHandlersForProperties:function(){CommonButtonView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:href",this.updateHref),this.listenTo(this.model,"change:target",this.updateTarget)},updateHref:function(){var e=this.model.get("href"),t=this.getButtonElement();t.attr("href",e)},updateTarget:function(){var e=this.model.get("target"),t=this.getButtonElement();t.attr("target","_"+e)},onClickHandler:function(e){var t=this.model.get("href");t.indexOf("http://")===-1&&(InfinniUI.AppRouter.navigate(t,{trigger:!0}),2!==e.which&&e.preventDefault())}});!function(){var e=InfinniUI.Template["controls/loaderIndicator/template.tpl.html"];InfinniUI.loaderIndicator={show:function(){$.blockUI({message:$(e()),ignoreIfBlocked:!0,baseZ:99999})},hide:function(){$.unblockUI()}},InfinniUI.config.useLoaderIndicator&&jQuery(function(){var t=$(e());$("body").append(t),$.blockUI.defaults.css={},$(document).ajaxStart(function(){$.blockUI({message:t,ignoreIfBlocked:!0,baseZ:99999})}).ajaxStop(function(){$.unblockUI()}).ajaxError(function(){$.unblockUI()})})}(),_.inherit(MenuBarControl,ContainerControl),_.extend(MenuBarControl.prototype,{createControlModel:function(){return new MenuBarModel},createControlView:function(e){return new MenuBarView({model:e})}});var MenuBarModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))}}),MenuBarView=ContainerView.extend({tagName:"nav",className:"pl-menu-bar navbar navbar-default",template:InfinniUI.Template["controls/menuBar/template/menuBar.tpl.html"],UI:{},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.$el.html(this.template({items:this.model.get("items")})),this.renderItemsContents(),this.bindUIElements(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItemsContents:function(){var e,t,n=this.$el.find(".pl-menu-bar-item"),i=this.model.get("items"),o=this.model.get("itemTemplate"),r=this;n.each(function(n,a){t=i.getByIndex(n),e=o(void 0,{item:t,index:n}),r.addChildElement(e),$(a).append(e.render())})},updateGrouping:function(){}});_.inherit(NumericBoxControl,TextEditorBaseControl),_.extend(NumericBoxControl.prototype,{createControlModel:function(){return new NumericBoxModel},createControlView:function(e){return new NumericBoxView({model:e})}});var NumericBoxModel=TextEditorBaseModel.extend({defaults:_.defaults({increment:1,inputType:"number"},TextEditorBaseModel.prototype.defaults),incValue:function(){var e=this.get("increment");this.addToValue(e)},decValue:function(){var e=this.get("increment");this.addToValue(-e)},addToValue:function(e){var t=this.get("value"),n=this.get("startValue"),i=this.get("minValue"),o=this.get("maxValue"),r=_.isNumber(t)?t:+t;this.isSetValue(t)&&_.isNumber(t)?r+=e:r=_.isNumber(n)?n:0,_.isNumber(i)&&ro&&(r=o),this.set("value",r)},initialize:function(){TextEditorBaseModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))},validateValue:function(e,t){var n=!0,i=this.get("minValue"),o=this.get("maxValue");return!this.isSetValue(e)||(_.isNumber(i)&&_.isNumber(o)?(eo)&&(n=!1):_.isNumber(i)&&eo&&(n=!1),n)}}),NumericBoxView=TextEditorBaseView.extend({className:"pl-numericbox form-group",template:InfinniUI.Template["controls/numericBox/template/numericBox.tpl.html"],UI:_.extend({},TextEditorBaseView.prototype.UI,{min:".pl-numeric-box-min",max:".pl-numeric-box-max"}),events:_.extend({},TextEditorBaseView.prototype.events,{"click .pl-numeric-box-min":"onClickMinControlHandler","click .pl-numeric-box-max":"onClickMaxControlHandler","mousedown .pl-numeric-box-min":"onMousedownMinControlHandler","mousedown .pl-numeric-box-max":"onMousedownMaxControlHandler"}),render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.renderNumericBoxEditor(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},getData:function(){var e=this.model;return _.extend({},TextEditorBaseView.prototype.getData.call(this),{minValue:e.get("minValue"),maxValue:e.get("maxValue"),increment:e.get("increment")})},renderNumericBoxEditor:function(){this.renderControlEditor()},onChangeEnabledHandler:function(e,t){this.ui.control.prop("disabled",!t),this.ui.min.prop("disabled",!t),this.ui.max.prop("disabled",!t)},onClickMinControlHandler:function(){this.canChangeValue()&&this.model.decValue()},onClickMaxControlHandler:function(){this.canChangeValue()&&this.model.incValue()},onMousedownMinControlHandler:function(e){this.canChangeValue()&&this.repeatUpdateValue(this.model.decValue.bind(this.model))},onMousedownMaxControlHandler:function(e){this.canChangeValue()&&this.repeatUpdateValue(this.model.incValue.bind(this.model))},repeatUpdateValue:function(e){function t(){n&&(clearInterval(n),n=null),window.document.removeEventListener("mouseup",t)}var n;window.document.addEventListener("mouseup",t),n=setInterval(e,200)},canChangeValue:function(){var e=this.model,t=e.get("enabled");return t===!0}});_.inherit(PanelControl,ContainerControl),_.extend(PanelControl.prototype,{createControlModel:function(){return new PanelModel},createControlView:function(e){return new PanelView({model:e})}});var PanelModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments)),this.on("change:collapsed",function(e,t){e.trigger(t?"collapsed":"expanded",null,{})})},defaults:_.defaults({collapsible:!1,collapsed:!1,collapsibleArea:""},ContainerModel.prototype.defaults),set:function(e,t,n){if(null==e)return this;var i;"object"==typeof e?(i=e,n=t):(i={})[e]=t;var o,r;if("collapsed"in i){o=this.get("collapsed"),r=i.collapsed;var a;r&&!o?a=this.set("_collapsing",!0,{validate:!1}).trigger("collapsing",null,{}).get("_collapsing"):!r&&o&&(a=this.set("_expanding",!0,{validate:!1}).trigger("expanding",null,{}).get("_expanding")),a===!1&&delete i.collapsed}return ContainerModel.prototype.set.call(this,i,n)},on:function(e,t,n){var i,o=this;switch(e){case"collapsing":i=function(){var e=t(null,{});e===!1&&o.set("_collapsing",!1)};break;case"expanding":i=function(){var e=t(null,{});e===!1&&o.set("_expanding",!1)};break;default:i=t}ContainerModel.prototype.on.call(this,e,i,n)}}),PanelView=ContainerView.extend({className:"pl-panel panel panel-default",template:InfinniUI.Template["controls/panel/template/panel.tpl.html"],UI:{header:".pl-panel-header",items:".panel-items"},events:{"click >.pl-panel-header":"onClickHeaderHandler"},initialize:function(e){ContainerView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.$el.html(this.template({items:this.model.get("items")})),this.bindUIElements(),this.renderItemsContents(),this.trigger("render"),this.updateProperties(),this.postrenderingActions(),this},initHandlersForProperties:function(){ContainerView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:collapsed",this.updateCollapsed),this.listenTo(this.model,"change:collapsible",this.updateCollapsible),this.listenTo(this.model,"change:header",this.updateHeader)},updateProperties:function(){ContainerView.prototype.updateProperties.call(this),this.updateCollapsed(),this.updateCollapsible(),this.updateHeader()},updateCollapsed:function(){this.ui.header.toggleClass("pl-collapsed",this.model.get("collapsed"))},updateCollapsible:function(e,t){this.ui.header.toggleClass("pl-collapsible",this.model.get("collapsible"))},updateHeader:function(){var e=this.model;this.ui.header.empty();var t=e.get("headerTemplate");if("function"==typeof t){var n=e.get("header");this.ui.header.append(t(null,{value:n}).render())}},renderItemsContents:function(){var e,t,n=this.$el.find(".pl-panel-i"),i=this.model.get("items"),o=this.model.get("itemTemplate"),r=this;n.each(function(n,a){t=i.getByIndex(n),e=o(void 0,{item:t,index:n}),r.addChildElement(e),$(a).append(e.render())})},updateGrouping:function(){},onEventCallback:function(){var e=this.model.get("collapsible");if(e){var t=this.model.get("collapsed");this.model.set("collapsed",!t),this.updateLayout()}},onClickHeaderHandler:function(e){var t=this.model.get("collapsibleArea");""!==t?$(e.target).closest("[data-pl-name="+t+"]").length&&this.onEventCallback():this.onEventCallback()}}),PasswordBoxControl=function(){_.superClass(PasswordBoxControl,this),this.initialize_editorBaseControl()};_.inherit(PasswordBoxControl,Control),_.extend(PasswordBoxControl.prototype,{createControlModel:function(){return new PasswordBoxModel},createControlView:function(e){return new PasswordBoxView({model:e})}},editorBaseControlMixin);var PasswordBoxModel=ControlModel.extend(_.extend({defaults:_.defaults({autocomplete:!0},editorBaseModelMixin.defaults_editorBaseModel,ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.initialize_editorBaseModel()}},editorBaseModelMixin)),PasswordBoxView=ControlView.extend(_.extend({},editorBaseViewMixin,{className:"pl-password-box form-group",template:{autocomplete:InfinniUI.Template["controls/passwordBox/template/passwordBox.on.tpl.html"],noautocomplete:InfinniUI.Template["controls/passwordBox/template/passwordBox.off.tpl.html"]},UI:_.extend({},editorBaseViewMixin.UI,{label:".pl-control-label",input:".pl-control"}),events:{"blur .pl-control":"onBlurHandler","input .pl-control":"onInputHandler","change .pl-control":"onChangeHandler"},initialize:function(){ControlView.prototype.initialize.apply(this)},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),editorBaseViewMixin.initHandlersForProperties.call(this),this.listenTo(this.model,"change:labelText",this.updateLabelText),this.listenTo(this.model,"change:labelFloating",this.updateLabelFloating),this.listenTo(this.model,"change:autocomplete",this.updateAutocomplete)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),editorBaseViewMixin.updateProperties.call(this),this.updateLabelText()},updateLabelText:function(){var e=this.model.get("labelText");this.ui.label.text(e)},updateAutocomplete:function(){this.rerender()},updateValue:function(){editorBaseViewMixin.updateValueState.call(this);var e=this.model.get("value");this.ui.input.val(e)},updateEnabled:function(){ControlView.prototype.updateEnabled.call(this);var e=this.model.get("enabled");this.ui.input.prop("disabled",!e)},getData:function(){return _.extend({},ControlView.prototype.getData.call(this),editorBaseViewMixin.getData.call(this))},render:function(){this.model;return this.prerenderingActions(),this.renderTemplate(this.getTemplate()),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},remove:function(){ControlView.prototype.remove.call(this)},getTemplate:function(){var e=this.model;return e.get("autocomplete")?this.template.autocomplete:this.template.noautocomplete},updateModelValue:function(){var e=this.ui.input.val(),t=this.model;t.set("value",e),t.set("rawValue",e)},onBlurHandler:function(){this.updateModelValue()},onChangeHandler:function(){this.updateModelValue()},onInputHandler:function(){this.updateModelValue()}}));_.inherit(ScrollPanelControl,ContainerControl),_.extend(ScrollPanelControl.prototype,{createControlModel:function(){return new ScrollPanelModel},createControlView:function(e){return new ScrollPanelView({model:e})}});var ScrollPanelModel=ContainerModel.extend({initialize:function(){ContainerModel.prototype.initialize.apply(this,Array.prototype.slice.call(arguments))},defaults:_.defaults({verticalAlignment:"Stretch",horizontalScroll:InfinniUI.ScrollVisibility.auto,verticalScroll:InfinniUI.ScrollVisibility.auto},ContainerModel.prototype.defaults)}),ScrollPanelView=ContainerView.extend({className:"pl-scrollpanel panel panel-default",template:InfinniUI.Template["controls/scrollPanel/template/scrollPanel.tpl.html"],UI:{},initialize:function(e){ContainerView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.removeChildElements(),this.$el.html(this.template({items:this.model.get("items")})),this.renderItemsContents(),this.bindUIElements(),this.postrenderingActions(),this.trigger("render"),this.updateProperties(),function(e){setTimeout(function(){e.scrollTop(0)},0)}(this.$el),this},initHandlersForProperties:function(){ContainerView.prototype.initHandlersForProperties.call(this),this.listenTo(this.model,"change:horizontalScroll",this.updateHorizontalScroll),this.listenTo(this.model,"change:verticalScroll",this.updateVerticalScroll)},updateProperties:function(){ContainerView.prototype.updateProperties.call(this),this.updateHorizontalScroll(),this.updateVerticalScroll()},updateHorizontalScroll:function(){var e="";switch(this.model.get("horizontalScroll")){case InfinniUI.ScrollVisibility.visible:e="visible";break;case InfinniUI.ScrollVisibility.hidden:e="hidden";break;case InfinniUI.ScrollVisibility.auto:default:e="auto"}this.switchClass("pl-horizontal-scroll",e,this.$el)},updateVerticalScroll:function(e,t){var n="";switch(this.model.get("verticalScroll")){case InfinniUI.ScrollVisibility.visible:n="visible";break;case InfinniUI.ScrollVisibility.hidden:n="hidden";break;case InfinniUI.ScrollVisibility.auto:default:n="auto"}this.switchClass("pl-vertical-scroll",n,this.$el)},renderItemsContents:function(){var e,t,n=this.$el.find(".pl-scrollpanel-i"),i=this.model.get("items"),o=this.model.get("itemTemplate"),r=this;n.each(function(n,a){t=i.getByIndex(n),e=o(void 0,{item:t,index:n}),r.addChildElement(e),$(a).append(e.render())})},updateGrouping:function(){}});_.inherit(ToggleButtonControl,Control),_.extend(ToggleButtonControl.prototype,{createControlModel:function(){return new ToggleButtonModel},createControlView:function(e){return new ToggleButtonView({model:e})}},editorBaseControlMixin);var ToggleButtonModel=ControlModel.extend(_.extend({defaults:_.defaults({value:!1,textOn:"ON",textOff:"OFF",horizontalAlignment:"Left"},ControlModel.prototype.defaults),initialize:function(){ControlModel.prototype.initialize.apply(this,arguments),this.initialize_editorBaseModel()}},editorBaseModelMixin)),ToggleButtonView=ControlView.extend(_.extend({},editorBaseViewMixin,{template:InfinniUI.Template["controls/toggleButton/template/toggleButton.tpl.html"],UI:_.extend({},editorBaseViewMixin.UI,{textOn:".togglebutton-handle-on",textOff:".togglebutton-handle-off",container:".togglebutton-container"}),events:{"click .togglebutton-box":"onClickHandler"},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.call(this),editorBaseViewMixin.initHandlersForProperties.call(this),this.listenTo(this.model,"change:textOn",this.updateTextOn),this.listenTo(this.model,"change:textOff",this.updateTextOff)},updateProperties:function(){ControlView.prototype.updateProperties.call(this),editorBaseViewMixin.updateProperties.call(this),this.updateTextOn(),this.updateTextOff()},updateFocusable:function(){var e=this.model.get("focusable");e?this.ui.container.attr("tabindex",0):this.ui.container.removeAttr("tabindex")},updateTextOn:function(){var e=this.model.get("textOn");this.ui.textOn.html(e||" ")},updateTextOff:function(){var e=this.model.get("textOff");this.ui.textOff.html(e||" ")},render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},getData:function(){var e=this.model;return _.extend({},ControlView.prototype.getData.call(this),editorBaseViewMixin.getData.call(this),{textOn:e.get("textOn"),textOff:e.get("textOff")})},onClickHandler:function(e){var t=this.model;t.set("value",!t.get("value"))},updateValue:function(){var e=this.model.get("value");this.switchClass("toggle",e?"on":"off",this.$el)}}));_.inherit(ToolBarControl,ContainerControl),_.extend(ToolBarControl.prototype,{createControlModel:function(){return new ToolBarModel},createControlView:function(e){return new ToolBarView({model:e})}});var ToolBarModel=ContainerModel.extend({}),ToolBarView=ContainerView.extend({className:"pl-tool-bar",template:InfinniUI.Template["controls/toolBar/template/toolBar.tpl.html"],itemTemplate:InfinniUI.Template["controls/toolBar/template/toolBarItem.tpl.html"],UI:{container:".pl-tool-bar__container"},render:function(){return this.prerenderingActions(),this.renderTemplate(this.template),this.ui.container.append(this.renderItems()),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItems:function(){var e=this.model,t=e.get("items"),n=e.get("itemTemplate");this.removeChildElements();var i=[];return t.forEach(function(e,t){var o=this.itemTemplate(),r=$(o),a=n(null,{index:t,item:e});this.addChildElement(a),r.append(a.render()),i.push(r)},this),i},updateGrouping:function(){}}),TooltipControl=function(){_.superClass(TooltipControl,this)};_.inherit(TooltipControl,Control),_.extend(TooltipControl.prototype,{createControlModel:function(){return new InfinniUI.TooltipModel},createControlView:function(e){return new InfinniUI.TooltipView({model:e})}}),InfinniUI.TooltipControl=TooltipControl,InfinniUI.TooltipModel=ControlModel.extend({}),InfinniUI.TooltipView=ControlView.extend({render:function(){return this.prerenderingActions(),this.renderContent(),this.trigger("render"),this.postrenderingActions(),this},initHandlersForProperties:function(){ControlView.prototype.initHandlersForProperties.apply(this,Array.prototype.slice.call(arguments)),this.listenTo(this.model,"change:content",this.updateContent)},updateContent:function(){ +this.renderContent()},renderContent:function(){var e=this.model,t=e.get("content");this.$el.html(t.render())}}),_.inherit(ViewControl,ContainerControl),_.extend(ViewControl.prototype,{createControlModel:function(){return new ViewModel},createControlView:function(e){return new ViewView({model:e})}});var DialogResult={none:0,accepted:1,canceled:2};window.InfinniUI.DialogResult=DialogResult;var ViewModel=ContainerModel.extend({defaults:_.defaults({dialogResult:DialogResult.none,isApplication:!1,closeButtonVisibility:!0},ContainerModel.prototype.defaults),initialize:function(){ContainerModel.prototype.initialize.apply(this),this.set("scripts",new Collection([],"name")),this.set("parameters",new Collection([],"name")),this.set("dataSources",new Collection([],"name"))}}),ViewView=ContainerView.extend({className:"pl-view",initialize:function(e){ContainerView.prototype.initialize.call(this,e)},render:function(){return this.prerenderingActions(),this.$el.empty(),this.renderItemsContents(),this.updateProperties(),this.trigger("render"),this.postrenderingActions(),this},renderItemsContents:function(){var e,t=this,n=this.model.get("items"),i=this.model.get("itemTemplate");n.forEach(function(n,o){e=i(void 0,{item:n,index:o}),e&&t.$el.append(e.render())})},updateGrouping:function(){}}),ViewPanelControl=function(){_.superClass(ViewPanelControl,this)};_.inherit(ViewPanelControl,Control),ViewPanelControl.prototype.createControlModel=function(){return new ViewPanelModel},ViewPanelControl.prototype.createControlView=function(e){return new ViewPanelView({model:e})};var ViewPanelModel=ControlModel.extend({defaults:_.defaults({layout:null},ControlModel.prototype.defaults),initialize:function(){var e=this;ControlModel.prototype.initialize.apply(this),this.once("change:layout",function(t,n){n&&n.onLoaded&&e.subscribeOnLoaded()})},subscribeOnLoaded:function(){var e=this,t=this.get("layout");t.onLoaded(function(){e.set("isLoaded",!0)})}}),ViewPanelView=ControlView.extend({className:"pl-view-panel",initialize:function(){ControlView.prototype.initialize.apply(this),this.listenTo(this.model,"change:layout",this.onChangeLayoutHandler)},onChangeLayoutHandler:function(e,t){this.$el.empty(),t&&this.$el.append(t.render())},render:function(){this.prerenderingActions();var e=this.model.get("layout");return e&&this.$el.append(e.render()),this.updateProperties(),this.trigger("render"),this.postrenderingActions(!1),this}}),DataSourceValidationNotifierMixin={initNotifyValidation:function(e){e.onErrorValidator(this.notifyOnValidationError.bind(this))},notifyOnValidationError:function(e,t){var n=t.value;"undefined"!=typeof n&&null!==n&&!n.IsValid&&Array.isArray(n.Items)&&n.Items.forEach(function(e){var t=window.InfinniUI.global.messageBus;t.send(messageTypes.onNotifyUser,{item:e,messageText:e.Message,messageType:"error"})})}},BaseDataSource=Backbone.Model.extend({defaults:{name:null,idProperty:"_id",identifyingMode:"byId",view:null,isDataReady:!1,dataProvider:null,model:null,modifiedItems:{},itemsById:{},fillCreatedItem:!0,suspendingList:null,waitingOnUpdateItemsHandlers:null,errorValidator:null,isRequestInProcess:!1,isLazy:!0,isWaiting:!1,resolvePriority:0,newItemsHandler:null,isNumRegEx:/^\d/},initialize:function(){var e=this.get("view"),t={items:null,selectedItem:null};if(this.initDataProvider(),!e)throw"BaseDataSource.initialize: При создании объекта не была задана view.";this.set("suspendingList",[]),this.set("waitingOnUpdateItemsHandlers",[]),this.set("model",new TreeModel(e.getContext(),this,t)),_.extend(this,BaseDataSource.identifyingStrategy.byId)},initDataProvider:function(){throw"BaseDataSource.initDataProvider В потомке BaseDataSource не задан провайдер данных."},onPropertyChanged:function(e,t,n){"function"==typeof e&&(n=t,t=e,e="*"),e="."==e.charAt(0)?e.substr(1):""==e?"items":"items."+e,this.get("model").onPropertyChanged(e,function(e,n){var i=n.property;i="items."==i.substr(0,6)?i.substr(6):"items"==i?"":"."+i,n.property=i,t(e,n)},n)},onSelectedItemChanged:function(e,t){var n=this;this.get("model").onPropertyChanged("selectedItem",function(t,i){var o=n._getArgumentTemplate();o.value=i.newValue,e(t,o)},t)},onErrorValidator:function(e){this.on("onErrorValidator",e)},onItemSaved:function(e){this.on("onItemSaved",e)},onItemCreated:function(e){this.on("onItemCreated",e)},onItemsUpdated:function(e){this.on("onItemsUpdated",e)},onItemsUpdatedOnce:function(e){this.once("onItemsUpdated",e)},onItemDeleted:function(e){this.on("onItemDeleted",e)},onProviderError:function(e){this.on("onProviderError",e)},getName:function(){return this.get("name")},setName:function(e){this.set("name",e),this.name=e},getView:function(){return this.get("view")},getProperty:function(e){var t,n=e.charAt(0);if(this.get("isNumRegEx").test(n))e="items."+e;else if(""==n)e="items";else if("$"==n){if(t=this._indexOfSelectedItem(),t==-1)return;e="items."+t+e.substr(1)}else if("."==n)e=e.substr(1);else{if(t=this._indexOfSelectedItem(),t==-1)return;e="items."+t+"."+e}return this.get("model").getProperty(e)},setProperty:function(e,t){var n,i,o,r=e.split(".");if("$"==r[0]){if(i=this._indexOfSelectedItem(),i==-1)return;e=i+e.substr(1),r[0]=i.toString()}if(n=e.charAt(0),1==r.length)if(""==r[0])this._setItems(t);else if(this.get("isNumRegEx").test(r[0]))this._changeItem(r[0],t);else{if(i=this._indexOfSelectedItem(),i==-1)return;e="items."+i+"."+e,o=this.get("model").setProperty(e,t),o&&this._includeItemToModifiedSetByIndex(i)}else if("."==n)e=e.substr(1),this.get("model").setProperty(e,t);else if(this.get("isNumRegEx").test(n))e="items."+e,o=this.get("model").setProperty(e,t),o&&this._includeItemToModifiedSetByIndex(parseInt(r[0]));else{if(i=this._indexOfSelectedItem(),i==-1)return;e="items."+i+"."+e,o=this.get("model").setProperty(e,t),o&&this._includeItemToModifiedSetByIndex(i)}},_setItems:function(e){this._detectIdentifyingMode(e);var t;this.set("isDataReady",!0),this.get("model").setProperty("items",e),this._clearModifiedSet(),e&&e.length>0?(t=this._indexItemsById(e),this.set("itemsById",t),this._restoreSelectedItem()||this.setSelectedItem(e[0])):this.setSelectedItem(null)},_restoreSelectedItem:function(){var e=window.InfinniUI.global.logger;e.warn({message:"BaseDataSource._restoreSelectedItem: not overrided by strategy",source:this})},getSelectedItem:function(){return this.get("model").getProperty("selectedItem")},setSelectedItem:function(e,t,n){var i=window.InfinniUI.global.logger;i.warn({message:"BaseDataSource.setSelectedItem: not overrided by strategy",source:this})},_notifyAboutSelectedItem:function(e,t){var n=this.getContext(),i=this._getArgumentTemplate();i.value=e,t&&t(n,i)},_tuneMirroringOfModel:function(e){e!=-1?this.get("model").setMirroring("items.$","items."+e):this.get("model").setMirroring(null,null)},getIdProperty:function(){return this.get("idProperty")},setIdProperty:function(e){this.set("idProperty",e)},getFillCreatedItem:function(){return this.get("fillCreatedItem")},setFillCreatedItem:function(e){this.set("fillCreatedItem",e)},suspendUpdate:function(e){var t=e||"default",n=this.get("suspendingList");n.indexOf(t)===-1&&(n=n.slice(0),n.push(t),this.set("suspendingList",n))},resumeUpdate:function(e){var t=e||"default",n=this.get("suspendingList"),i=n.indexOf(t);i!==-1&&(n=n.slice(0),n.splice(i,1),this.set("suspendingList",n),!this.isUpdateSuspended()&&this.get("waitingOnUpdateItemsHandlers").length>0&&this.updateItems())},isUpdateSuspended:function(){var e=this.get("suspendingList");return e.length>0},isModifiedItems:function(){return this.isModified()},isModified:function(e){if(0==arguments.length)return _.size(this.get("modifiedItems"))>0;if(null===e||void 0===e)return!1;var t=this.idOfItem(e);return t in this.get("modifiedItems")},_includeItemToModifiedSetByIndex:function(e){var t;t=this.getItems()[e],this._includeItemToModifiedSet(t)},_includeItemToModifiedSet:function(e){var t=window.InfinniUI.global.logger;t.warn({message:"BaseDataSource._includeItemToModifiedSet: not overrided by strategy",source:this})},_excludeItemFromModifiedSet:function(e){var t=window.InfinniUI.global.logger;t.warn({message:"BaseDataSource._excludeItemFromModifiedSet: not overrided by strategy",source:this})},_clearModifiedSet:function(){this.set("modifiedItems",{})},_checkPropertyName:function(e){var t=!0;try{if(e&&e.length>0&&(t=e.match(/^[\$#@\d]+/)),!t)throw new Error('Wrong property name "'+e+'"')}catch(n){console.debug(n)}},_changeItem:function(e,t){var n=this.get("model").getProperty("items."+e),i=n==this.getSelectedItem(),o=this.get("idProperty"),r=this.get("itemsById");t!=n&&(this._excludeItemFromModifiedSet(n),delete r[n[o]],this.get("model").setProperty("items."+e,t),this._includeItemToModifiedSet(t),r[t[o]]=t,this.set("itemsById",r),i&&this.get("model").setProperty("selectedItem",t))},tryInitData:function(){this.get("isDataReady")||this.get("isRequestInProcess")||this.updateItems()},saveItem:function(e,t,n){var i,o=this.get("dataProvider"),r=(window.InfinniUI.global.logger,this),a=this._compensateOnErrorOfProviderHandler(n);return this.isModified(e)?(i=this.getValidationResult(e),i.IsValid?void o.saveItem(e,function(i){if("IsValid"in i&&i.IsValid!==!0){var o=r._getValidationResult(i);r._notifyAboutValidation(o,"error"),r._executeCallback(n,{item:e,result:o,originalResponse:i})}else r._excludeItemFromModifiedSet(e),r._notifyAboutItemSaved({item:e,result:i.data},"modified"),r._executeCallback(t,{item:e,result:r._getValidationResult(i),originalResponse:i})},function(t){var n=r._getValidationResult(t);r._notifyAboutValidation(n,"error"),r._executeCallback(a,{item:e,result:n,originalResponse:t})}):(this._notifyAboutValidation(i,"error"),void this._executeCallback(n,{item:e,result:i}))):(this._notifyAboutItemSaved({item:e,result:null},"notModified"),void r._executeCallback(t,{item:e,result:{IsValid:!0}}))},_getValidationResult:function(e){return e.data&&e.data.responseJSON&&e.data.responseJSON.Result?e.data.responseJSON.Result.ValidationResult:e.data&&e.data.Result&&e.data.Result.ValidationResult},_executeCallback:function(e,t){e&&e(this.getContext(),t)},_notifyAboutItemSaved:function(e,t){var n=this.getContext(),i=this._getArgumentTemplate();i.value=e,i.result=t,this.trigger("onItemSaved",n,i)},deleteItem:function(e,t,n){var i=this.get("dataProvider"),o=this,r=this.idOfItem(e),a=void 0!==this.get("itemsById")[r],l=this._compensateOnErrorOfProviderHandler(n);return null==e||void 0!==r&&!a?void this._notifyAboutMissingDeletedItem(e,n):(this.beforeDeleteItem(e),void i.deleteItem(e,function(i){if("IsValid"in i&&i.IsValid!==!0){var r=o._getValidationResult(i);o._notifyAboutValidation(r,"error"),o._executeCallback(n,{item:e,result:r})}else o._handleDeletedItem(e,t)},function(t){var n=o._getValidationResult(t);o._notifyAboutValidation(n,"error"),o._executeCallback(l,{item:e,result:n})}))},beforeDeleteItem:function(e){},_handleDeletedItem:function(e,t){var n=window.InfinniUI.global.logger;n.warn({message:"BaseDataSource._handleDeletedItem: not overrided by strategy",source:this})},_notifyAboutItemDeleted:function(e,t){var n=this.getContext(),i=this._getArgumentTemplate();i.value=e,t&&t(n,i),this.trigger("onItemDeleted",n,i)},_notifyAboutMissingDeletedItem:function(e,t){var n=this.getContext(),i=this._getArgumentTemplate();i.value=e,i.error={message:"Нельзя удалить элемент, которого нет текущем наборе источника данных"},t&&t(n,i)},isDataReady:function(){return this.get("isDataReady")},getItems:function(){var e=window.InfinniUI.global.logger;return this.isDataReady()||e.warn({message:"BaseDataSource: Попытка получить данные источника данных ("+this.get("name")+"), до того как он был проинициализирован данными",source:this}),this.get("model").getProperty("items")},updateItems:function(e,t){if(this.isUpdateSuspended()){var n=this.get("waitingOnUpdateItemsHandlers");n.push({onSuccess:e,onError:t})}else{var i=this.get("dataProvider"),o=this;t=this._compensateOnErrorOfProviderHandler(t),this.set("isRequestInProcess",!0),i.getItems(function(n){o._handleSuccessUpdateItemsInProvider(n,e,t)},t)}},_compensateOnErrorOfProviderHandler:function(e){var t=this;return function(){"function"==typeof e?e.apply(void 0,arguments):t.trigger("onProviderError",arguments)}},_handleSuccessUpdateItemsInProvider:function(e,t,n){var i=this,o=i.get("isWaiting"),r=function(){i.set("isRequestInProcess",!1),i._handleUpdatedItemsData(e.data,t,n)};o?i.once("change:isWaiting",function(){r()}):r()},_onErrorProviderUpdateItemsHandle:function(){},setIsWaiting:function(e){this.set("isWaiting",e)},_handleUpdatedItemsData:function(e,t,n){this.get("newItemsHandler")&&(e=this.get("newItemsHandler")(e)),this._setItems(e),this._notifyAboutItemsUpdated(e,t,n)},_notifyAboutItemsUpdated:function(e,t,n){for(var i=this.getContext(),o={value:e,source:this},r=this.get("waitingOnUpdateItemsHandlers"),a=0,l=r.length;a0?!$.isPlainObject(e[0])||this.getIdProperty()in e[0]?(this.set("identifyingMode","byId"),_.extend(this,BaseDataSource.identifyingStrategy.byId)):(this.set("identifyingMode","byLink"),_.extend(this,BaseDataSource.identifyingStrategy.byLink)):(this.set("identifyingMode","byId"),_.extend(this,BaseDataSource.identifyingStrategy.byId))},_getIdentifyingMode:function(){return this.get("identifyingMode")}});BaseDataSource.identifyingStrategy={byId:{_restoreSelectedItem:function(){var e=this.getSelectedItem(),t=this.idOfItem(e);if(null!=t){var n=this.get("itemsById"),i=n[t];if(null!=i)return this.setSelectedItem(i),!0}return!1},setSelectedItem:function(e,t,n){var i,o=this.getSelectedItem(),r=this.get("itemsById"),a=this.idOfItem(e);if("undefined"==typeof e&&(e=null),e!=o){if(null!==e&&!r[a]){if(n)return void n(this.getContext(),{error:"BaseDataSource.setSelectedItem() Попытка выбрать элемент в источнике, которого нет среди элементов этого источника."});throw"BaseDataSource.setSelectedItem() Попытка выбрать элемент в источнике, которого нет среди элементов этого источника."}this.get("model").setProperty("selectedItem",e),i=this._indexOfItem(r[a]),this._tuneMirroringOfModel(i),this._notifyAboutSelectedItem(e,t)}},_includeItemToModifiedSet:function(e){var t=this.idOfItem(e);this.get("modifiedItems")[t]=e},_excludeItemFromModifiedSet:function(e){var t=this.idOfItem(e);delete this.get("modifiedItems")[t]},_handleDeletedItem:function(e,t){for(var n=this.getItems(),i=this.get("idProperty"),o=this.idOfItem(e),r=this.getSelectedItem(),a=0,l=n.length,s=!1;a=0&&(n.splice(o,1),this._excludeItemFromModifiedSet(e),i&&i==e&&this.setSelectedItem(null)),this._notifyAboutItemDeleted(e,t)}}},window.InfinniUI.BaseDataSource=BaseDataSource;var RestDataSource=BaseDataSource.extend({defaults:_.defaults({updatingItemsConverter:null},BaseDataSource.prototype.defaults),initialize:function(){BaseDataSource.prototype.initialize.apply(this,Array.prototype.slice.call(arguments));var e=this.get("model");e.urlParams={get:{method:"get",origin:null,path:"",data:{},params:{}},set:{method:"post",origin:null,path:"",data:{},params:{}},"delete":{method:"delete",origin:null,path:"",data:{},params:{}}},this.initUrlParamsHandlers()},initDataProvider:function(){var e=window.InfinniUI.providerRegister.build("RestDataSource");this.set("dataProvider",e)},initUrlParamsHandlers:function(){var e=this;this.get("model").onPropertyChanged("urlParams.get.*",function(t,n){var i,o=e.get("dataProvider"),r=e.getGettingUrlParams();o.setOrigin("get",r.origin),i=e._templateParamsInStr(r.path,r.params),o.setPath("get",i),i=e._templateParamsInObject(r.data,r.params),o.setData("get",i),o.setMethod("get",r.method),(e.get("isDataReady")||e.get("isRequestInProcess")||e.get("waitingOnUpdateItemsHandlers").length>0)&&e.updateItems()}),this.get("model").onPropertyChanged("urlParams.set.*",function(t,n){var i,o=e.get("dataProvider"),r=e.getSettingUrlParams();o.setOrigin("set",r.origin),i=e._templateParamsInStr(r.path,r.params),o.setPath("set",i),i=e._templateParamsInObject(r.data,r.params),o.setData("set",i),o.setMethod("set",r.method)}),this.get("model").onPropertyChanged("urlParams.delete.*",function(t,n){var i,o=e.get("dataProvider"),r=e.getDeletingUrlParams();o.setOrigin("delete",r.origin),i=e._templateParamsInStr(r.path,r.params),o.setPath("delete",i),i=e._templateParamsInObject(r.data,r.params),o.setData("delete",i),o.setMethod("delete",r.method)})},updateItems:function(){this._checkGettingUrlParamsReady()?(BaseDataSource.prototype.updateItems.apply(this,Array.prototype.slice.call(arguments)),this.resumeUpdate("urlGettingParamsNotReady")):(this.suspendUpdate("urlGettingParamsNotReady"),BaseDataSource.prototype.updateItems.apply(this,Array.prototype.slice.call(arguments)))},getGettingUrlParams:function(e){return e=0==arguments.length?"urlParams.get":""==e?"urlParams.get":"urlParams.get."+e,this.get("model").getProperty(e)},setGettingUrlParams:function(e,t){1==arguments.length?(t=e,e="urlParams.get"):e=""==e?"urlParams.get":"urlParams.get."+e,this.get("model").setProperty(e,t)},getSettingUrlParams:function(e){return e=0==arguments.length?"urlParams.set":""==e?"urlParams.set":"urlParams.set."+e,this.get("model").getProperty(e)},setSettingUrlParams:function(e,t){1==arguments.length?(t=e,e="urlParams.set"):e=""==e?"urlParams.set":"urlParams.set."+e,this.get("model").setProperty(e,t)},getDeletingUrlParams:function(e){return e=0==arguments.length?"urlParams.delete":""==e?"urlParams.delete":"urlParams.delete."+e,this.get("model").getProperty(e)},setDeletingUrlParams:function(e,t){1==arguments.length?(t=e,e="urlParams.delete"):e=""==e?"urlParams.delete":"urlParams.delete."+e,this.get("model").setProperty(e,t)},_checkGettingUrlParamsReady:function(){var e,t,n,i,o,r=[];if(!this._checkUrlParamsReady(this.getGettingUrlParams()))return!1;e=this.getGettingUrlParams("path"),t=this._findSubstitutionParams(e),r=r.concat(t),n=this.getGettingUrlParams("data"),e=JSON.stringify(n),t=this._findSubstitutionParams(e),r=r.concat(t),i=this.getGettingUrlParams("params");for(var a=0,l=r.length;a/g,function(e,n){return t.push(n),e}),t},_templateParamsInStr:function(e,t){return e&&t?e.replace(/<%([\s\S]+?)%>/g,function(e,n){return t[n]}):e},_templateParamsInObject:function(e,t){if(!e||!t)return e;var n=JSON.stringify(e),i=this._templateParamsInStr(n,t);return JSON.parse(i)},getUpdatingItemsConverter:function(){return this.get("updatingItemsConverter")},setUpdatingItemsConverter:function(e){this.set("updatingItemsConverter",e)},_handleUpdatedItemsData:function(e,t,n){var i,o=this.getUpdatingItemsConverter();i=o?o(e):e,BaseDataSource.prototype._handleUpdatedItemsData.call(this,i,t,n)}});window.InfinniUI.RestDataSource=RestDataSource;var DocumentDataSource=RestDataSource.extend({defaults:_.defaults({documentId:null},RestDataSource.prototype.defaults),initialize:function(){RestDataSource.prototype.initialize.apply(this,Array.prototype.slice.call(arguments));var e=this.get("model");e.setProperty("pageNumber",0),e.setProperty("pageSize",15),e.setProperty("filterParams",{}),this.setUpdatingItemsConverter(function(t){return e.setProperty("totalCount",t.Result.Count),e.setProperty("additionalResult",t.Result.AdditionalResult),t.Result.Items}),this.initHandlers()},initHandlers:function(){var e=this.get("model"),t=this,n=_.bind(this.updateGettingUrlParams,this);e.onPropertyChanged("documentId",function(){t.updateGettingUrlParams(),t.updateSettingUrlParams(),t.updateDeletingUrlParams()}),e.onPropertyChanged("filter",n),e.onPropertyChanged("filterParams.*",n),e.onPropertyChanged("pageNumber",n),e.onPropertyChanged("pageSize",n),e.onPropertyChanged("search",n),e.onPropertyChanged("select",n),e.onPropertyChanged("order",n),e.onPropertyChanged("needTotalCount",n),this.updateGettingUrlParams(),this.updateSettingUrlParams(),this.updateDeletingUrlParams()},updateGettingUrlParams:function(){var e=this.get("model"),t={method:"get",origin:InfinniUI.config.serverUrl,path:"/documents/"+this.get("model").getProperty("documentId"),data:{},params:{}},n=e.getProperty("filter"),i=e.getProperty("filterParams"),o=e.getProperty("pageNumber"),r=e.getProperty("pageSize"),a=e.getProperty("search"),l=e.getProperty("select"),s=e.getProperty("order"),u=e.getProperty("needTotalCount");n&&(t.data.filter=n,i&&_.extend(t.params,i)),r&&(o=o||0,t.data.skip=o*r,t.data.take=r),a&&(t.data.search=a),l&&(t.data.select=l),s&&(t.data.order=s),u&&(t.data.count=u),this.setGettingUrlParams(t)},updateSettingUrlParams:function(){var e=(this.get("model"),{method:"post",origin:InfinniUI.config.serverUrl,path:"/documents/"+this.get("model").getProperty("documentId"),data:{},params:{}});this.setSettingUrlParams(e)},updateDeletingUrlParams:function(){var e=(this.get("model"),{method:"delete",origin:InfinniUI.config.serverUrl,path:"/documents/"+this.get("model").getProperty("documentId")+"/<%id%>",data:{},params:{}});this.setDeletingUrlParams(e)},initDataProvider:function(){var e=window.InfinniUI.providerRegister.build("DocumentDataSource");this.set("dataProvider",e)},getDocumentId:function(){return this.get("model").getProperty("documentId")},setDocumentId:function(e){this.get("model").setProperty("documentId",e)},getFilter:function(){return this.get("model").getProperty("filter")},setFilter:function(e){this.get("model").setProperty("filter",e)},getFilterParams:function(e){return e=0==arguments.length?"filterParams":""==e?"filterParams":"filterParams."+e,this.get("model").getProperty(e)},setFilterParams:function(e,t){1==arguments.length?(t=e,e="filterParams"):e=""==e?"filterParams":"filterParams."+e,this.get("model").setProperty(e,t)},setIdFilter:function(e){this.setFilter("eq("+this.getIdProperty()+","+this.quoteValue(e)+")")},getPageNumber:function(){return this.get("model").getProperty("pageNumber")},setPageNumber:function(e){this.get("model").setProperty("pageNumber",e)},getPageSize:function(){return this.get("model").getProperty("pageSize")},setPageSize:function(e){this.get("model").setProperty("pageSize",e)},getSearch:function(){return this.get("model").getProperty("search")},setSearch:function(e){this.get("model").setProperty("search",e)},getSelect:function(){return this.get("model").getProperty("select")},setSelect:function(e){this.get("model").setProperty("select",e)},getOrder:function(){return this.get("model").getProperty("order")},setOrder:function(e){this.get("model").setProperty("order",e)},getTotalCount:function(){return this.get("model").getProperty("totalCount")},getNeedTotalCount:function(){return this.get("model").getProperty("needTotalCount")},setNeedTotalCount:function(e){this.get("model").setProperty("needTotalCount",e)},beforeDeleteItem:function(e){var t=this.idOfItem(e);void 0!==t&&this.setDeletingUrlParams("params.id",t)},quoteValue:function(e){var t="'";return _.isString(e)?t+e+t:e}});window.InfinniUI.DocumentDataSource=DocumentDataSource;var BaseDataSourceBuilder=function(){};_.extend(BaseDataSourceBuilder.prototype,{build:function(e,t){var n=this.createDataSource(t.parentView);return n.suspendUpdate("tuningInSourceBuilder"),this.applyMetadata(t.builder,t.parentView,t.metadata,n),this.applySuspended(n,t.suspended),n.resumeUpdate("tuningInSourceBuilder"),n},applySuspended:function(e,t){if(t)for(var n in t)t.hasOwnProperty(n)&&e.getName()===n&&e.suspendUpdate(t[n])},applyMetadata:function(e,t,n,i){var o=n.IdProperty;o&&i.setIdProperty(o),"SuspendUpdate"in n&&i.suspendUpdate(n.SuspendUpdate),i.setName(n.Name),i.setFillCreatedItem(n.FillCreatedItem),"IsLazy"in n&&i.setIsLazy(n.IsLazy),"ResolvePriority"in n&&i.setResolvePriority(n.ResolvePriority),_.isObject(n.CustomProperties)&&this.initCustomProperties(i,n.CustomProperties),this.initValidation(t,i,n),this.initNotifyValidation(i),this.initScriptsHandlers(t,n,i),this.initFileProvider(i)},createDataSource:function(e){throw"BaseDataSourceBuilder.createDataSource В потомке BaseDataSourceBuilder не переопределен метод createDataSource."},initCustomProperties:function(e,t){_.each(t,function(t,n){e.setProperty("."+n,t)})},initValidation:function(e,t,n){n.ValidationErrors&&t.setErrorValidator(function(t,i){return new ScriptExecutor(e).executeScript(n.ValidationErrors.Name||n.ValidationErrors,i)})},initScriptsHandlers:function(e,t,n){e&&(t.OnSelectedItemChanged&&n.onSelectedItemChanged(function(n,i){new ScriptExecutor(e).executeScript(t.OnSelectedItemChanged.Name||t.OnSelectedItemChanged,i)}),t.OnItemsUpdated&&n.onItemsUpdated(function(n,i){new ScriptExecutor(e).executeScript(t.OnItemsUpdated.Name||t.OnItemsUpdated,i)}),t.OnPropertyChanged&&n.onPropertyChanged(function(n,i){new ScriptExecutor(e).executeScript(t.OnPropertyChanged.Name||t.OnPropertyChanged,i)}),t.OnItemDeleted&&n.onItemDeleted(function(){new ScriptExecutor(e).executeScript(t.OnItemDeleted.Name||t.OnItemDeleted)}),t.OnErrorValidator&&n.onErrorValidator(function(){new ScriptExecutor(e).executeScript(t.OnErrorValidator.Name||t.OnErrorValidator)}))},buildBindingBuilder:function(e){return function(t){return e.builder.buildBinding(t,{parentView:e.parentView,basePathOfProperty:e.basePathOfProperty})}},initFileProvider:function(e){var t=InfinniUI.config.serverUrl,n=new DocumentUploadQueryConstructor(t),i=new DocumentFileProvider(n);e.setFileProvider(i)}}),_.extend(BaseDataSourceBuilder.prototype,DataSourceValidationNotifierMixin),window.InfinniUI.BaseDataSourceBuilder=BaseDataSourceBuilder;var RestDataSourceBuilder=function(){_.superClass(RestDataSourceBuilder,this)};_.inherit(RestDataSourceBuilder,BaseDataSourceBuilder),_.extend(RestDataSourceBuilder.prototype,{createDataSource:function(e){return new RestDataSource({view:e})},applyMetadata:function(e,t,n,i){BaseDataSourceBuilder.prototype.applyMetadata.call(this,e,t,n,i);var o;this.initProviderErrorHandling(i),"GettingParams"in n&&(o=this.extractUrlParams(n.GettingParams,".urlParams.get.params"),i.setGettingUrlParams(o),this.bindParams(n.GettingParams,i,t,".urlParams.get.params",e)),"SettingParams"in n&&(o=this.extractUrlParams(n.SettingParams,".urlParams.set.params"),i.setSettingUrlParams(o),this.bindParams(n.SettingParams,i,t,".urlParams.set.params",e)),"DeletingParams"in n&&(o=this.extractUrlParams(n.DeletingParams,".urlParams.delet.params"),i.setDeletingUrlParams(o),this.bindParams(n.DeletingParams,i,t,".urlParams.delet.params",e)),"UpdatingItemsConverter"in n&&i.setUpdatingItemsConverter(function(e){return new ScriptExecutor(t).executeScript(n.UpdatingItemsConverter.Name||n.UpdatingItemsConverter,{value:e,source:i})})},extractUrlParams:function(e,t){var n={};return"Origin"in e?n.origin=e.Origin:n.origin=InfinniUI.config.serverUrl,"Path"in e&&(n.path=e.Path),"Data"in e&&(n.data=e.Data),"Method"in e&&(n.method=e.Method),n.params={},n},bindParams:function(e,t,n,i,o){if("Params"in e){var r=e.Params;for(var a in r)this.initBindingToProperty(r[a],t,n,i+"."+a,o)}},initBindingToProperty:function(e,t,n,i,o){if("object"!=typeof e)void 0!==e&&t.setProperty(i,e);else{var r={parent:n,parentView:n},a=o.buildBinding(e,r);a.setMode(InfinniUI.BindingModes.toElement),a.bindElement(t,i)}},initProviderErrorHandling:function(e){e.onProviderError(function(){var e=window.InfinniUI.global.messageBus;e.send(messageTypes.onNotifyUser,{messageText:"Ошибка на сервере",messageType:"error"})})}}),window.InfinniUI.RestDataSourceBuilder=RestDataSourceBuilder;var DocumentDataSourceBuilder=function(){_.superClass(DocumentDataSourceBuilder,this)};_.inherit(DocumentDataSourceBuilder,BaseDataSourceBuilder), +_.extend(DocumentDataSourceBuilder.prototype,{applyMetadata:function(e,t,n,i){if(BaseDataSourceBuilder.prototype.applyMetadata.call(this,e,t,n,i),i.setDocumentId(n.DocumentId),"PageNumber"in n&&i.setPageNumber(n.PageNumber),"PageSize"in n&&i.setPageSize(n.PageSize),"Filter"in n&&i.setFilter(n.Filter),"FilterParams"in n){var o=n.FilterParams;for(var r in o)this.initBindingToProperty(o[r],i,t,".filterParams."+r,e)}"Search"in n&&i.setSearch(n.Search),"Select"in n&&i.setSelect(n.Select),"Order"in n&&i.setOrder(n.Order),"NeedTotalCount"in n&&i.setNeedTotalCount(n.NeedTotalCount)},createDataSource:function(e){return new DocumentDataSource({view:e})},initBindingToProperty:RestDataSourceBuilder.prototype.initBindingToProperty}),window.InfinniUI.DocumentDataSourceBuilder=DocumentDataSourceBuilder;var Element=function(e,t){this.parent=e,this.control=this.createControl(t),this.state={Enabled:!0},this.childElements=[]};Object.defineProperties(Element.prototype,{name:{get:function(){return this.getName()}}}),_.extend(Element.prototype,{createControl:function(e){throw"Не перегружен абстрактный метод Element.createControl"},setParent:function(e){this.parent=e},getParent:function(){return this.parent},getChildElements:function(){return this.childElements},findAllChildrenByType:function(e){function t(){return this.constructor.name===e}function n(t){return t.findAllChildrenByType(e)}return this._findAllChildren(t,n)},findAllChildrenByName:function(e){function t(){return this.getName()===e}function n(t){return t.findAllChildrenByName(e)}return this._findAllChildren(t,n)},_findAllChildren:function(e,t){var n=this.getChildElements(),i=[];return Array.isArray(n)&&n.forEach(function(n){e.call(n)&&i.push(n),Array.prototype.push.apply(i,t(n))}),i},getView:function(){return this.parentView||(this.parent&&this.parent.isView?this.parentView=this.parent:this.parent&&this.parent.getView?this.parentView=this.parent.getView():this.parentView=null),this.parentView},getName:function(){return this.control.get("name")},setName:function(e){if(this.getName())throw"name already exists";"string"==typeof e&&this.control.set("name",e)},getProperty:function(e){var t="get"+this._upperFirstSymbol(e);if("function"==typeof this[t])return this[t]();throw"expect that "+t+" is getter function"},setProperty:function(e,t){var n,i="set"+this._upperFirstSymbol(e);if("function"==typeof this[i])this[i](t);else{if(!this._isCollectionProperty(e))throw"expect that "+i+" is setter function";n="get"+this._upperFirstSymbol(e),this[n]().set(t)}},_isCollectionProperty:function(e){var t="get"+this._upperFirstSymbol(e);return"function"==typeof this[t]&&this[t]()instanceof Collection},onPropertyChanged:function(e,t){var n="on"+this._upperFirstSymbol(e)+"Changed";"function"==typeof this[n]?this[n](t):this.control.on("change:"+e,function(n,i){var o=this.getView(),r=o?o.getContext():void 0,a={property:e,oldValue:n.previous(e),newValue:i};t(r,a)}.bind(this))},getText:function(){return this.control.get("text")},setText:function(e){"undefined"!=typeof e&&this.control.set("text",e)},getEnabled:function(){return this.control.get("enabled")},setEnabled:function(e){if("boolean"==typeof e){this.setState("Enabled",e);var t=this.control.get("parentEnabled"),n=this.control.get("enabled");e=t&&e,e!==n&&(this.control.set("enabled",e),this.setParentEnabledOnChild(e))}},setParentEnabledOnChild:function(e){var t=this.getChildElements();if(_.isEmpty(t)===!1)for(var n=0,i=t.length;ni)&&(t="Значение должно быть от "+n+" до "+i):ei&&(t="Значение должно быть меьше "+i):t="Значение должно быть числом",t)},NumericBox.prototype.convertValue=function(e){var t=null===e||""===e||"undefined"==typeof e?null:+e;return _.isNumber(t)?t:null},NumericBox.prototype.getStartValue=function(){return this.control.get("startValue")},window.InfinniUI.NumericBoxBuilder=NumericBoxBuilder,_.inherit(NumericBoxBuilder,TextEditorBaseBuilder),NumericBoxBuilder.prototype.createElement=function(e){return new NumericBox(e.parent)},NumericBoxBuilder.prototype.applyMetadata=function(e){TextEditorBaseBuilder.prototype.applyMetadata.call(this,e);var t=e.element,n=e.metadata;t.setMinValue(n.MinValue),t.setMaxValue(n.MaxValue),t.setIncrement(n.Increment),t.setStartValue(n.StartValue)},window.InfinniUI.Panel=Panel,_.inherit(Panel,Container),Panel.prototype.getCollapsible=function(){return this.control.get("collapsible")},Panel.prototype.setCollapsible=function(e){"undefined"!=typeof e&&this.control.set("collapsible",!!e)},Panel.prototype.getCollapsed=function(){return this.control.get("collapsed")},Panel.prototype.setCollapsed=function(e){"undefined"!=typeof e&&this.control.set("collapsed",!!e)},Panel.prototype.getHeaderTemplate=function(){return this.control.get("headerTemplate")},Panel.prototype.setHeaderTemplate=function(e){this.control.set("headerTemplate",e)},Panel.prototype.getHeader=function(){return this.control.get("header")},Panel.prototype.setHeader=function(e){this.control.set("header",e)},Panel.prototype.getCollapsibleArea=function(){return this.control.get("collapsibleArea")},Panel.prototype.setCollapsibleArea=function(e){this.control.set("collapsibleArea",e)},Panel.prototype.onExpanding=function(e){this.control.on("expanding",e)},Panel.prototype.onExpanded=function(e){this.control.on("expanded",e)},Panel.prototype.onCollapsing=function(e){this.control.on("collapsing",e)},Panel.prototype.onCollapsed=function(e){this.control.on("collapsed",e)},Panel.prototype.createControl=function(){return new PanelControl},window.InfinniUI.PanelBuilder=PanelBuilder,_.inherit(PanelBuilder,ContainerBuilder),_.extend(PanelBuilder.prototype,{createElement:function(e){return new Panel(e.parent)},applyMetadata:function(e){var t=e.metadata,n=e.element,i=ContainerBuilder.prototype.applyMetadata.call(this,e);n.setCollapsible(t.Collapsible),n.setCollapsed(t.Collapsed),n.setCollapsibleArea(t.CollapsibleArea);var o=this.buildHeaderTemplate(t.HeaderTemplate,e);if(n.setHeaderTemplate(o),t.Header&&"object"==typeof t.Header){var r=e.builder,a=r.buildType("PropertyBinding",t.Header,{parent:n,parentView:e.parentView,basePathOfProperty:e.basePathOfProperty});a.bindElement(n,"header")}else n.setHeader(t.Header);return this.initEventHandler(e),i},initEventHandler:function(e){function t(){return new ScriptExecutor(e.parentView)}var n=e.metadata,i=e.element;n.OnExpanding&&i.onExpanding(function(e,i){return t().executeScript(n.OnExpanding.Name||n.OnExpanding,i)}),n.OnExpanded&&i.onExpanded(function(e,i){return t().executeScript(n.OnExpanded.Name||n.OnExpanded,i)}),n.OnCollapsing&&i.onCollapsing(function(e,i){return t().executeScript(n.OnCollapsing.Name||n.OnCollapsing,i)}),n.OnCollapsed&&i.onCollapsed(function(e,i){return t().executeScript(n.OnCollapsed.Name||n.OnCollapsed,i)})},buildHeaderTemplate:function(e,t){var n;return n="undefined"==typeof e||_.isEmpty(e)?this.buildDefaultHeaderTemplate(t):this.buildMetadataHeaderTemplate(e,t)},buildDefaultHeaderTemplate:function(e){return function(e,t){var n=new Label(this);return n.setText(t.value),n}},buildMetadataHeaderTemplate:function(e,t){var n=t.element,i=t.builder;return function(o,r){var a={parent:n,parentView:t.parentView,basePathOfProperty:t.basePathOfProperty};return i.build(e,a)}}}),window.InfinniUI.PasswordBox=PasswordBox,_.inherit(PasswordBox,Element),_.extend(PasswordBox.prototype,{setAutocomplete:function(e){"undefined"!=typeof e&&null!==e&&this.control.set("autocomplete",!!e)},getAutocomplete:function(){return this.control.get("autocomplete")},createControl:function(){return new PasswordBoxControl},getRawValue:function(){return this.control.get("rawValue")}},editorBaseMixin,labelTextElementMixin),window.InfinniUI.PasswordBoxBuilder=PasswordBoxBuilder,_.inherit(PasswordBoxBuilder,ElementBuilder),_.extend(PasswordBoxBuilder.prototype,{applyMetadata:function(e){ElementBuilder.prototype.applyMetadata.call(this,e),this.applyMetadata_editorBaseBuilder(e);var t=e.metadata,n=e.element;this.initBindingToProperty(e,"LabelText"),n.setAutocomplete(t.Autocomplete)},createElement:function(e){var t=new PasswordBox(e.parent);return t}},editorBaseBuilderMixin),window.InfinniUI.PopupButton=PopupButton,_.inherit(PopupButton,Container),_.extend(PopupButton.prototype,{createControl:function(e){return new PopupButtonControl(e)}},buttonMixin),window.InfinniUI.PopupButtonBuilder=PopupButtonBuilder,_.inherit(PopupButtonBuilder,ContainerBuilder),_.extend(PopupButtonBuilder.prototype,{createElement:function(e){var t=this.detectViewMode(e);return new PopupButton(e.parent,t)},detectViewMode:function(e){var t=e.metadata.ViewMode,n=e.parent,i=!1;if(!t)for(;!i;)n?n instanceof MenuBar?(t="forMenu",i=!0):n=n.parent:i=!0;return t},applyMetadata:function(e){ContainerBuilder.prototype.applyMetadata.call(this,e),this.applyButtonMetadata.call(this,e)}},buttonBuilderMixin),window.InfinniUI.RadioGroupBuilder=RadioGroupBuilder,_.inherit(RadioGroupBuilder,ListBoxBuilder),_.extend(RadioGroupBuilder.prototype,{createElement:function(e){var t=e.metadata.ViewMode||"checking";return new ListBox(e.parent,t)},applyMetadata:function(e){var t=e.element;ListBoxBuilder.prototype.applyMetadata.call(this,e),t.setMultiSelect(!1)}}),window.InfinniUI.ScrollPanel=ScrollPanel,_.inherit(ScrollPanel,Container),ScrollPanel.prototype.getHorizontalScroll=function(){return this.control.get("horizontalScroll")},ScrollPanel.prototype.setHorizontalScroll=function(e){InfinniUI.Metadata.isValidValue(e,InfinniUI.ScrollVisibility)&&this.control.set("horizontalScroll",e)},ScrollPanel.prototype.getVerticalScroll=function(){return this.control.get("verticalScroll")},ScrollPanel.prototype.setVerticalScroll=function(e){InfinniUI.Metadata.isValidValue(e,InfinniUI.ScrollVisibility)&&this.control.set("verticalScroll",e)},ScrollPanel.prototype.createControl=function(){return new ScrollPanelControl},window.InfinniUI.ScrollPanelBuilder=ScrollPanelBuilder,_.inherit(ScrollPanelBuilder,ContainerBuilder),_.extend(ScrollPanelBuilder.prototype,{createElement:function(e){return new ScrollPanel(e.parent)},applyMetadata:function(e){var t=e.metadata,n=e.element,i=ContainerBuilder.prototype.applyMetadata.call(this,e);return n.setHorizontalScroll(t.HorizontalScroll),n.setVerticalScroll(t.VerticalScroll),i}}),window.InfinniUI.TabPanel=TabPanel,_.inherit(TabPanel,Container),TabPanel.prototype.getHeaderLocation=function(){return this.control.get("headerLocation")},TabPanel.prototype.setHeaderLocation=function(e){InfinniUI.Metadata.isValidValue(e,InfinniUI.TabHeaderLocation)&&this.control.set("headerLocation",e)},TabPanel.prototype.getHeaderOrientation=function(){return this.control.get("headerOrientation")},TabPanel.prototype.setHeaderOrientation=function(e){InfinniUI.Metadata.isValidValue(e,InfinniUI.TabHeaderOrientation)&&this.control.set("headerOrientation",e)},TabPanel.prototype.setHeaderTemplate=function(e){this.control.set("headerTemplate",e)},TabPanel.prototype.getHeaderTemplate=function(){return this.control.get("headerTemplate")},TabPanel.prototype.setSelectedItem=function(e){return this.control.setSelectedItem(e)},TabPanel.prototype.getSelectedItem=function(){return this.control.get("selectedItem")},TabPanel.prototype.onSelectedItemChanged=function(e){this.control.on("change:selectedItem",e)},TabPanel.prototype.closeTab=function(e){var t=this.childElements.indexOf(e);if(t===-1)throw new Error("TabPage not found in TabPanel.childElements");this.getItems().removeAt(t)},TabPanel.prototype.createControl=function(){return new TabPanelControl},window.InfinniUI.TabPanelBuilder=TabPanelBuilder,_.inherit(TabPanelBuilder,ContainerBuilder),_.extend(TabPanelBuilder.prototype,{createElement:function(e){return new TabPanel(e.parent)},applyMetadata:function(e){var t=e.metadata,n=e.element,i=ContainerBuilder.prototype.applyMetadata.call(this,e);return n.setHeaderLocation(t.HeaderLocation),n.setHeaderOrientation(t.HeaderOrientation),this.initScriptHandlers(e),i},initScriptHandlers:function(e){var t=e.metadata,n=e.element;n.onSelectedItemChanged(function(e,t){var n=window.InfinniUI.global.messageBus;n.send("OnChangeLayout",{})}),t.OnSelectedItemChanged&&n.onSelectedItemChanged(function(n,i){return new ScriptExecutor(e.parentView).executeScript(t.OnSelectedItemChanged.Name||t.OnSelectedItemChanged,i)})}}),window.InfinniUI.TablePanel=TablePanel,_.inherit(TablePanel,Container),_.extend(TablePanel.prototype,{createControl:function(){return new TablePanelControl}}),window.InfinniUI.TablePanelBuilder=TablePanelBuilder,_.inherit(TablePanelBuilder,ContainerBuilder),_.extend(TablePanelBuilder.prototype,{createElement:function(e){return new TablePanel(e.parent)},applyMetadata:function(e){e.metadata,e.element;ContainerBuilder.prototype.applyMetadata.call(this,e)}}),window.InfinniUI.ToggleButton=ToggleButton,_.inherit(ToggleButton,Element),_.extend(ToggleButton.prototype,{createControl:function(e){return new ToggleButtonControl(e)},getTextOn:function(){return this.control.get("textOn")},setTextOn:function(e){return this.control.set("textOn",e?e:"")},getTextOff:function(){return this.control.get("textOff")},setTextOff:function(e){return this.control.set("textOff",e?e:"")}},editorBaseMixin),window.InfinniUI.ToggleButtonBuilder=ToggleButtonBuilder,_.inherit(ToggleButtonBuilder,ElementBuilder),_.extend(ToggleButtonBuilder.prototype,{createElement:function(e){return new ToggleButton(e.parent)},applyMetadata:function(e){ElementBuilder.prototype.applyMetadata.call(this,e),this.applyMetadata_editorBaseBuilder(e);var t=e.element,n=e.metadata;t.setTextOff(n.TextOff),t.setTextOn(n.TextOn)}},editorBaseBuilderMixin);var ToolBar=function(e){_.superClass(ToolBar,this,e)};window.InfinniUI.ToolBar=ToolBar,_.inherit(ToolBar,Container),ToolBar.prototype.createControl=function(){return new ToolBarControl},window.InfinniUI.ToolBarBuilder=ToolBarBuilder,_.inherit(ToolBarBuilder,ContainerBuilder),_.extend(ToolBarBuilder.prototype,{createElement:function(e){return new ToolBar(e.parent)}});var Tooltip=function(e){_.superClass(Icon,this,e)};_.inherit(Tooltip,Element),_.extend(Tooltip.prototype,{createControl:function(){return new InfinniUI.TooltipControl},setContent:function(e){this.control.set("content",e)}}),InfinniUI.Tooltip=Tooltip,InfinniUI.TooltipBuilder=TooltipBuilder,_.inherit(TooltipBuilder,ElementBuilder),_.extend(TooltipBuilder.prototype,{createElement:function(e){return new InfinniUI.Tooltip},normalizeMetadata:function(e){return"string"==typeof e&&(e={Text:e}),e},applyMetadata:function(e){var t=e.element;e.metadata=this.normalizeMetadata(e.metadata),ElementBuilder.prototype.applyMetadata.call(this,e),t.setContent(this.buildContent(e.metadata,e));var n=InfinniUI.global.messageBus;n.send(messageTypes.onToolTipInit,{element:e.parent,content:t}),e.parent.onRemove(function(){n.send(messageTypes.onToolTipDestroy,{element:e.parent})})},buildContent:function(e,t){var n,i=t.builder,o={parent:t.element,parentView:t.parentView,basePathOfProperty:t.basePathOfProperty};return n="Text"in e?this.buildTextContent(e.Text,i,o):this.buildElementContent(e,i,o)},buildTextContent:function(e,t,n){return t.buildType("Label",{Text:e},n)},buildElementContent:function(e,t,n){return t.build(e,n)}}),window.InfinniUI.TreeView=TreeView,_.inherit(TreeView,ListEditorBase),TreeView.prototype.createControl=function(){return new TreeViewControl},TreeView.prototype.getKeySelector=function(){return this.control.get("keySelector")},TreeView.prototype.setKeySelector=function(e){this.control.set("keySelector",e)},TreeView.prototype.getParentSelector=function(){return this.control.get("parentSelector")},TreeView.prototype.setParentSelector=function(e){this.control.set("parentSelector",e)},window.InfinniUI.TreeViewBuilder=TreeViewBuilder,_.inherit(TreeViewBuilder,ListEditorBaseBuilder),_.extend(TreeViewBuilder.prototype,{createElement:function(e){return new TreeView(e.parent)},applyMetadata:function(e){ListEditorBaseBuilder.prototype.applyMetadata.call(this,e);this._initKeySelector(e),this._initParentSelector(e)},_initKeySelector:function(e){var t,n=e.element,i=e.metadata;t=i.KeySelector?function(e,t){var o=new ScriptExecutor(n.getScriptsStorage());return o.executeScript(i.KeySelector.Name||i.KeySelector,t)}:i.KeyProperty?function(e,t){return InfinniUI.ObjectUtils.getPropertyValue(t.value,i.KeyProperty)}:function(e,t){return t.value},n.setKeySelector(t)},_initParentSelector:function(e){var t,n=e.element,i=e.metadata;t=i.ParentSelector?function(e,t){var o=new ScriptExecutor(n.getScriptsStorage());return o.executeScript(i.ParentSelector.Name||i.ParentSelector,t)}:i.ParentProperty?function(e,t){return InfinniUI.ObjectUtils.getPropertyValue(t.value,i.ParentProperty)}:function(e,t){return t.value},n.setParentSelector(t)}}),window.InfinniUI.View=View,_.inherit(View,Container),_.extend(View.prototype,{isView:!0,_initDataSourceHandlers:function(){var e=this,t=this.getContext().dataSources,n=[];this.control.onLoaded(function(){for(var i in t)n.push(t[i].getCurrentRequestPromise());n.length>0?$.when.apply($,n).done(function(){e._notifyAboutDsReady()}):e._notifyAboutDsReady()})},_notifyAboutDsReady:function(){this.handlers.onBeforeLoaded.resolve(),this.handlers.onLoaded.resolve()},createControl:function(){return new ViewControl},_initContext:function(){this.context={view:this,scripts:{},parameters:{},dataSources:{},controls:{},messageBus:new MessageBus(this),global:InfinniUI.global};var e=this;this.control.get("scripts").onChange(function(){e.context.scripts={};var t=e.getScripts();t.forEach(function(t){e.context.scripts[t.name]=t.func})}),this.control.get("parameters").onChange(function(){e.context.parameters={};var t=e.getParameters();t.forEach(function(t){e.context.parameters[t.name]=t,e.registerMember(t.name,t)})}),this.control.get("dataSources").onChange(function(){e.context.dataSources={};var t=e.getDataSources();t.forEach(function(t){e.context.dataSources[t.get("name")]=t,e.registerMember(t.name,t)})})},getApplicationView:function(){var e=this.control.get("isApplication"),t=this.parent;return e?this:_.isEmpty(t)?null:t.getApplicationView()},isApplication:function(e){var t=this.control.get("isApplication");return _.isBoolean(e)&&this.control.set("isApplication",e),t},registerElement:function(e){this.context.controls[e.name]=e,this.registerMember(e.name,e)},getContext:function(){return this.context},getScripts:function(){return this.control.get("scripts")},getParameters:function(){return this.control.get("parameters")},getDataSources:function(){return this.control.get("dataSources")},getDialogResult:function(){return this.control.get("dialogResult")},setDialogResult:function(e){return this.control.set("dialogResult",e)},open:function(e,t){var n=this.getContext(),i=this._getScriptArgs();this.eventManager.trigger("onOpening",i,n)?(this.openStrategy.open(),this.eventManager.trigger("onOpened",i,n),e&&e(n,i)):t&&t(n,i)},close:function(e,t,n){if(!this.isClosing){this.isClosing=!0;var i=this.getContext(),o=this._getScriptArgs();n||this.eventManager.trigger("onClosing",o,i)?(this.eventManager.trigger("onClosed",o,i),this.openStrategy.close(),e&&e(i,o)):t&&t(i,o)}},getScriptsStorage:function(){return this},setOpenStrategy:function(e){this.openStrategy=e},onBeforeLoaded:function(e){this.handlers.onBeforeLoaded.done(e)},onLoaded:function(e){this.handlers.onLoaded.done(e)},onOpening:function(e){this.eventManager.on("onOpening",e)},onOpened:function(e){this.eventManager.on("onOpened",e)},onClosing:function(e){this.eventManager.on("onClosing",e)},onClosed:function(e){this.eventManager.on("onClosed",e)},_getScriptArgs:function(){return{source:this}},setHeaderTemplate:function(e){this.headerTemplate=e},getHeaderTemplate:function(){return this.headerTemplate},setCloseButtonVisibility:function(e){"boolean"==typeof e&&this.control.set("closeButtonVisibility",e)},getCloseButtonVisibility:function(){return this.control.get("closeButtonVisibility")},noDataSourceOnView:function(){this._initDataSourceHandlers()},registerMember:function(e,t){this.members[e]=t,e in this.membersDeferreds&&this.membersDeferreds[e].resolve(t)},getDeferredOfMember:function(e){if(!(e in this.membersDeferreds)&&(this.membersDeferreds[e]=$.Deferred(),this.members[e])){var t=this.members[e];this.membersDeferreds[e].resolve(t)}return this.membersDeferreds[e]},setFocusOnControl:function(e){this.control.set("focusOnControl",e)},getFocusOnControl:function(){return this.control.get("focusOnControl")}}),window.InfinniUI.ViewBuilder=ViewBuilder,_.inherit(ViewBuilder,ContainerBuilder),_.extend(ViewBuilder.prototype,{createElement:function(e){return new View(e.parent)},applyMetadata:function(e){e.parentView;e=_.extend({},e),e.parentView=e.element;var t=e.metadata,n=e.element,i=e.builder,o=n.getScripts(),r=n.getParameters();if(t.Scripts)for(var a=0,l=t.Scripts.length;a1&&(_.each(e,function(e){e.setIsWaiting(!0)}),n(t))}},viewBuilderHeaderTemplateMixin),window.InfinniUI.ViewPanel=ViewPanel,_.inherit(ViewPanel,Element),_.extend(ViewPanel.prototype,{setLayout:function(e){var t=this.getLayout();t&&t.close(),this.control.set("layout",e)},getLayout:function(){return this.control.get("layout")},createControl:function(){return new ViewPanelControl}}),window.InfinniUI.ViewPanelBuilder=ViewPanelBuilder,_.inherit(ViewPanelBuilder,ElementBuilder),_.extend(ViewPanelBuilder.prototype,{applyMetadata:function(e){ElementBuilder.prototype.applyMetadata.call(this,e);var t=e.builder,n=e.element,i=e.metadata;e.parentView;if(_.isEmpty(i.Name)&&(i.Name=guid(),n.setName(i.Name)),InfinniUI.global.containers[i.Name]=n,"LinkView"in i){var o=t.build(i.LinkView,{parentView:e.parentView,parent:e.element});o.setOpenMode("Container"),o.setContainer(i.Name),o.createView(function(e){e.open()})}},createElement:function(e){return new ViewPanel(e.parent)}}),InfinniUI.global.containers={},_.inherit(DataGridRow,Element),_.extend(DataGridRow.prototype,{createControl:function(){return new DataGridRowControl},setCellElements:function(e){this.control.set("cellElements",e)},toggle:function(e){this.control.set("toggle",e)},getSelected:function(){this.control.get("selected")},setSelected:function(e){this.control.set("selected",e)},setMultiSelect:function(e){this.control.set("multiSelect",e)},setShowSelectors:function(e){this.control.set("showSelectors",e)},onToggle:function(e){this.control.onToggle(e)},setRowBackground:function(e){this.control.set("rowBackground",e)},getRowBackground:function(){return this.control.get("rowBackground")},setRowForeground:function(e){this.control.set("rowForeground",e)},getRowForeground:function(){return this.control.get("rowForeground")},setRowTextStyle:function(e){this.control.set("rowTextStyle",e)},getRowTextStyle:function(){return this.control.get("rowTextStyle")},setRowStyle:function(e){this.control.set("rowStyle",e)},getRowStyle:function(){return this.control.get("rowStyle")},setGrid:function(e){this.control.set("grid",e)},_transformRowProperties:function(e){for(var t in e)e.hasOwnProperty(t)&&(this.setProperty(e[t],this.getProperty(t)),this.onPropertyChanged(t,function(e,t){return function(n,i){e.setProperty(t,i.newValue)}}(this,e[t])))}}),_.inherit(TabPage,Container),TabPage.prototype.getIcon=function(){return this.control.get("icon")},TabPage.prototype.setIcon=function(e){this.control.set("icon",e)},TabPage.prototype.getCanClose=function(){return this.control.get("canClose")},TabPage.prototype.setCanClose=function(e){this.control.set("canClose",e)},TabPage.prototype.close=function(e,t){var n=this.getCanClose(),i=this,o=this.events;n&&this.events.trigger("closing").done(function(){i.parent&&i.parent.closeTab(i),"function"==typeof e&&e(),o.trigger("closed")}).fail(function(){"function"==typeof t&&t()})},TabPage.prototype.onClosing=function(e){this.events.on("closing",e)},TabPage.prototype.onClosed=function(e){this.events.on("closed",e)},TabPage.prototype.getSelected=function(){return this.control.get("selected")},TabPage.prototype.setSelected=function(e){this.control.set("selected",e)},TabPage.prototype.createControl=function(){return new TabPageControl},_.inherit(TabPageBuilder,ContainerBuilder),_.extend(TabPageBuilder.prototype,{createElement:function(e){return new TabPage(e.parent)},applyMetadata:function(e){var t=e.metadata,n=e.element,i=ContainerBuilder.prototype.applyMetadata.call(this,e);return n.setIcon(t.Icon),n.setCanClose(t.CanClose),this.initScriptHandlers(e),i},initScriptHandlers:function(e){var t=e.metadata,n=e.element;t.OnClosing&&n.onClosing(function(){return new ScriptExecutor(e.parentView).executeScript(t.OnClosing.Name||t.OnClosing,{})}),t.OnClosed&&n.onClosed(function(){return new ScriptExecutor(e.parentView).executeScript(t.OnClosed.Name||t.OnClosed,{})})}}),_.inherit(Cell,Container),_.extend(Cell.prototype,{createControl:function(){return new CellControl},getColumnSpan:function(){return this.control.get("columnSpan")},setColumnSpan:function(e){this.control.set("columnSpan",e)}}),_.inherit(CellBuilder,ContainerBuilder),_.extend(CellBuilder.prototype,{createElement:function(e){return new Cell(e.parent)},applyMetadata:function(e){var t=e.metadata;e.element;ContainerBuilder.prototype.applyMetadata.call(this,e),e.element.setColumnSpan(t.ColumnSpan)}}),_.inherit(Row,Container),_.extend(Row.prototype,{createControl:function(){return new RowControl}}),_.inherit(RowBuilder,ContainerBuilder),_.extend(RowBuilder.prototype,{createElement:function(e){return new Row(e.parent)},applyMetadata:function(e){e.metadata,e.element;ContainerBuilder.prototype.applyMetadata.call(this,e)}}),window.InfinniUI.BaseAction=BaseAction,_.extend(BaseAction.prototype,{defaults:{},setProperty:function(e,t){var n=this._properties;n[e]!==t&&(n[e]=t,this.trigger("change:"+e,this,t))},getProperty:function(e){return this._properties[e]},initDefaultValues:function(){},onExecutedHandler:function(e){var t=this.getProperty("onExecutedHandler");_.isFunction(t)&&t(e)}},Backbone.Events),InfinniUI.global.executeAction=function(e,t,n){var i=new ApplicationBuilder,o=i.build(t,{parentView:e.view});o.execute(n)};var BaseActionBuilderMixin={applyBaseActionMetadata:function(e,t){var n=t.metadata;"OnExecuted"in n&&e.setProperty("onExecutedHandler",function(t){new ScriptExecutor(e.parentView).executeScript(n.OnExecuted.Name||n.OnExecuted,t)})}};window.InfinniUI.BaseEditAction=BaseEditAction,_.inherit(BaseEditAction,BaseAction),_.extend(BaseEditAction.prototype,{execute:function(e){var t=this,n=this.getProperty("linkView");this.setProperty("callback",e),n.createView(function(e){t.handleViewReady(e)})},handleViewReady:function(e){var t=this.getProperty("sourceSource"),n=e.getContext().dataSources[t],i=this.getProperty("destinationSource"),o=this.parentView.getContext().dataSources[i],r=this;this.setProperty("editDataSource",n),this.setProperty("destinationDataSource",o);var a=this.setSelectedItem();a?(e.open(),e.onClosed(function(){var t=e.getDialogResult();t==DialogResult.accepted&&r.handleClosingView()})):e.close()},handleClosingView:function(){ +var e=this.getProperty("callback");this.save(),this.onExecutedHandler(),_.isFunction(e)&&e()},_isObjectDataSource:function(e){return"setItems"in e}});var BaseEditActionBuilderMixin={applyBaseEditActionMetadata:function(e,t){var n=t.metadata,i=t.parentView,o=t.builder,r={};r[n.SourceValue.Source]="BaseEditAction";var a=o.build(n.LinkView,{parent:t.parent,parentView:i,basePathOfProperty:t.basePathOfProperty,suspended:r});e.setProperty("linkView",a),e.setProperty("sourceSource",n.SourceValue.Source),e.setProperty("destinationSource",n.DestinationValue.Source);var l=null!=t.basePathOfProperty?t.basePathOfProperty.resolveProperty(n.DestinationValue.Property):n.DestinationValue.Property;e.setProperty("destinationProperty",l)}},BaseFallibleActionBuilderMixin={applyBaseFallibleActionMetadata:function(e,t){var n=t.metadata;"OnSuccess"in n&&e.setProperty("onSuccessHandler",function(t){new ScriptExecutor(e.parentView).executeScript(n.OnSuccess.Name||n.OnSuccess,t)}),"OnError"in n&&e.setProperty("onErrorHandler",function(t){new ScriptExecutor(e.parentView).executeScript(n.OnError.Name||n.OnError,t)})}},BaseFallibleActionMixin={onSuccessHandler:function(e){var t=this.getProperty("onSuccessHandler");_.isFunction(t)&&t(e)},onErrorHandler:function(e){var t=this.getProperty("onErrorHandler");_.isFunction(t)&&t(e)}};_.inherit(AcceptAction,BaseAction),_.extend(AcceptAction.prototype,{execute:function(e){var t=this;this.parentView.onClosed(function(){t.onExecutedHandler(),e&&e()}),this.parentView.setDialogResult(DialogResult.accepted),this.parentView.close()}}),window.InfinniUI.AcceptAction=AcceptAction,_.extend(AcceptActionBuilder.prototype,BaseActionBuilderMixin,{build:function(e,t){var n=new AcceptAction(t.parentView);return this.applyBaseActionMetadata(n,t),n}}),window.InfinniUI.AcceptActionBuilder=AcceptActionBuilder,_.inherit(AddAction,BaseEditAction),_.extend(AddAction.prototype,{setSelectedItem:function(){var e=this.getProperty("editDataSource"),t=e.getView();return t.onBeforeLoaded(function(){e.createItem()}),!0},save:function(){var e=this.getProperty("editDataSource"),t=this.getProperty("destinationDataSource"),n=this.getProperty("destinationProperty")||"";if(this._isObjectDataSource(e)){var i=t.getProperty(n)||[],o=e.getSelectedItem();i=_.clone(i),i.push(o),t.setProperty(n,i)}else t.updateItems()}}),window.InfinniUI.AddAction=AddAction,_.extend(AddActionBuilder.prototype,BaseActionBuilderMixin,BaseEditActionBuilderMixin,{build:function(e,t){var n=new AddAction(t.parentView);return this.applyBaseActionMetadata(n,t),this.applyBaseEditActionMetadata(n,t),n}}),window.InfinniUI.AddActionBuilder=AddActionBuilder,_.inherit(CancelAction,BaseAction),_.extend(CancelAction.prototype,{execute:function(e){var t=this;this.parentView.onClosed(function(){t.onExecutedHandler(),e&&e()}),this.parentView.setDialogResult(DialogResult.canceled),this.parentView.close()}}),window.InfinniUI.CancelAction=CancelAction,_.extend(CancelActionBuilder.prototype,BaseActionBuilderMixin,{build:function(e,t){var n=new CancelAction(t.parentView);return this.applyBaseActionMetadata(n,t),n}}),window.InfinniUI.CancelActionBuilder=CancelActionBuilder,_.inherit(DeleteAction,BaseAction),_.extend(DeleteAction.prototype,BaseFallibleActionMixin,{execute:function(e){var t=this.getProperty("accept"),n=this,i=this.getProperty("destinationSource"),o=this.getProperty("destinationProperty");i.getProperty(o)?t?new MessageBox({text:"Вы уверены, что хотите удалить?",buttons:[{name:"Да",type:"action",onClick:function(){n.remove(e)}},{name:"Нет"}]}):this.remove(e):new MessageBox({text:"Вы не выбрали элемент который необходимо удалить",buttons:[{name:"Закрыть"}]})},remove:function(e){var t=this.getProperty("destinationSource"),n=this.getProperty("destinationProperty");this._isDocument(n)?this._deleteDocument(t,n,e):this._deleteItem(t,n,e)},_deleteDocument:function(e,t,n){var i=this,o=function(t,o){e.updateItems(),i.onExecutedHandler(o),i.onSuccessHandler(o),_.isFunction(n)&&n()},r=function(e,t){i.onExecutedHandler(t),i.onErrorHandler(t),_.isFunction(n)&&n()},a=e.getProperty(t);e.deleteItem(a,o,r)},_deleteItem:function(e,t,n){var i=t.split("."),o=i.pop(),r=i.join("."),a=e.getProperty(r);a=_.clone(a),a.splice(o,1),e.setProperty(r,a),this.onExecutedHandler(),this.onSuccessHandler(),_.isFunction(n)&&n()},_isDocument:function(e){return"$"==e||_.isFinite(e)}}),window.InfinniUI.DeleteAction=DeleteAction,_.extend(DeleteActionBuilder.prototype,BaseActionBuilderMixin,BaseFallibleActionBuilderMixin,{build:function(e,t){var n=t.metadata,i=t.parentView,o=n.DestinationValue.Source,r=n.DestinationValue.Property||"$",a=new DeleteAction(i);this.applyBaseActionMetadata(a,t),this.applyBaseFallibleActionMetadata(a,t);var l=n.Accept!==!1,s=i.getContext().dataSources[o],u=null!=t.basePathOfProperty?t.basePathOfProperty.resolveProperty(r):r;return a.setProperty("accept",l),a.setProperty("destinationSource",s),a.setProperty("destinationProperty",u),a}}),window.InfinniUI.DeleteActionBuilder=DeleteActionBuilder,_.inherit(EditAction,BaseEditAction),_.extend(EditAction.prototype,{setSelectedItem:function(){var e=this.getProperty("editDataSource"),t=this.getProperty("destinationDataSource"),n=this.getProperty("destinationProperty"),i=t.getProperty(n);if(null==i){if(this._isDocumentPath(n)){var o=window.InfinniUI.global.logger,r=stringUtils.format('EditAction: edit item has not been found. {0} does not have item by path "{1}"',[t.getName(),n]);return o.error(r),!1}i=i||{}}return this._isObjectDataSource(e)?this._setItem(e,i):this._setDocument(e,i),!0},_resumeUpdateEditDataSource:function(){var e=this.getProperty("editDataSource");e.resumeUpdate("BaseEditAction")},_setDocument:function(e,t){var n=e.idOfItem(t);e.setIdFilter(n),e.tryInitData(),this._resumeUpdateEditDataSource()},_setItem:function(e,t){var n=_.clone(t);void 0!==n&&null!==n||(n={}),this._resumeUpdateEditDataSource(),e.setItems([n]),e.setSelectedItem(n)},save:function(){var e=this.getProperty("editDataSource"),t=this.getProperty("destinationDataSource"),n=this.getProperty("destinationProperty");if(this._isObjectDataSource(e)){var i=e.getSelectedItem();t.setProperty(n,i)}else t.updateItems()},_isDocumentPath:function(e){return!e.includes(".")}}),window.InfinniUI.EditAction=EditAction,_.extend(EditActionBuilder.prototype,BaseActionBuilderMixin,BaseEditActionBuilderMixin,{build:function(e,t){var n=new EditAction(t.parentView);return this.applyBaseActionMetadata(n,t),this.applyBaseEditActionMetadata(n,t),n}}),window.InfinniUI.EditActionBuilder=EditActionBuilder,_.inherit(OpenAction,BaseAction),_.extend(OpenAction.prototype,{execute:function(e){var t=this.getProperty("linkView"),n=this;t.createView(function(t){t.onLoaded(function(){n.onExecutedHandler(),e&&e(t)}),t.open()})}}),window.InfinniUI.OpenAction=OpenAction,_.extend(OpenActionBuilder.prototype,BaseActionBuilderMixin,{build:function(e,t){var n=new OpenAction(t.parentView);this.applyBaseActionMetadata(n,t);var i=t.builder.build(t.metadata.LinkView,{parent:t.parent,parentView:t.parentView,basePathOfProperty:t.basePathOfProperty});return n.setProperty("linkView",i),n}}),window.InfinniUI.OpenActionBuilder=OpenActionBuilder,_.inherit(RouteToAction,BaseAction),_.extend(RouteToAction.prototype,{execute:function(e){var t=InfinniUI.AppRouter,n=this.getHref();t.navigate(n,{trigger:!0})},getHref:function(){return this.href},setHref:function(e){this.href=e}}),window.InfinniUI.RouteToAction=RouteToAction,_.extend(RouteToActionBuilder.prototype,BaseActionBuilderMixin,routerServiceMixin,{build:function(e,t){var n=new RouteToAction,i=routerService.getLinkByName(t.metadata.Name,"no"),o=t.metadata.Params,r=t.metadata.Query;if(n.setHref(i),t.element=n,o)for(var a=0,l=o.length;a$/);return i?this.getParam(i[1]):e.replace(/<%([\s\S]+?)%>/g,function(e,i){var o=n.getParam(i);return t&&_.isString(o)&&(o=o.replace(/"/g,'\\"')),o})},_compileData:function(e){var t;return Array.isArray(e)?t=Array.map(function(e){(_.isObject(e)||Array.isArray(e))&&this._compileData(e)},this):_.isObject(e)?(t={},Object.keys(e).forEach(function(n){var i=this._replaceParamsInStr(n);t[i]=this._compileData(e[n])},this)):t=this._replaceParamsInStr(e,!0),t},_replaceParamsInObject:function(e){return _.isEmpty(e)?e:this._compileData(e)}}),window.InfinniUI.ServerAction=ServerAction,_.extend(ServerActionBuilder.prototype,BaseActionBuilderMixin,BaseFallibleActionBuilderMixin,{build:function(e,t){var n=t.builder,i=t.metadata,o=t.parentView,r=new ServerAction(o);if(this.applyBaseActionMetadata(r,t),this.applyBaseFallibleActionMetadata(r,t),r.setProperty("origin",i.Origin||InfinniUI.config.serverUrl.replace(/\/$/,"")),r.setProperty("path",i.Path),i.Data&&r.setProperty("data",i.Data),i.Method&&r.setProperty("method",i.Method),(i.ContentType||i.ContentType===!1)&&r.setProperty("contentType",i.ContentType),i.Params)for(var a in i.Params){var l=i.Params[a];Array.isArray(l)||null===l||"object"!=typeof l?void 0!==l&&r.setParam(a,l):this._initBinding(a,l,r,o,n)}return r},_initBinding:function(e,t,n,i,o){var r={parent:i,parentView:i},a=o.buildBinding(t,r);a.setMode(InfinniUI.BindingModes.toElement),a.bindElement({setProperty:function(e,t){n.setParam(e,t)},onPropertyChanged:function(){}},e)}}),window.InfinniUI.ServerActionBuilder=ServerActionBuilder;var serverActionContentTypeStrategy={File:{run:function(e,t,n,i,o){e.download(t,n,i,o)}},Object:{run:function(e,t,n,i,o){e.request(t,n,i,o)}}};_.inherit(UpdateAction,BaseAction),_.extend(UpdateAction.prototype,BaseFallibleActionMixin,{execute:function(e){var t=this.getProperty("dataSource"),n=this,i=function(t,i){n.onExecutedHandler(i),n.onSuccessHandler(i),_.isFunction(e)&&e(t,i)},o=function(t,i){n.onExecutedHandler(i),n.onErrorHandler(i),_.isFunction(e)&&e(t,i)};t.updateItems(i,o)}}),window.InfinniUI.UpdateAction=UpdateAction,_.extend(UpdateActionBuilder.prototype,BaseActionBuilderMixin,BaseFallibleActionBuilderMixin,{build:function(e,t){var n=t.parentView.getContext().dataSources[t.metadata.DestinationValue.Source],i=new UpdateAction(t.parentView);return this.applyBaseActionMetadata(i,t),this.applyBaseFallibleActionMetadata(i,t),i.setProperty("dataSource",n),i}}),window.InfinniUI.UpdateActionBuilder=UpdateActionBuilder,_.extend(ApplicationBuilder.prototype,{builder:null,registerElementBuilders:function(){var e=this.builder;e.register("View",new ViewBuilder),e.register("InlineView",new InlineViewBuilder),e.register("AutoView",new MetadataViewBuilder),e.register("StackPanel",new StackPanelBuilder),e.register("GridPanel",new GridPanelBuilder),e.register("ScrollPanel",new ScrollPanelBuilder),e.register("Panel",new PanelBuilder),e.register("ScrollPanel",new ScrollPanelBuilder),e.register("ViewPanel",new ViewPanelBuilder),e.register("TabPanel",new TabPanelBuilder),e.register("TabPage",new TabPageBuilder),e.register("TablePanel",new TablePanelBuilder),e.register("Cell",new CellBuilder),e.register("Row",new RowBuilder),e.register("MenuBar",new MenuBarBuilder),e.register("DataGrid",new DataGridBuilder),e.register("DataGridRow",new DataGridRowBuilder),e.register("DataGridColumn",new DataGridColumnBuilder),e.register("ListBox",new ListBoxBuilder),e.register("TextBox",new TextBoxBuilder),e.register("PasswordBox",new PasswordBoxBuilder),e.register("CheckBox",new CheckBoxBuilder),e.register("IndeterminateCheckBox",new IndeterminateCheckBoxBuilder),e.register("ImageBox",new ImageBoxBuilder),e.register("FileBox",new FileBoxBuilder),e.register("Label",new LabelBuilder),e.register("Link",new LinkBuilder),e.register("Form",new FormBuilder),e.register("Icon",new IconBuilder),e.register("DateTimePicker",new DateTimePickerBuilder),e.register("DatePicker",new DatePickerBuilder),e.register("TimePicker",new TimePickerBuilder),e.register("ToggleButton",new ToggleButtonBuilder),e.register("NumericBox",new NumericBoxBuilder),e.register("Button",new ButtonBuilder),e.register("ToolBar",new ToolBarBuilder),e.register("ToolBarButton",new ButtonBuilder),e.register("ComboBox",new ComboBoxBuilder),e.register("RadioGroup",new RadioGroupBuilder),e.register("ExtensionPanel",new ExtensionPanelBuilder),e.register("PopupButton",new PopupButtonBuilder),e.register("DataNavigation",new DataNavigationBuilder),e.register("TreeView",new TreeViewBuilder),e.register("Frame",new FrameBuilder),e.register("ButtonEdit",new ButtonEditBuilder),e.register("RestDataSource",new RestDataSourceBuilder),e.register("DocumentDataSource",new DocumentDataSourceBuilder),e.register("PropertyBinding",new DataBindingBuilder),e.register("ObjectDataSource",new ObjectDataSourceBuilder),e.register("Parameter",new ParameterBuilder),e.register("AcceptAction",new AcceptActionBuilder),e.register("AddAction",new AddActionBuilder),e.register("CancelAction",new CancelActionBuilder),e.register("DeleteAction",new DeleteActionBuilder),e.register("EditAction",new EditActionBuilder),e.register("OpenAction",new OpenActionBuilder),e.register("SaveAction",new SaveActionBuilder),e.register("SelectAction",new SelectActionBuilder),e.register("UpdateAction",new UpdateActionBuilder),e.register("ServerAction",new ServerActionBuilder),e.register("RouteToAction",new RouteToActionBuilder),e.register("BooleanFormat",new BooleanFormatBuilder),e.register("DateTimeFormat",new DateTimeFormatBuilder),e.register("NumberFormat",new NumberFormatBuilder),e.register("ObjectFormat",new ObjectFormatBuilder),e.register("DateTimeEditMask",new DateTimeEditMaskBuilder),e.register("NumberEditMask",new NumberEditMaskBuilder),e.register("TemplateEditMask",new TemplateEditMaskBuilder),e.register("RegexEditMask",new RegexEditMaskBuilder),e.register("Script",new ScriptBuilder),e.register("Divider",new DividerBuilder),e.register("ContextMenu",new ContextMenuBuilder),e.register("ToolTip",new InfinniUI.TooltipBuilder);for(var t=ApplicationBuilder.registerQueue,n=0,i=t.length;n0&&(i.url=i.url+"?"+stringUtils.joinDataForQuery(o.data));else{var s=new FormData;s.append("document",JSON.stringify(l.dataWithoutFiles));for(var u in l.files)s.append(u,l.files[u]);i={type:o.method,url:r,xhrFields:{withCredentials:!0},data:s,cache:!1,contentType:!1,processData:!1,success:function(e){t({requestId:a,data:e})},error:function(e){n({requestId:a,data:e})}}}return $.ajax(i),a},getItems:function(e,t){return this.send("get",e,t)},saveItem:function(e,t,n){return this.requestParams.set.data=e,this.send("set",t,n)},deleteItem:function(e,t,n){return this.send("delete",t,n)},createItem:function(e,t){var n=this;setTimeout(function(){e(n.createLocalItem(t))},10)},createLocalItem:function(e){var t={};return t[e]=this._generateLocalId(),t},_generateLocalId:function(){return guid()},extractFilesFromData:function(e){function t(e,i){var o,r,a=Array.isArray(e)?[]:{};for(var l in e)if(e.hasOwnProperty(l))if(r=i.slice(),r.push(l),o=e[l],null!==o&&"object"==typeof o)if(o.constructor===Date)a[l]=o;else{if(o.constructor!==Object&&o.constructor!==Array){a[l]=null,n[r.join(".")]=o;continue}a[l]=t(o,r)}else a[l]=o;return a}var n=Object.create(null),i=t(e,[]);return{dataWithoutFiles:i,files:n}}}),window.InfinniUI.Providers.RestDataProvider=RestDataProvider;var ServerActionProvider=function(){};ServerActionProvider.prototype.request=function(e,t,n,i){var o=Math.round(1e5*Math.random());return $.ajax({type:e.method,url:e.requestUrl,xhrFields:{withCredentials:!0},data:e.args,contentType:e.contentType,success:function(e){var i={requestId:o,data:e};_.isFunction(t)&&t(i),_.isFunction(n)&&n(i)},error:function(e){var n={requestId:o,data:e};_.isFunction(t)&&t(n),_.isFunction(i)&&i(n)}}),o},ServerActionProvider.prototype.download=function(e,t,n,i){new DownloadExecutor(t,n,i).run(e)},window.InfinniUI.Providers.ServerActionProvider=ServerActionProvider;var DataProviderReplaceItemQueue=function(e){var t=e||[],n=[],i="__Id",o=function(e){var n=_.pick(e,t),o=_.isEmpty(e[i])?"Id":i;return n[o]=e[o],n},r=function(e){return _.findWhere(n,o(e))},a=function(e){return _.where(n,o(e))},l=function(e,t){var n=a(e);n.forEach(function(e){e.Id=t.Id,e.value.Id=t.Id})},s=function(e){var t=n.indexOf(e);t===-1&&console.error("DataProviderReplaceItemQueue: Не найден запрос в очереди"),n.splice(t,1);var i=r(e);u(i)},u=function(e){"undefined"!=typeof e&&null!==e&&e.request(e).done(l.bind(void 0,e)).always(s.bind(void 0,e))};this.append=function(e,t){var o=_.defaults(e,_.pick(e.value,["Id",i]));o.request=t;var r=a(o);if(n.push(o),0===r.length)u(e);else if(r.length>1)for(var l=1,s=r.length;l12&&(t-=12),t<10?"0"+t.toString():t.toString()},h:function(e){var t=e.getHours();return t>12?t-=12:0===t&&(t=12),t.toString()},mm:function(e){var t=e.getMinutes();return t<10?"0"+t.toString():t.toString()},"%m":function(e){var t=e.getMinutes();return t.toString()},m:function(e){var t=e.getMinutes();return t.toString()},ss:function(e){var t=e.getSeconds();return t<10?"0"+t.toString():t.toString()},"%s":function(e){var t=e.getSeconds();return t.toString()},s:function(e){var t=e.getSeconds();return t.toString()},tt:function(e,t){var n=e.getHours();return n<12?t.dateTimeFormatInfo.amDesignator:t.dateTimeFormatInfo.pmDesignator},"%t":function(e,t){var n=e.getHours();return n<12?t.dateTimeFormatInfo.amDesignator.substr(0,1):t.dateTimeFormatInfo.pmDesignator.substr(0,1)},t:function(e,t){var n=e.getHours();return n<12?t.dateTimeFormatInfo.amDesignator.substr(0,1):t.dateTimeFormatInfo.pmDesignator.substr(0,1)},zzz:function(e){var t,n,i=-e.getTimezoneOffset()/60;return t=100*(i-Math.floor(i)),i=Math.floor(i),i<0?(n="-",i=-i):n="+",t=t<10?"0"+t.toString():t.toString(),i<10?n+"0"+i.toString()+":"+t:n+i.toString()+":"+t},zz:function(e){var t,n=-e.getTimezoneOffset()/60;return n=Math.floor(n),n<0?(t="-",n=-n):t="+",n<10?t+"0"+n.toString():t+n.toString()},z:function(e,t){var n,i=-e.getTimezoneOffset()/60;return i=Math.floor(i),i<0?(n="-",i=-i):n="+",n+i.toString()},"%z":function(e,t){var n,i=-e.getTimezoneOffset()/60;return i=Math.floor(i),i<0?(n="-",i=-i):n="+",n+i.toString()},":":function(e,t){return t.dateTimeFormatInfo.timeSeparator},"/":function(e,t){return t.dateTimeFormatInfo.dateSeparator}}},formatMixin),window.InfinniUI.DateTimeFormatBuilder=DateTimeFormatBuilder,window.InfinniUI.NumberFormat=NumberFormat,_.extend(NumberFormat.prototype,{defaultFormat:"n",formatValue:function(e,t,n){if("undefined"==typeof e||null===e)return"";var i=this;return t=t||new Culture(InfinniUI.config.lang),n=n||this.getFormat(),n.replace(this.rg,function(n,o,r){return r=void 0!==r&&""!=r?parseInt(r):void 0,i.rules[o].call(i,e,r,t)})},rg:/^([pnc])(\d*)$/gi,rules:{P:function(e,t,n){t=void 0!==t?t:n.numberFormatInfo.percentDecimalDigits;var i,o=e>=0,r=this.formatNumber(Math.abs(e),t,n.numberFormatInfo.percentGroupSeparator,n.numberFormatInfo.percentDecimalSeparator);return i=o?n.numberFormatInfo.percentPositivePattern.replace("p",r):n.numberFormatInfo.percentNegativePattern.replace("p",r),i=i.replace("%",n.numberFormatInfo.percentSymbol)},p:function(e,t,n){return e*=100,this.rules.P.call(this,e,t,n)},n:function(e,t,n){t=void 0!==t?t:n.numberFormatInfo.numberDecimalDigits;var i,o=e>=0,r=this.formatNumber(Math.abs(e),t,n.numberFormatInfo.numberGroupSeparator,n.numberFormatInfo.numberDecimalSeparator);return i=o?n.numberFormatInfo.numberPositivePattern.replace("n",r):n.numberFormatInfo.numberNegativePattern.replace("n",r)},N:function(){return this.rules.n.apply(this,arguments)},c:function(e,t,n){t=void 0!==t?t:n.numberFormatInfo.currencyDecimalDigits;var i,o=e>=0,r=this.formatNumber(Math.abs(e),t,n.numberFormatInfo.currencyGroupSeparator,n.numberFormatInfo.currencyDecimalSeparator);return i=o?n.numberFormatInfo.currencyPositivePattern.replace("c",r):n.numberFormatInfo.currencyNegativePattern.replace("c",r),i=i.replace("$",n.numberFormatInfo.currencySymbol)},C:function(){return this.rules.c.apply(this,arguments)}},formatNumber:function(e,t,n,i){e=e.toFixed(t);var o=e.toString(),r=o.split("."),a=this.formatIntPath(r[0],n),l=this.formatFractPath(r[1],i,t);return a+l},formatIntPath:function(e,t){return e.replace(/(\d{1,3}(?=(\d{3})+(?:\.\d|\b)))/g,"$1"+t)},formatFractPath:function(e,t,n){var i,o=e?e:"";return 0==n?"":o.length>=n?t+o.substr(0,n):(i=Math.pow(10,n-o.length),i=i.toString().substr(1),t+o+i)}},formatMixin),window.InfinniUI.NumberFormatBuilder=NumberFormatBuilder,window.InfinniUI.ObjectFormat=ObjectFormat,_.extend(ObjectFormat.prototype,{formatValue:function(e,t,n){t=t||new Culture(InfinniUI.config.lang),n=n||this.getFormat();var i=/{[^}]*}/g,o="";return o=n.replace(i,this.formatIterator.bind(this,e,t))},formatIterator:function(e,t,n){var i,o,r,a,l,s=/^{|}$/g;if(i=n,o=n.replace(s,""),l=o.split(":"),a="object"==typeof e?""===l[0]?e:InfinniUI.ObjectUtils.getPropertyValue(e,l[0]):e,2===l.length){for(var u=0,d=this.formatters.length;ui&&(t=i)),t},getPrevIntValue:function(e,t){e=e||{};var n=null,i="undefined"!=typeof e.step?i:1;return"undefined"!=typeof e.min&&(n=e.min),t=parseInt(t,10),isNaN(t)?t=null===n?0:n:(t-=i,null!==n&&t2||2===e.length)}function i(e){return null!==e&&"undefined"!=typeof e&&(parseInt(e,10)>5||2===e.length)}function o(e){return null!==e&&"undefined"!=typeof e&&(parseInt(e,10)>5||2===e.length)}var r=/^(?:3[0-1]|[012]?[0-9]?)$/,a=/^(?:1[0-2]|0?[1-9]?)$/,l=/^\d{1,4}$/,s=/^\d{1,2}$/,u=/^(?:[2][0-3]|[01]?[0-9]?)$/,d=/^(?:0?\d|1[0-2])$/,c=/^[0-5]?[0-9]$/;return{d:{init:function(){this.width=1,this.min=1,this.max=31},match:function(e){return r.test(e)},validator:function(e){return this.rangeValidator(e)},filled:e,prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){return e.setDate(t),e}},dd:{init:function(){this.width=2,this.min=1,this.max=31},match:function(e){return r.test(e)},validator:function(e){return this.rangeValidator(e)},filled:e,prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){return e.setDate(t),e}},M:{init:function(){this.width=1,this.min=1,this.max=12},match:function(e){return a.test(e)},validator:function(e){return this.rangeValidator(e)},filled:t,prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){return e.setMonth(parseInt(t,10)-1),e}},MM:{init:function(){this.width=2,this.min=1,this.max=12},match:function(e){return a.test(e)},validator:function(e){return this.rangeValidator(e)},filled:t,prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){return e.setMonth(parseInt(t,10)-1),e}},y:{init:function(){this.width=2,this.min=0,this.max=99},match:function(e){return s.test(e)},validator:function(e){return this.rangeValidator(e)},prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){var n=parseInt(t,10);if(!isNaN(n)){n="0000"+n;var i=new Date;e.setFullYear(i.getFullYear().toString().substr(0,2)+n.slice(-2))}return e}},yy:{init:function(){this.width=2,this.min=0,this.max=99},match:function(e){return s.test(e)},validator:function(e){return this.rangeValidator(e)},prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){var n=parseInt(t,10);if(!isNaN(n)){n="0000"+n;var i=new Date;e.setFullYear(i.getFullYear().toString().substr(0,2)+n.slice(-2))}return e}},yyyy:{init:function(){this.width=4,this.min=0,this.max=9999},match:function(e){return l.test(e)},validator:function(e){return this.rangeValidator(e)},prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){return e.setFullYear(t),e}},H:{init:function(){this.width=1,this.min=0,this.max=23},match:function(e){return u.test(e)},validator:function(e){return this.rangeValidator(e)},filled:n,prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){return e.setHours(t),e}},h:{init:function(){this.width=1,this.min=1,this.max=12},match:function(e){return d.test(e)},validator:function(e){return this.rangeValidator(e)},filled:n,prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){return e.setHours(t),e}},HH:{init:function(){this.width=2,this.min=0,this.max=23},match:function(e){return u.test(e)},validator:function(e){return this.rangeValidator(e)},filled:n,prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){return e.setHours(t),e}},m:{init:function(){this.width=1,this.min=0,this.max=59},match:function(e){return c.test(e)},validator:function(e){return this.rangeValidator(e)},filled:i,prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){return e.setMinutes(t),e}},mm:{init:function(){this.width=2,this.min=0,this.max=59},match:function(e){return c.test(e)},validator:function(e){return this.rangeValidator(e)},filled:i,prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){return e.setMinutes(t),e}},s:{init:function(){this.width=1,this.min=0,this.max=59},match:function(e){return c.test(e)},validator:function(e){return this.rangeValidator(e)},filled:o,prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){return e.setSeconds(t),e}},ss:{init:function(){this.width=2,this.min=0,this.max=59},match:function(e){return c.test(e)},validator:function(e){return this.rangeValidator(e)},filled:o,prev:function(e){return this.getPrevIntValue(e)},next:function(e){return this.getNextIntValue(e)},format:function(e){return this.padNumber(e)},apply:function(e,t){return e.setSeconds(t),e}},MMM:{init:function(){this.min=2,this.max=12,this.width=2},match:function(){return!1},validator:function(e){return this.rangeValidator(e)},prev:function(e){return this.getPrevMonthValue("MMM",e)},next:function(e){return this.getNextMonthValue("MMM",e)},apply:function(e,t){var n=this.getIndexMonthValue("MMM",t);return n!==-1&&e.setMonth(n),e}},MMMM:{init:function(){this.min=2,this.max=12,this.width=2},match:function(){return!1},validator:function(e){var t=this.getListForMask("MMMM");return t.indexOf(e)>-1},prev:function(e){return this.getPrevMonthValue("MMMM",e)},next:function(e){return this.getNextMonthValue("MMMM",e)},apply:function(e,t){var n=this.getIndexMonthValue("MMMM",t);return n!==-1&&e.setMonth(n),e}},tt:{init:function(){this.width=2},match:function(){return!1},prev:function(e){var t=this.getPrevMonthValue("tt",e);return t===e?this.getNextMonthValue("tt",e):t},next:function(e){var t=this.getNextMonthValue("tt",e);return t===e?this.getPrevMonthValue("tt",e):t},apply:function(e,t){if(e instanceof Date){var n=e.getHours(),i=this.getCurrentCulture(),o=i.dateTimeFormatInfo;n>=12&&(n-=12),t===o.pmDesignator&&(n+=12),e.setHours(n)}return e}}}}(),DateTimeMaskPart=function(e){_.extend(this,DateTimeMaskPartStrategy[e]),this.init()};_.extend(DateTimeMaskPart.prototype,{init:function(){},filled:function(e){return null!==e&&"undefined"!=typeof e&&e.length===this.width},match:function(e){return!0},validator:function(e){return!0},fulfilled:function(e){return this.match(e)&&this.validator(e)},prev:function(e){return e},next:function(e){return e},format:function(e){return e},applyPart:function(e,t){return e},padNumber:function(e){var t="undefined"!=typeof this.width?this.width:null;e=parseInt(e,10);var n,i;return n=isNaN(e)?n="":e.toString(),i=n.length,null!==t&&in&&(e=n)),e},getPrevIntValue:function(e){var t="undefined"!=typeof this.min?this.min:null,n="undefined"!=typeof this.step?this.step:1;return e=parseInt(e,10),isNaN(e)?e=null===t?0:t:(e-=n,null!==t&&e=0?n[i]:t)},getIndexListValueForMask:function(e,t){var n=this.getListForMask(e);return"undefined"==typeof n?-1:n.indexOf(t)},getNextMonthValue:function(e,t){return this.getNextListValueForMask(e,t)},getPrevMonthValue:function(e,t){return this.getPrevListValueForMask(e,t)},getIndexMonthValue:function(e,t){return this.getIndexListValueForMask(e,t)},rangeValidator:function(e){return e=parseInt(e,10),!(isNaN(e)||ethis.max)}}),window.InfinniUI.DateTimeEditMask=DateTimeEditMask,_.extend(DateTimeEditMask.prototype,editMaskMixin),_.extend(DateTimeEditMask.prototype,{getNextItemMask:function(e){var t,n=this.getItemTemplate(e);return null!==n?(t=this.moveToNextChar(n.left+n.width),t>n.left+n.width&&(e=t)):e=this.moveToNextChar(e),e},setNextValue:function(e){var t,n,i,o=this.getItemTemplate(e);return null!==o?(t=o.item,i=this.masks[t.mask],"undefined"!=typeof i.next&&(n=i.next(t.text),"undefined"!=typeof i.format&&(n=i.format(n)),t.text=""+n,e=Math.min(o.left+t.text.length,e))):e=this.moveToNextChar(e),e},setPrevValue:function(e){var t,n,i,o=this.getItemTemplate(e);return null!==o?(t=o.item,i=this.masks[t.mask],"undefined"!=typeof i.prev&&(n=i.prev(t.text),"undefined"!=typeof i.format&&(n=i.format(n)),t.text=""+n,e=Math.min(o.left+t.text.length,e))):e=this.moveToNextChar(e),e},deleteSelectedText:function(e,t,n){var i,o,r,a,l,s=e,u=t;n=n||"";for(var d=e+n.length-1;(i=this.getItemTemplate(s))&&(l=s,o=s-i.left,r=i.item.text,a=this.masks[i.item.mask],r=r.substring(0,o)+n+r.substring(o+u),r.length&&!a.match(r)||(i.item.text=r),s=this.getNextItemMask(s),l!==s);)u=t-(s-e),n="";return this.moveToNextChar(d)},deleteCharLeft:function(e,t){var n,i,o=this.getItemTemplate(e);return t?e=this.deleteSelectedText(e,t):null!==o?o.index>0?(n=o.item,e--,i=n.text.slice(0,o.index-1)+n.text.slice(o.index),n.text=i):(o=this.getItemTemplate(o.left-1),e=o.left+o.item.text.length):e=this.moveToNextChar(e),e},deleteCharRight:function(e,t){var n,i,o=this.getItemTemplate(e);return t?e=this.deleteSelectedText(e,t):null!==o?(n=o.item,i=n.text.slice(0,o.index)+n.text.slice(o.index+1),n.text=i,0==n.text.length&&(e=this.getNextItemMask(e))):e=this.moveToNextChar(e),e},pasteStringToMask:function(e,t){function n(e){return Math.max(e.mask.length,e.text.length)}function i(n){for(var i=0,o=[],r=a;rn[r].position-i-t&&o.push(n[r]):i+=n[r].length;return o[o.length-1]}e=e.replace(/\D/gi,"");var o=e.split(""),r=this.getItemTemplate(t),a=this.template.indexOf(r.item),l=0,s=i(this.template);l=s?this.template.indexOf(s):a;for(var u=0,d=0,c=a;cd&&o.splice(d,o.length),this.template[c].text=o.join("")+this.template[c].text.slice(o.length,d))},getItemTemplate:function(e){var t,n,i,o=this.template,r=0,a=null;if("undefined"==typeof o&&(this.reset(),o=this.template),!Array.isArray(o))return null;for(var l=0,s=o.length;l=r&&e<=r+n){i=e-r,a={item:t,left:r,width:n,index:e-r};break}r+=n}return a},setCharAt:function(e,t){var n,i,o,r,a=this.getItemTemplate(t);if(null!==a)if(i=a.item,r=t-a.left,r>i.text.length?(t=a.left+i.text.length,r=i.text.length):r<0&&(t=a.left,r=0),o=this.masks[i.mask],n=i.text.slice(0,r)+e+i.text.slice(r),o.match(n))i.text=n,t=this.moveToNextChar(t),o.filled(n)&&(t=this.getNextItemMask(t));else{var l=this.template.indexOf(a.item)+1;this.template[l]===e&&(t=this.getNextItemMask(t))}else t=this.moveToNextChar(t);return t},moveToPrevChar:function(e){e-=1;for(var t,n,i,o=this.template,r=0,a=r,l=0,s=o.length;l=r&&ea&&(e=a),e},moveToNextChar:function(e){e+=1;for(var t,n,i,o,r=this.template,a=0,l=0,s=r.length;l=a&&e<=a+o)break;if(e=n&&(e=n),e},getText:function(){var e,t,n=this.template,i=[];if(Array.isArray(n)){for(var o=0,r=n.length;o=0;t-=1)if("string"!=typeof o[t]){r=o[t].position;break}return null===r?0:r+1},moveToPrevChar:function(e){e=Math.max(e,0);var t,n,i=this.template,o=i.slice(0,e),r=null,a=!1;for(t=o.length-1;t>=0;t-=1){if("string"!=typeof o[t]){r=o[t].position+(a?1:0);break}a=!0}if(null===r)for(o=i.slice(e),t=0,n=o.length;t=r&&e<=r+n){i=e-r,a={item:t,left:r,width:n,index:e-r};break}r+=n}return a},deleteCharRight:function(e,t){var n,i,o;if(t>0)return this.deleteSelectedText(e,t);for(i=0,o=this.template.length;i0)return this.deleteSelectedText(e,t);for(i=this.template.length-1;i>=0;i-=1)if(n=this.template[i],!("string"==typeof n||n.position>=e)){e=n.position,n.text="";break}return e},pasteStringToMask:function(e,t){function n(e){return Math.max(e.mask.length,e.text.length)}function i(n){for(var i=0,o=[],r=a;rn[r].position-i-t&&o.push(n[r]):i+=n[r].length;return o[o.length-1]}e=e.replace(/\D/gi,"");var o=e.split(""),r=this.getItemTemplate(t),a=this.template.indexOf(r.item),l=0,s=i(this.template);l=s?this.template.indexOf(s):a;for(var u=0,d=0,c=a;cd&&o.splice(d,o.length),this.template[c].text=o.join("")+this.template[c].text.slice(o.length,d))},clearText:function(e,t){for(var n,i,o=0,r=this.template.length;o=e&&n.position0&&this.clearText(t,n);for(var a=0,l=r.length;at)break}}return t},deleteSelectedText:function(e,t,n){var i=this.clearText(e,t);return"undefined"!=typeof n&&(i=this.setCharAt(n,e)),i},getNextItemMask:function(e){var t,n,i;for(n=this.template.length-1;n>=0;n-=1)if(t=this.template[n],"string"!=typeof t){if(t.position<=e){e="undefined"==typeof i?this.moveToNextChar(e):i;break}i=t.position}return e},getText:function(){for(var e,t=this.template,n=[],i=0,o=t.length;i0)switch(o[0]){case"n":case"N":e=this.culture.numberFormatInfo.numberDecimalSeparator;break;case"p":case"P":e=this.culture.numberFormatInfo.percentDecimalSeparator;break;case"c":case"C":e=this.culture.numberFormatInfo.currencyDecimalSeparator}return e},getDecimalDigits:function(){var e=this.getItemTemplate(),t=e.item,n=/^([npc])(\d*)$/i,i=t.mask.match(n),o=0;if(i&&i.length>0)if(""!==i[2])o=+i[2];else switch(i[0]){case"n":case"N":o=this.culture.numberFormatInfo.numberDecimalDigits;break;case"p":case"P":o=this.culture.numberFormatInfo.percentDecimalDigits;break;case"c":case"C":o=this.culture.numberFormatInfo.currencyDecimalDigits}return o},reset:function(e){this.value=null,"undefined"!=typeof e&&null!==e&&""!==e&&(e=+e,isNaN(e)&&(e=null),this.value=e),this.template=this.buildTemplate(e)},buildTemplate:function(e){var t=/([npc])(\d*)/i,n=this.mask,i=[],o=this;return n.replace(t,function(t,n,r,a,l){i.push(l.slice(0,a)),i.push({mask:t,text:null===e?"":o.formatMask(e,t),value:e}),i.push(l.substring(a+t.length))}),this.template=i},getText:function(){var e,t=[];if(Array.isArray(this.template)){for(var n=0,i=this.template.length;n0?e-1:0;var t,n,i=this.getItemTemplate(),o=i.item,r=o.text;if(e=i.left&&t<=i.left+a.length)if(n=t-o,e==l)null===r.value&&(r.value=0,r.text=this.formatMask(r.value,r.mask)),r.text.indexOf(l)!==-1&&(t=o+r.text.indexOf(l)+l.length);else if(/\d/.test(e)){var s;s=a.indexOf(l)>-1&&n>a.indexOf(l),r.value=this.parseText([a.slice(0,n),e,a.slice(n)].join(""),r.value),r.text=this.formatMask(r.value,r.mask),""===a?t=this.moveToNextChar(o):(t=s?t+1:t+r.text.length-a.length,t=Math.min(t,o+this.getIndexOfEndDigit(r.text)))}return t},updateDigitValue:function(e,t){var n,i=this.getItemTemplate(),o=i.left,r=i.item,a=r.text;if(ei.left+a.length)return this.moveToNextChar(e);if(n=e-o,n>0){var l=a.substr(n-1,1);/\d/.test(l)&&(l=parseInt(l,10)+t,l>9&&(l=9),l<0&&(l=0),r.value=this.parseText([a.slice(0,n-1),l,a.slice(n)].join(""),r.value),r.text=this.formatMask(r.value,r.mask))}return e},setNextValue:function(e){return this.updateDigitValue(e,1)},setPrevValue:function(e){return this.updateDigitValue(e,-1)},deleteSelectedText:function(e,t,n){function i(e,t){return e.slice(0,t).split(" ").length-1}var o=this.getItemTemplate(),r=o.item,a=r.text,l=null===r.value||"undefined"==typeof r.value?"":r.value.toString(),s=t+e;n||(n="");var u=a.slice(0,e),d=a.slice(0,s),c=u.split(" ").length-1,p=d.split(" ").length-1;e-=c,s-=p;var h=l.slice(0,e)+n+l.slice(s,l.length),m=this.formatMask(h,r.mask);return n?(e+=n.length+c,e+=i(m,e)):e+=i(m,e),_.isEmpty(h)&&(h=null),this.reset(h),h?e:0},deleteCharRight:function(e,t){if(t>0)return this.deleteSelectedText(e,t);var n,i=this.getItemTemplate(),o=i.left,r=i.item,a=r.text,l=this.getDecimalSeparator();if(ei.left+a.length)return this.moveToNextChar(0);if(a.length===t)return this.clearValue(r);n=e-o;var s=a.indexOf(l),u=a.substr(n).search(/\d/);if(0===r.value)r.value=null,r.text=this.formatMask(r.value,r.mask),e=o;else if(u>-1){u+=n;var d=a.split(l);n===d[0].length?r.value=this.parseText(d[0],r.value):r.value=this.parseText([a.substr(0,u),a.substr(u+1)].join(""),r.value),r.text=this.formatMask(r.value,r.mask),ui.left+a.length)return this.moveToNextChar(0);var u=this.getDecimalDigits();if(n=e-o,a.length===t)return this.clearValue(r);var d=!1;if(n<=0)return e;s>-1&&(d=n>s,n===a.length-u&&(n-=l.length,e-=l.length));var c=a.slice(0,n),p=/\d/.test(c)?c.length-c.split("").reverse().join("").search(/\d/)-1:0;return r.value=this.parseText(a.slice(0,p)+a.slice(p+1),r.value),r.text=this.formatMask(r.value,r.mask),e=d?e-1:e+r.text.length-a.length,0===r.value&&e<=1&&(r.value=null,r.text=this.formatMask(r.value,r.mask),e=o),e},getValue:function(){var e,t=this.getItemTemplate();return t&&(e=t.item.value),e},getIndexOfEndDigit:function(e){var t=e.split("").reverse().join("").search(/\d/);return t===-1?t:e.length-t},parseText:function(e,t){var n,i=this.getItemTemplate(),o=i.item,r=o.mask,a=this.getDecimalSeparator(),l=this.getDecimalDigits(),s=e.split(a);return s=s.map(function(e,t){var n=e.replace(/[^\d]/g,"");return 1===t?n.substr(0,l):n}),e=s.join("."),""===e?n=null:(n=+e,t<0&&(n=-n),/^p/.test(r)&&(n/=100)),n},getItemTemplate:function(){var e,t=this.template,n=0,i=null;if("undefined"==typeof t&&(this.reset(),t=this.template),!Array.isArray(t))return null;for(var o=0,r=t.length;o0){var o=i[0];if(!jQuery.contains(document,o.control.controlView.el))return;o.setFocus&&o.setFocus(),e()}},1e3/3);setTimeout(e,3e3)}}};window.InfinniUI.InlineViewBuilder=InlineViewBuilder,window.InfinniUI.LinkView=LinkView,_.extend(LinkView.prototype,{setOpenMode:function(e){_.isEmpty(e)||(this.openMode=e)},getOpenMode:function(){return this.openMode},setContainer:function(e){this.containerName=e},setViewTemplate:function(e){this.viewTemplate=e},setDialogWidth:function(e){e=e.toLowerCase(),"extralarge"==e&&(e="100%"),this.dialogWidth=e},createView:function(e){function t(t){n.view=t,n._initViewHandler(t),e(t)}var n=this;this.viewTemplate(t)},_initViewHandler:function(e){var t,n,i=this,o=i.openMode;switch(e.setParent&&e.setParent(this.parent),window.InfinniUI.global.messageBus.send("onViewCreated",{openMode:o,view:e}),o){case"Container":n=InfinniUI.global.containers[this.containerName],t=new OpenModeContainerStrategy,t.setView(e),t.setContainer(n),e.setOpenStrategy(t);break;case"Dialog":t=new OpenModeDialogStrategy,t.setView(e),this.dialogWidth&&t.setDialogWidth(this.dialogWidth),t.setView(e),e.setOpenStrategy(t)}}}),window.InfinniUI.MetadataViewBuilder=MetadataViewBuilder,_.extend(MetadataViewBuilder.prototype,{build:function(e,t){var n=t.metadata,i=this.getParentViewByOpenMode(t,n.OpenMode),o=this.buildViewTemplate(t,i),r=new LinkView(i);return r.setViewTemplate(o),"OpenMode"in n&&r.setOpenMode(n.OpenMode),"Container"in n&&r.setContainer(n.Container),"DialogWidth"in n&&r.setDialogWidth(n.DialogWidth),r},buildViewTemplate:function(e,t){var n=e.metadata,i=this;return function(o){var r=window.InfinniUI.providerRegister.build("MetadataDataSource",n);r.getMetadata(function(r){if(null==r)return InfinniUI.global.logger.error("view metadata not found"),void InfinniUI.global.messageBus.send(messageTypes.onViewBuildError,{error:"metadata not found",metadata:n});var a=function(){var e=Array.prototype.slice.call(arguments);o.apply(null,e)};i.buildViewByMetadata(e,r,t,a)})}},buildViewByMetadata:function(e,t,n,i){var o=e.builder,r=this.buildParameters(e),a=o.buildType("View",t,{parentView:n,parent:n,params:r,suspended:e.suspended});i(a)},buildParameters:function(e){var t,n=e.metadata.Parameters,i=e.builder,o=e.parentView,r={};if("undefined"!=typeof n&&null!==n)for(var a=0;a'),e.find(".lastfocuselementinmodal").on("focusin",function(){e.find(".firstfocuselementinmodal").focus()}),e.keydown(function(t){$(document.activeElement).hasClass("lastfocuselementinmodal")&&9==(t.which||t.keyCode)&&(t.preventDefault(),e.find(".firstfocuselementinmodal").focus()),$(document.activeElement).hasClass("firstfocuselementinmodal")&&9==(t.which||t.keyCode)&&t.shiftKey&&(t.preventDefault(),e.find(".lastfocuselementinmodal").focus())})},close:function(){this.$modal&&this.$modal.modal("hide")},cleanup:function(){this.view.remove(),this.$modal.remove(),InfinniUI.ModalWindowService.modalWasClosed(this.$modal)}}),window.InfinniUI.ScriptBuilder=ScriptBuilder,ScriptBuilder.prototype.build=function(e,t){var n=t.metadata,i=n.Name,o=n.Body,r=new Function("context","args",o);return function(e,t){var n;try{n=r.call(void 0,e,t)}catch(a){console.groupCollapsed("%2$s: %1$c%3$s","color: #ff0000",i,a.message),console.error(o),console.groupEnd()}return n}},window.InfinniUI.ScriptExecutor=ScriptExecutor,ScriptExecutor.prototype.executeScript=function(e,t){var n,i,o,r=this.parent,a=r.getContext();return"{"==e.substr(0,1)?(i=e.substr(1,e.length-2),o=this.buildScriptByBody(i)):(o=r.getScripts().getById(e),o&&(o=o.func)),a&&o&&(n=o.call(void 0,a,t)),n},ScriptExecutor.prototype.buildScriptByBody=function(e){var t=this.parent.getContext(),n={metadata:{Body:e,Name:"InlineScript"}},i=new ScriptBuilder;return i.build(t,n)},InfinniUI.ModalWindowService=function(){function e(){var e=window.InfinniUI.global.messageBus;e.send("OnChangeLayout",{})}var t=[];return{modalWasOpened:function(e){if(0!=t.length){var n=t[t.length-1];n.modal.addClass("invisible"),n.background.addClass("invisible")}t.push(e)},modalWasClosed:function(n){for(var i=0,o=t.length;i0&&(u("on"),p())},s=function(t,n,i){r[t]||(r[t]=[],e&&e.on(t,c(t))),r[t].push({context:i,callback:n}),!a&&e&&p()},u=function(t){for(var n in r)"on"===t?e.on(n,c(n)):e.off(n)},d=function(t,n){if(n){for(var i=r[t],o=0,a=i.lenght;o0?_.debounce(this.onRequestsChanged.bind(this),50):this.onRequestsChanged.bind(this);this.on("change:requests",i)},onDataLoading:function(){var e=this.get("requests");this.set("requests",e+1)},onDataLoaded:function(){var e=this.get("requests");this.set("requests",e-1)},onRequestsChanged:function(e,t){this.set("progress",t>0)}}),AjaxLoaderIndicatorView=Backbone.View.extend({className:"pl-ajaxloader",template:InfinniUI.Template["services/ajaxLoaderIndicator/template/template.tpl.html"],hiddenClassName:"hidden",initialize:function(){this.listenTo(this.model,"change:progress",this.updateProgress)},render:function(){return this.$el.html(this.template()),this.updateProgress(),this},updateProgress:function(){var e=this.model.get("progress");this.$el.toggleClass(this.hiddenClassName,!e)}});InfinniUI.ContextMenuService=function(){function e(e){return e.control.controlView.$el}function t(e,t){e.on("contextmenu",function(e){e.preventDefault(),n.send(messageTypes.onOpenContextMenu.name,{x:e.pageX,y:e.pageY})})}var n=window.InfinniUI.global.messageBus;n.subscribe(messageTypes.onContextMenu.name,function(n,i){var o=i.value;t(e(o.source),o.content)})}();var MessageBox=Backbone.View.extend({tagName:"div",className:"modal fade messagebox",UI:{firstfocuselementinmodal:".firstfocuselementinmodal",lastfocuselementinmodal:".lastfocuselementinmodal"},events:{"click .btn":"onClickButtonHandler","focusin .lastfocuselementinmodal":"onFocusinLastElement",keydown:"onKeydownHandler"},template:InfinniUI.Template["services/messageBox/template/default.tpl.html"],initialize:function(e){this.setOptions(e),$(document.activeElement).blur(),this.render(),this.bindUIElements(),this.$el.modal({show:!0})},setOptions:function(e){this.options=this.applyDefaultOptions(e)},onFocusinLastElement:function(){this.ui.firstfocuselementinmodal.focus()},onKeydownHandler:function(e){document.activeElement===this.ui.lastfocuselementinmodal[0]&&9==(e.which||e.keyCode)&&(e.preventDefault(),this.ui.firstfocuselementinmodal.focus()),document.activeElement===this.ui.firstfocuselementinmodal[0]&&9==(e.which||e.keyCode)&&e.shiftKey&&(e.preventDefault(),this.ui.lastfocuselementinmodal.focus())},render:function(){var e=this.options.$parent||$("body"),t=this.template(this.options);return this.$el.html(t),this.subscribeToDialog(),e.append(this.$el),this},subscribeToDialog:function(){var e=this;this.$el.on("shown.bs.modal",function(t){e.ui.firstfocuselementinmodal.focus()}),this.$el.on("hidden.bs.modal",function(){e.remove()})},onClickButtonHandler:function(e){e.preventDefault();var t=$(e.target),n=parseInt(t.data("index"),10),i=this.options.buttons[n].onClick;i&&i.apply(null),this.close()},close:function(){"function"==typeof this.options.onClose&&this.options.onClose.call(null),this.$el.modal("hide")},applyDefaultOptions:function(e){var t=_.defaults({},e,{type:"default",buttons:[]});return this.applyDefaultButtonsOptions(t),t},applyDefaultButtonsOptions:function(e){return e.buttons.filter(function(e){return"undefined"==typeof e.type}).forEach(function(e){e.type="default"}),e}});_.extend(MessageBox.prototype,bindUIElementsMixin),InfinniUI.MessageBox=MessageBox;var routerService=function(e){if(!e)return null;var t=function(e){var t={};t.routes={};for(var n=0,o=e.length;n/g;r=l.exec(e[n].Path);)a=r[0].replace(/\s+/g,"").slice(2,-2),e[n].Path=e[n].Path.slice(0,r.index)+":"+a+e[n].Path.slice(r.index+r[0].length),l.lastIndex=r.index+a.length;t.routes[e[n].Path.slice(1)]=e[n].Name,t[e[n].Name]=i(e[n].Name,e[n].Action)}return t},n=function(t,n){for(var i=n||"yes",o=0,r=e.length;o\r\n\r\n
\r\n \r\n \r\n
\r\n\r\n\r\n\r\n';}return __p}; -this["InfinniUI"]["Template"]["controls/dateTimePicker/template/select.date.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '
\r\n\r\n\r\n
\r\n
\r\n \r\n \r\n \r\n
\r\n\r\n';}return __p}; +this["InfinniUI"]["Template"]["controls/dateTimePicker/template/select.date.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '
\r\n\r\n\r\n\r\n\r\n';}return __p}; -this["InfinniUI"]["Template"]["controls/dateTimePicker/template/select.dateTime.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '
\r\n\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n
\r\n\r\n\r\n';}return __p}; +this["InfinniUI"]["Template"]["controls/dateTimePicker/template/select.dateTime.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '
\r\n\r\n\r\n\r\n\r\n';}return __p}; -this["InfinniUI"]["Template"]["controls/dateTimePicker/template/select.time.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '
\r\n\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n\r\n\r\n';}return __p}; +this["InfinniUI"]["Template"]["controls/dateTimePicker/template/select.time.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '
\r\n\r\n\r\n\r\n\r\n';}return __p}; this["InfinniUI"]["Template"]["controls/dateTimePicker/template/time.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '', __e = _.escape;with (obj) {__p += '\r\n\r\n
\r\n \r\n \r\n
\r\n\r\n\r\n\r\n';}return __p}; -this["InfinniUI"]["Template"]["controls/fileBox/template/template.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '', __e = _.escape;with (obj) {__p += '
\r\n \r\n\r\n
\r\n Файл не выбран...\r\n\r\n filename.ext\r\n\r\n \r\n filename.ext\r\n \r\n\r\n \r\n \r\n\r\n \r\n \r\n\r\n
\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n \r\n
\r\n';}return __p}; +this["InfinniUI"]["Template"]["controls/fileBox/template/template.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '', __e = _.escape;with (obj) {__p += '
\r\n \r\n\r\n
\r\n ' +((__t = (window.InfinniUI.localized.strings.FileBox.noFile)) == null ? '' : __t) +'\r\n\r\n filename.ext\r\n\r\n \r\n filename.ext\r\n \r\n\r\n \r\n \r\n\r\n \r\n \r\n\r\n
\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n \r\n
\r\n';}return __p}; this["InfinniUI"]["Template"]["controls/form/template/form.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '', __j = Array.prototype.join;function print() { __p += __j.call(arguments, '') }with (obj) { items.forEach(function(item, index){;__p += '\n
\n';});;__p += '\n';}return __p}; @@ -47,7 +47,7 @@ this["InfinniUI"]["Template"]["controls/frame/template/frame.tpl.html"] = functi this["InfinniUI"]["Template"]["controls/gridPanel/template/row.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '
';}return __p}; -this["InfinniUI"]["Template"]["controls/imageBox/template/imageBox.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '', __e = _.escape;with (obj) {__p += '
\r\n \r\n \r\n
\r\n\r\n
\r\n \r\n \r\n
\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n';}return __p}; +this["InfinniUI"]["Template"]["controls/imageBox/template/imageBox.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '', __e = _.escape;with (obj) {__p += '
\r\n
\r\n \r\n
\r\n \r\n
\r\n\r\n
\r\n \r\n \r\n
\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n';}return __p}; this["InfinniUI"]["Template"]["controls/indeterminateCheckBox/template/indeterminateCheckBox.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '', __e = _.escape;with (obj) {__p += '
\n \n
\n';}return __p}; @@ -111,15 +111,15 @@ this["InfinniUI"]["Template"]["controls/dataGrid/dataGridRow/template/multiSelec this["InfinniUI"]["Template"]["controls/dataGrid/dataGridRow/template/singleSelect.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '\r\n
\r\n \r\n
\r\n';}return __p}; -this["InfinniUI"]["Template"]["controls/dataNavigation/buttons/template/next.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '»';}return __p}; +this["InfinniUI"]["Template"]["controls/dataNavigation/buttons/template/next.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '»';}return __p}; -this["InfinniUI"]["Template"]["controls/dataNavigation/buttons/template/page.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '', __e = _.escape;with (obj) {__p += '' +__e(pageNumber + 1) +'';}return __p}; +this["InfinniUI"]["Template"]["controls/dataNavigation/buttons/template/page.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '', __e = _.escape;with (obj) {__p += '' +__e(pageNumber + 1) +'';}return __p}; -this["InfinniUI"]["Template"]["controls/dataNavigation/buttons/template/prev.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '«';}return __p}; +this["InfinniUI"]["Template"]["controls/dataNavigation/buttons/template/prev.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '«';}return __p}; this["InfinniUI"]["Template"]["controls/dataNavigation/pageSizes/template/pageSizes.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '', __j = Array.prototype.join;function print() { __p += __j.call(arguments, '') }with (obj) {__p += '';}return __p}; -this["InfinniUI"]["Template"]["controls/dateTimePicker/template/date/days.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n Время\r\n
';}return __p}; +this["InfinniUI"]["Template"]["controls/dateTimePicker/template/date/days.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n';}return __p}; this["InfinniUI"]["Template"]["controls/dateTimePicker/template/date/months.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
';}return __p}; @@ -131,7 +131,7 @@ this["InfinniUI"]["Template"]["controls/dateTimePicker/template/time/minutes.tpl this["InfinniUI"]["Template"]["controls/dateTimePicker/template/time/seconds.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
00051015
20253035
40455055
\r\n
';}return __p}; -this["InfinniUI"]["Template"]["controls/dateTimePicker/template/time/time.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n 12\r\n :\r\n 14\r\n :\r\n 00\r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n';}return __p}; +this["InfinniUI"]["Template"]["controls/dateTimePicker/template/time/time.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n 12\r\n :\r\n 14\r\n :\r\n 00\r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n';}return __p}; this["InfinniUI"]["Template"]["controls/label/commonView/template/label.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '\n';}return __p}; @@ -159,10 +159,10 @@ this["InfinniUI"]["Template"]["controls/tabPanel/tabHeader/template/tabHeader.tp this["InfinniUI"]["Template"]["controls/tabPanel/tabPage/template/tabPage.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '', __j = Array.prototype.join;function print() { __p += __j.call(arguments, '') }with (obj) {__p += '
\n '; items.forEach(function(item, index){;__p += '\n
\n ';});;__p += '\n
';}return __p}; -this["InfinniUI"]["Template"]["controls/comboBox/dropdown/group/template/template.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '
\n
';}return __p}; - this["InfinniUI"]["Template"]["controls/comboBox/dropdown/template/group/template.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '
\n\n\n \n \n \n\n
\n
\n \n
\n
\n По запросу "" ничего не найдено\n
\n\n
\n \n
\n
\n\n';}return __p}; this["InfinniUI"]["Template"]["controls/comboBox/dropdown/template/plain/template.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '
\n\n
\n
\n \n
\n
\n По запросу "" ничего не найдено\n
\n
\n \n
\n
\n';}return __p}; -this["InfinniUI"]["Template"]["extensions/loginForm/template/loginForm.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '', __e = _.escape;with (obj) {__p += '\r\n\r\n';}return __p}; \ No newline at end of file +this["InfinniUI"]["Template"]["controls/comboBox/dropdown/group/template/template.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '';with (obj) {__p += '
\n
';}return __p}; + +this["InfinniUI"]["Template"]["extensions/loginForm/template/loginForm.tpl.html"] = function(obj) {obj || (obj = {});var __t, __p = '', __e = _.escape;with (obj) {__p += '\r\n\r\n';}return __p}; \ No newline at end of file diff --git a/out/unitTest.js b/out/unitTest.js new file mode 100644 index 0000000..bbacbbd --- /dev/null +++ b/out/unitTest.js @@ -0,0 +1,16330 @@ +'use strict'; +var FakeRestDataProvider = function(){ + _.superClass(FakeRestDataProvider, this); +}; + +_.inherit(FakeRestDataProvider, InfinniUI.Providers.RestDataProvider); + +_.extend( FakeRestDataProvider.prototype, { + + items: [], + lastSendedUrl: '', + + send: function(type, successHandler, errorHandler){ + var requestId = Math.round((Math.random() * 100000)); + var params = this.requestParams[type]; + var that = this; + + + var urlString = params.origin + params.path; + var queryString; + + if(type == 'get' && _.size(params.data) > 0){ + queryString = InfinniUI.StringUtils.joinDataForQuery(params.data); + urlString = urlString + '?' + queryString; + } + + FakeRestDataProvider.prototype.lastSendedUrl = urlString; + + setTimeout(function(){ + successHandler({ + requestId: requestId, + data: { + Result: { + Items:that.items + } + } + }); + }, 1); + + return requestId; + } + +}); + +describe('Builder', function () { + var builder; + + beforeEach(function () { + builder = new InfinniUI.Builder(); + }); + + describe('build', function () { + it('should return null if no builder found', function () { + var view = builder.buildType('IncorrectType', null, {parentView: fakeView()}); + + assert.isNull(view); + }); + + it('should find builder by metadataValue if no metadataType passed', function () { + var viewFactory = function () { + return 42; + }; + + builder.register('TextBox', { build: viewFactory}); + assert.equal(builder.build({ TextBox: {} }), 42); + }); + + it('should pick concrete value from metadata if no metadataType passed', function (done) { + var viewBuilder = { + build: function (context, args) { + assert.isNotNull(args.metadata.Name); + assert.isNotNull(args.metadata.Multiline); + + assert.equal(args.metadata.Name, 'TextBox'); + assert.isTrue(args.metadata.Multiline); + done(); + } + }; + + builder.register('TextBox', viewBuilder); + builder.build({ TextBox: { Name: 'TextBox', Multiline: true } }); + }); + }); + + describe('register', function () { + it('should have builder after register', function () { + var viewFactory = function () { + return 42; + }; + builder.register('TextBox', { build: viewFactory}); + + assert.equal(builder.buildType('TextBox', null, { parentView: fakeView() }), 42); + }); + }); +}); + +function FakeDataProvider(mode) { + + var items = [ + { + "Id": '1', + "FirstName": "Иван", + "LastName": "Иванов" + }, + { + "Id": '2', + "FirstName": "Петр", + "LastName": "Петров" + }, + { + "Id": '3', + "FirstName": "Иван1", + "LastName": "Иванов1" + }, + { + "Id": '4', + "FirstName": "Петр2", + "LastName": "Петров2" + }, + { + "Id": '5', + "FirstName": "Иван3", + "LastName": "Иванов3" + }, + { + "Id": '6', + "FirstName": "Петр4", + "LastName": "Петров5" + }, + { + "Id": '10', + "FirstName": "Анна", + "LastName": "Сергеева" + + } + ]; + + var itemsUpdated = [ + { + "Id": '4', + "FirstName": "Федор", + "LastName": "Федоров" + }, + { + "Id": '5', + "FirstName": "Сидор", + "LastName": "Сидоров" + } + ]; + + this.getItems = function (resultCallback, criteriaList, pageNumber, pageSize, sorting) { + if (mode === undefined || mode() === 'Created') { + + var result = items; + /*var allItems = items; + + for (var i = 0; i < pageSize; i++) { + var itemIndex = i + (pageNumber * pageSize); + if (itemIndex < allItems.length) { + result.push(items[itemIndex]); + } + else { + break; + } + } + + if(criteriaList && criteriaList.length == 1 && criteriaList[0].CriteriaType == 1){ + result = _.filter(result, function(item){ + return item.Id == criteriaList[0].Value; + }); + }*/ + + setTimeout(function(){ + resultCallback({data:result}); + }, 100); + + } + else { + setTimeout(function(){ + resultCallback(itemsUpdated); + }, 100); + } + }; + + this.createItem = function (resultCallback) { + setTimeout(function(){ + resultCallback({prefilledField: 1, Id:1, __Id:1}); + },100); + + }; + + this.saveItem = function (value, resultCallback, warnings) { + + var itemIndex = -1; + + for (var i = 0; i < items.length; i++) { + if (items[i]._id === value._id) { + itemIndex = i; + break; + } + } + + if (itemIndex !== -1) { + items[itemIndex] = value; + } + else { + items.push(value); + } + + setTimeout(function(){ + resultCallback(items); + },90); + }; + + this.deleteItem = function (value, resultCallback) { + var itemIndex = items.indexOf(value); + items.splice(itemIndex, 1); + resultCallback(items); + }; + + this.getItem = function (itemId, resultCallback) { + for (var i = 0; i < items.length; i++) { + if (items[i].Id === itemId) { + resultCallback([items[i]]); + return; + } + } + resultCallback(null); + }; + + this.createIdFilter = function(id){ + return [{ + "Property": "Id", + "Value": id, + "CriteriaType": 1 + }]; + }; + + this.setCreateAction = function(){}; + this.setUpdateAction = function(){}; + this.setReadAction = function(){}; + this.setDeleteAction = function(){}; +} + +var FakeDocumentDataProvider = function(){ + _.superClass(FakeDocumentDataProvider, this); +}; + +_.inherit(FakeDocumentDataProvider, InfinniUI.Providers.RestDataProvider); + +_.extend( FakeDocumentDataProvider.prototype, { + + items: [], + lastSendedUrl: '', + + send: function(type, successHandler, errorHandler){ + var requestId = Math.round( (Math.random() * 100000) ); + var params = this.requestParams[type]; + var that = this; + var filter; + + + var urlString = params.origin + params.path; + var queryString; + + if( type == 'get' && _.size(params.data) > 0 ){ + queryString = this.joinDataForQuery(params.data); + urlString = urlString + '?' + queryString; + } + + FakeDocumentDataProvider.prototype.lastSendedUrl = urlString; + + filter = this.splitUrl(urlString).query.filter; + + setTimeout(function(){ + successHandler({ + requestId: requestId, + data: that.InfinniUI.FilterItems( that.items, filter ) + }); + }, 1); + + return requestId; + }, + + splitUrl: function(url){ + var result = { + origin: '', + paths: [], + query: {} + }, + tmpPaths, + tmpPathsLength, + tmpQuery, + tmpQueryItem; + + tmpPaths = url.split('/'); + + result.origin = tmpPaths[0]; + tmpPaths.splice(0, 1); + + tmpPathsLength = tmpPaths.length; + + if( tmpPathsLength > 0 ){ + tmpQuery = tmpPaths[tmpPathsLength - 1].split('?'); + if(tmpQuery.length > 1){ + tmpPaths[tmpPathsLength - 1] = tmpQuery[0]; + tmpQuery = tmpQuery[1].split('&'); + + for( var i = 0, ii = tmpQuery.length; i < ii; i++ ){ + tmpQueryItem = tmpQuery[i].split('='); + result.query[tmpQueryItem[0]] = tmpQueryItem[1]; + } + } + } + + return result; + }, + + filterItems: function(items, filter){ + + if(!filter){ + return items; + } + + var fu; + var result = JSON.parse(JSON.stringify(items)); + + filter = filter.replace(/([a-zA-Z_][A-Za-z0-9_\.]*)\s*[,)$]/g, function(a,b){ + var last = a[a.length - 1]; + if(last != ',' && last != ')'){ + last = ''; + } + return '"' + b + '"' + last; + }); + + fu = new Function('resultItems', 'eq', 'and', 'return ' + filter + ';'); + + return fu(result, eq, and); + + + function eq(param, value){ + var tmpResult = []; + for(var i = 0, ii = result.length; i/', + Data: { + a: 2, + b: '<%param2%>' + }, + Params: { + param1: 4, + param2: 'abc' + } + } + }; + + // When + var serverAction = builder.build(metadata, {parentView: fakeView()}); + + // Then + assert.equal(serverAction.getProperty('contentType'), 'application/json'); + assert.equal(serverAction.getProperty('method'), 'post'); + assert.equal(serverAction.getProperty('origin'), 'http://some.ru'); + assert.equal(serverAction.getProperty('path'), '/some/<%param1%>/'); + + assert.equal(serverAction.getParam('param1'), 4); + assert.equal(serverAction.getParam('param2'), 'abc'); + }); + + it('should update param from binding', function () { + // Given + var builder = new InfinniUI.ApplicationBuilder(); + + var label = new InfinniUI.Label(); + label.setName('Label_1'); + label.setValue('oldValue'); + + var view = new InfinniUI.View(); + view.registerElement(label); + + var metadata = { + ServerAction: { + Origin: 'http://some.ru', + Path: '/some/<%param1%>/', + Params: { + param: { + Source: 'Label_1', + Property: 'value' + } + } + } + }; + + var serverAction = builder.build(metadata, {parentView: view}); + + // When + assert.equal(serverAction.getParam('param'), 'oldValue'); + label.setValue('newValue'); + + // Then + assert.equal(serverAction.getParam('param'), 'newValue'); + }); + + describe('should constract correct url', function () { + it('get', function () { + // Given + window.InfinniUI.providerRegister.register('ServerActionProvider', function () { + return { + request: function (requestData) { + window.serverActionTest_urlParams = requestData; + } + }; + }); + + var builder = new InfinniUI.ApplicationBuilder(); + var metadata = { + ServerAction: { + Origin: 'http://some.ru', + Path: '/some/<%param1%>', + Data: { + a: 2, + b: '<%param2%>' + }, + Params: { + param1: 4, + param2: 6 + } + } + }; + + var serverAction = builder.build(metadata, {parentView: fakeView()}); + + // When + serverAction.execute(); + + // Then + assert.equal(window.serverActionTest_urlParams.method, 'GET'); + assert.equal(window.serverActionTest_urlParams.requestUrl, 'http://some.ru/some/4?a=2&b=6'); + assert.equal(window.serverActionTest_urlParams.contentType, 'application/x-www-form-urlencoded; charset=utf-8'); + }); + + + it('post', function () { + // Given + window.InfinniUI.providerRegister.register('ServerActionProvider', function () { + return { + request: function (requestData) { + window.serverActionTest_urlParams = requestData; + } + }; + }); + + var builder = new InfinniUI.ApplicationBuilder(); + var metadata = { + ServerAction: { + Method: 'Post', + ContentType: false, + Origin: 'http://some.ru', + Path: '/some/<%param1%>', + Data: { + a: 2, + b: 'user#<%param2%>' + }, + Params: { + param1: 4, + param2: 6 + } + } + }; + + var serverAction = builder.build(metadata, {parentView: fakeView()}); + + // When + serverAction.execute(); + + // Then + assert.equal(window.serverActionTest_urlParams.method, 'POST'); + assert.equal(window.serverActionTest_urlParams.requestUrl, 'http://some.ru/some/4'); + assert.equal(window.serverActionTest_urlParams.contentType, false); + assert.deepEqual(window.serverActionTest_urlParams.args, {a: 2, b: "user#6"}); + }); + + it('should convert data to string JSON if contentType is application/json', function () { + // Given + window.InfinniUI.providerRegister.register('ServerActionProvider', function () { + return { + request: function (requestData) { + window.serverActionTest_urlParams = requestData; + } + }; + }); + + var builder = new InfinniUI.ApplicationBuilder(); + var metadata = { + ServerAction: { + Method: 'Post', + ContentType: 'application/json; charset=utf-8', + Origin: 'http://some.ru', + Path: '', + Data: { + a: 2, + b: 'abc' + } + } + }; + + var serverAction = builder.build(metadata, {parentView: fakeView()}); + + // When + serverAction.execute(); + + // Then + assert.equal(window.serverActionTest_urlParams.args, '{"a":2,"b":"abc"}'); + }); + }); + + + it('should escape quote in Data', function () { + var data; + // Given + window.InfinniUI.providerRegister.register('ServerActionProvider', function () { + return { + request: function (requestData) { + data = requestData; + } + }; + }); + + var builder = new InfinniUI.ApplicationBuilder(); + var json = {"name": "value"}; + var metadata = { + ServerAction: { + Origin: 'http://some.ru', + Path: '/json', + Method: 'POST', + Data: { + b: '<%param1%>' + }, + Params: { + param1: JSON.stringify(json) + } + } + }; + + var serverAction = builder.build(metadata, {parentView: fakeView()}); + + // When + serverAction.execute(); + + // Then + assert.equal(data.args.b, JSON.stringify(json)); + }); + + it('should keep data type', function () { + var data; + // Given + window.InfinniUI.providerRegister.register('ServerActionProvider', function () { + return { + request: function (requestData) { + data = requestData; + } + }; + }); + + var builder = new InfinniUI.ApplicationBuilder(); + + var metadata = { + ServerAction: { + Origin: 'http://some.ru', + Path: '/json', + Method: 'POST', + Data: { + "Number": '<%paramNumber%>', + "String": '<%paramString%>', + "Null": '<%paramNull%>' + }, + Params: { + paramNumber: 1, + paramString: 'text', + paramNull: null + } + } + }; + + var serverAction = builder.build(metadata, {parentView: fakeView()}); + + // When + serverAction.execute(); + + // Then + assert.equal(JSON.stringify(data.args), JSON.stringify({"Number": 1, "String": "text", "Null": null})); + }); + + it('should use "config.serverUrl" as "Origin" by default', function () { + var data; + // Given + var oldServerUrl = window.InfinniUI.config.serverUrl; + + window.InfinniUI.config.serverUrl = 'ftp://ftp.site.org/'; + + window.InfinniUI.providerRegister.register('ServerActionProvider', function () { + return { + request: function (requestData) { + data = requestData; + } + }; + }); + + var builder = new InfinniUI.ApplicationBuilder(); + + var metadata = { + ServerAction: { + Path: '/public', + Method: 'POST', + Data: { + "Number": '<%paramNumber%>', + "String": '<%paramString%>', + "Null": '<%paramNull%>' + }, + Params: { + paramNumber: 1, + paramString: 'text', + paramNull: null + } + } + }; + + var serverAction = builder.build(metadata, {parentView: fakeView()}); + + // When + serverAction.execute(); + + // Then + assert.equal(data.requestUrl, 'ftp://ftp.site.org/public'); + }); + +}); + +describe('UpdateAction', function () { + it('successful build', function () { + // Given + var view = new InfinniUI.View(); + var dataSource = new InfinniUI.ObjectDataSource({ name: 'MainDS', view: view }); + var builder = new InfinniUI.ApplicationBuilder(); + + view.getDataSources().push(dataSource); + + var metadata = { + UpdateAction: { + DestinationValue: { + Source: 'MainDS' + } + } + }; + + // When + var updateAction = builder.build(metadata, {parentView: view}); + + // Then + assert.isNotNull( updateAction ); + assert.isNotNull( updateAction.execute, 'action should have execute' ); + }); + + it('should update DataSource', function () { + // Given + var view = new InfinniUI.View(); + var dataSource = new InfinniUI.ObjectDataSource({ name: 'MainDS', view: view }); + var builder = new InfinniUI.UpdateActionBuilder(); + + window.dsWasUpdated = false; + + view.getDataSources().push(dataSource); + dataSource.onItemsUpdated(function(){ + window.dsWasUpdated = true; + }); + + var metadata = { + DestinationValue: { + Source: 'MainDS' + } + }; + + var updateAction = builder.build(null, {parentView: view, metadata: metadata}); + + assert.isFalse(window.dsWasUpdated, 'initial data is invalid'); + + // When + updateAction.execute(); + + // Then + assert.isTrue(window.dsWasUpdated, 'ds should be update'); + }); + + it('should call onExecuted', function () { + // Given + var view = new InfinniUI.View(); + var dataSource = new InfinniUI.ObjectDataSource({ name: 'MainDS', view: view }); + var builder = new InfinniUI.UpdateActionBuilder(); + + view.getDataSources().push(dataSource); + + var metadata = { + "OnExecuted": "{ window.onExecutedWasCalled = true; }", + DestinationValue: { + Source: 'MainDS' + } + }; + + var updateAction = builder.build(null, {parentView: view, metadata: metadata}); + + assert.isUndefined(window.onExecutedWasCalled); + + // When + updateAction.execute(); + + // Then + assert.isTrue(window.onExecutedWasCalled); + + // cleanup + window.onExecutedWasCalled = undefined; + }); +}); + +describe('DateTimeEditMask', function () { + describe('format', function () { + + it('successful build template', function () { + //Given + var editMask = new InfinniUI.DateTimeEditMask(); + editMask.mask = "%dd MM yyyy г."; + //When + var template = editMask.buildTemplate(); + //Then + assert.isArray(template); + assert.lengthOf(template, 6); + }); + + it('successful format value', function () { + //Given + var editMask = new InfinniUI.DateTimeEditMask(); + editMask.mask = "%dd MM yyyy г."; + editMask.format = new InfinniUI.DateTimeFormat(); + editMask.format.setFormat(editMask.mask); + //When + editMask.reset('2014-09-26T15:15'); + var text = editMask.getText(); + //Then + assert.equal(text, '26 09 2014 г.'); + }); + + it('successful input value', function () { + //Given + var editMask = new InfinniUI.DateTimeEditMask(); + editMask.mask = "dd MM yyyy г."; + editMask.format = new InfinniUI.DateTimeFormat(); + editMask.format.setFormat(editMask.mask); + //var template = editMask.buildTemplate(); + editMask.reset(null); + //When + var position = 0; + position = editMask.setCharAt('1', position); + position = editMask.setCharAt('9', position); + position = editMask.setCharAt('0', position); + position = editMask.setCharAt('7', position); + position = editMask.setCharAt('2', position); + position = editMask.setCharAt('0', position); + position = editMask.setCharAt('1', position); + position = editMask.setCharAt('4', position); + var text = editMask.getText(); + //Then + assert.equal(text, '19 07 2014 г.'); + assert.equal(position, 10) + }); + + it('successful navigation', function () { + //Given + var editMask = new InfinniUI.DateTimeEditMask(); + editMask.mask = "dd MM yyyy г."; + editMask.format = new InfinniUI.DateTimeFormat(); + editMask.format.setFormat(editMask.mask); + var date = new Date(); + editMask.reset(date); + //When + var position = 0; + var start = editMask.moveToPrevChar(position); + position = editMask.moveToNextChar(99); + position = editMask.setNextValue(position); + //Then + var value = editMask.getValue(); + var text = editMask.getText(); + assert.equal(position, text.length - 3); + assert.equal(date.getFullYear() + 1, (new Date(value)).getFullYear()); + }); + + it('successful delete char (right)', function () { + //Given + var editMask = new InfinniUI.DateTimeEditMask(); + editMask.mask = "dd MM yyyy г."; + editMask.format = new InfinniUI.DateTimeFormat(); + editMask.format.setFormat(editMask.mask); + + var date = new Date(2014, 9, 6, 9, 30, 50, 0); //06-10-2014 09:30:50 + editMask.reset(date); + //When + var position = 0; + var start = editMask.moveToPrevChar(position); + + position = editMask.deleteCharRight(position);//"6_ 10 2014 г." + position = editMask.deleteCharRight(position);//"__ 10 2014 г." + + //Then + var text = editMask.getText(); + assert.equal(position, 3); + assert.equal(text, "__ 10 2014 г."); + }); + + it('successful delete char (left)', function () { + //Given + var editMask = new InfinniUI.DateTimeEditMask(); + editMask.mask = "dd MM yyyy г."; + editMask.format = new InfinniUI.DateTimeFormat(); + editMask.format.setFormat(editMask.mask); + + var date = new Date(2014, 9, 6, 9, 30, 50, 0); //06-10-2014 09:30:50 + editMask.reset(date); + //When + var position = 8; + var start = editMask.moveToPrevChar(position); + + position = editMask.deleteCharLeft(position);//"06 10 214_ г." + position = editMask.deleteCharLeft(position);//"06 10 14__ г." + + //Then + var text = editMask.getText(); + assert.equal(position, 6); + assert.equal(text, "06 10 14__ г."); + }); + + it('successful set char', function () { + //Given + var editMask = new InfinniUI.DateTimeEditMask(); + editMask.mask = "dd MM yyyy г."; + editMask.format = new InfinniUI.DateTimeFormat(); + editMask.format.setFormat(editMask.mask); + + editMask.reset(null); + //When + var position = 9; + var start = editMask.moveToPrevChar(position); //"__ __ ____ г." + + position = editMask.setCharAt('2', position); + position = editMask.setCharAt('0', position); + position = editMask.setCharAt('1', position); + position = editMask.setCharAt('4', position); + + //Then + var text = editMask.getText(); + assert.equal(start, 8); + assert.equal(position, 10); + assert.equal(text, "__ __ 2014 г."); + }); + + + it('successful delete value', function () { + //Given + var editMask = new InfinniUI.DateTimeEditMask(); + editMask.mask = "dd MM yyyy г."; + editMask.format = new InfinniUI.DateTimeFormat(); + editMask.format.setFormat(editMask.mask); + //var template = editMask.buildTemplate(); + editMask.reset(null); + //When + var position = 0; + position = editMask.setCharAt('1', position); + position = editMask.setCharAt('9', position); + position = editMask.setCharAt('0', position); + position = editMask.setCharAt('7', position); + position = editMask.setCharAt('2', position); + position = editMask.setCharAt('0', position); + position = editMask.setCharAt('1', position); + position = editMask.setCharAt('4', position); + + position = editMask.deleteCharLeft(position);// 4 + position = editMask.deleteCharLeft(position);// 1 + position = editMask.deleteCharLeft(position);// 0 + position = editMask.deleteCharLeft(position);// 2 + position = editMask.deleteCharLeft(position);// . + position = editMask.deleteCharLeft(position);// 7 + position = editMask.deleteCharLeft(position);// 0 + position = editMask.deleteCharLeft(position);// . + position = editMask.deleteCharLeft(position);// 9 + position = editMask.deleteCharLeft(position);// 1 + var text = editMask.getText(); + //Then + assert.equal(text, '__ __ ____ г.'); + assert.equal(position, 0); + }); + + }); + + +}); + +describe('NumberEditMask', function () { + describe('format', function () { + + it('successful build template', function () { + //Given + var editMask = new InfinniUI.DateTimeEditMask(); + editMask.mask = "%d MM yyyy г."; + //When + var template = editMask.buildTemplate(); + //Then + assert.isArray(template); + assert.lengthOf(template, 6); + }); + + it('successful format value', function () { + //Given + var editMask = new InfinniUI.NumberEditMask(); + editMask.mask = "Цена n3 руб. за 1 кг"; + editMask.format = new InfinniUI.NumberFormat(); + editMask.format.setFormat(editMask.mask); + //When + editMask.reset('50'); + var text = editMask.getText(); + //Then + assert.equal(text, 'Цена 50,000 руб. за 1 кг'); + }); + + it('successful setCharAt', function () { + //Given + var editMask = new InfinniUI.NumberEditMask(); + editMask.mask = "Цена n3 руб. за 1 кг"; + editMask.format = new InfinniUI.NumberFormat(); + editMask.format.setFormat(editMask.mask); + + //When + editMask.reset('50'); + var position = 5; + position = editMask.setCharAt('1', position); + position = editMask.setCharAt('2', position); + position = editMask.setCharAt('3', position); + position = editMask.setCharAt('4', position); + position = editMask.setCharAt(',', position); + position = editMask.setCharAt('9', position); + var text = editMask.getText(); + + //Then + assert.equal(text, 'Цена 123 450,900 руб. за 1 кг'); + assert.equal(position, 14); + + }); + + it('successful setNextValue/setPrevValue', function () { + //Given + var editMask = new InfinniUI.NumberEditMask(); + editMask.mask = "Цена n3 руб. за 1 кг"; + editMask.format = new InfinniUI.NumberFormat(); + editMask.format.setFormat(editMask.mask); + + //When + editMask.reset('50'); + var position = 5; + position = editMask.setNextValue(position); + position = editMask.setNextValue(position); + position = editMask.setCharAt(',', position); + position = editMask.setPrevValue(position); + position = editMask.setPrevValue(position); + var text = editMask.getText(); + + //Then + assert.equal(text, 'Цена 50,000 руб. за 1 кг'); + assert.equal(position, 8); + + }); + + it('successful delete chars', function () { + //Given + var editMask = new InfinniUI.NumberEditMask(); + editMask.mask = "Цена n3 руб. за 1 кг"; + editMask.format = new InfinniUI.NumberFormat(); + editMask.format.setFormat(editMask.mask); + + //When + editMask.reset(123456789.876); + var position = 20; + position = editMask.deleteCharLeft(position); //"Цена 123 456 789,870 руб. за 1 кг" + position = editMask.deleteCharLeft(position); //"Цена 123 456 789,800 руб. за 1 кг" + position = editMask.deleteCharLeft(position); //"Цена 123 456 789,000 руб. за 1 кг" + position = editMask.deleteCharLeft(position); //"Цена 12 345 678,000 руб. за 1 кг" + position = editMask.deleteCharLeft(position); //"Цена 1 234 567,000 руб. за 1 кг" + position = editMask.deleteCharLeft(position); //"Цена 123 456,000 руб. за 1 кг" + position = editMask.deleteCharLeft(position); //"Цена 12 345,000 руб. за 1 кг" + position = editMask.moveToPrevChar(position); + position = editMask.moveToPrevChar(position); + position = editMask.moveToPrevChar(position); + position = editMask.moveToPrevChar(position); + position = editMask.deleteCharRight(position); //"Цена 1 245,000 руб. за 1 кг" + position = editMask.deleteCharRight(position); //"Цена 125,000 руб. за 1 кг" + var text = editMask.getText(); + + //Then + assert.equal(text, 'Цена 125,000 руб. за 1 кг'); + assert.equal(position, 7); + + }); + + it('successful movePrevChar', function () { + //Given + var editMask = new InfinniUI.NumberEditMask(); + editMask.mask = "Цена n3 руб. за 1 кг"; + editMask.format = new InfinniUI.NumberFormat(); + editMask.format.setFormat(editMask.mask); + + //When + editMask.reset(1234.567); //"Цена 1 234,567 руб. за 1 кг" + var position = 14; + position = editMask.moveToPrevChar(position); + position = editMask.moveToPrevChar(position); + position = editMask.moveToPrevChar(position); + + //Then + assert.equal(position, 11); + + }); + + it('successful decimalSeparator for currency', function () { + //Given + var editMask = new InfinniUI.NumberEditMask(); + editMask.mask = "Цена c3 за 1 кг"; + editMask.format = new InfinniUI.NumberFormat(); + editMask.format.setFormat(editMask.mask); + + //When + editMask.reset(null); //"Цена _,___ руб. за 1 кг" + var position = 5; + position = editMask.setCharAt('1', position); + position = editMask.setCharAt(',', position); + + //Then + assert.equal(position, 7); + assert.equal(editMask.getText(), 'Цена 1,000р. за 1 кг'); + }); + + it('successful decimal part for currency', function () { + //Given + var editMask = new InfinniUI.NumberEditMask(); + editMask.mask = "Цена c2 за 1 кг"; + editMask.format = new InfinniUI.NumberFormat(); + editMask.format.setFormat(editMask.mask); + + //When + editMask.reset(null); //"Цена _,___ руб. за 1 кг" + var position = 5; + position = editMask.setCharAt('1', position); + position = editMask.setCharAt(',', position); + position = editMask.setCharAt('2', position); + position = editMask.setCharAt('3', position); + position = editMask.setCharAt('4', position); + + //Then + assert.equal(position, 9); + assert.equal(editMask.getText(), 'Цена 1,23р. за 1 кг'); + + }); + + it('successful move to start', function () { + //Given + var editMask = new InfinniUI.NumberEditMask(); + editMask.mask = "Цена c2 за 1 кг"; + editMask.format = new InfinniUI.NumberFormat(); + editMask.format.setFormat(editMask.mask); + + //When + editMask.reset(null); + var position = editMask.moveToPrevChar(0); + + //Then + assert.equal(position, 5); + assert.equal(editMask.getText(), 'Цена _,__р. за 1 кг'); + + }); + + }); + + + + +}); + +describe('RegexEditMask', function () { + describe('format', function () { + + it('successful test mask', function () { + //Given + var editMask = new InfinniUI.RegexEditMask(); + editMask.mask = '^[0-9]{4}$'; + + //When + editMask.reset('1234'); + + //Then + assert.equal(editMask.getValue(), '1234'); + assert.isTrue(editMask.getIsComplete('1234')); + assert.isFalse(editMask.getIsComplete('123')); + }); + + }); + +}); + +describe('TemplateEditMask', function () { + describe('format', function () { + + it('successful build mask', function () { + //Given + var editMask = new InfinniUI.TemplateEditMask(); + + //When + + //Then + assert.isDefined(editMask); + }); + + it('successful build template', function () { + //Given + var editMask = new InfinniUI.TemplateEditMask(); + editMask.mask = '+\\9(999)000-00-00'; + + //When + var template = editMask.buildTemplate(); + //Then + assert.lengthOf(template, 16); + assert.equal(template[0], '+'); + assert.equal(template[1], '9'); + assert.equal(template[2], '('); + assert.isObject(template[3]); + assert.isObject(template[4]); + assert.isObject(template[5]); + assert.equal(template[6], ')'); + assert.isObject(template[7]); + assert.isObject(template[8]); + assert.isObject(template[9]); + assert.equal(template[10], '-'); + assert.isObject(template[11]); + assert.isObject(template[12]); + assert.equal(template[13], '-'); + assert.isObject(template[14]); + assert.isObject(template[15]); + assert.equal(editMask.getText(), '+9(___)___-__-__'); + assert.equal(editMask.getValue(), '+9()--') + }); + + it('successful move at start', function () { + //Given + var editMask = new InfinniUI.TemplateEditMask(); + editMask.mask = '+7(999)000-00-00'; + + //When + editMask.reset(); + //Then + var position = editMask.moveToPrevChar(0); + assert.equal(position, 3); + }); + + it('successful to last', function () { + //Given + var editMask = new InfinniUI.TemplateEditMask(); + editMask.mask = '+7(999)000-00-00'; + + //When + editMask.reset(); + //Then + var position = editMask.moveToNextChar(editMask.mask.length); + assert.equal(position, 16); + }); + + it('successful to set char', function () { + //Given + var editMask = new InfinniUI.TemplateEditMask(); + editMask.mask = '+7 (999)000-00-00'; + + //When + editMask.reset(); + var position = editMask.moveToPrevChar(0); + position = editMask.setCharAt('1', position); + position = editMask.setCharAt('2', position); + position = editMask.setCharAt('3', position); + + position = editMask.setCharAt('4', position); + position = editMask.setCharAt('5', position); + position = editMask.setCharAt('6', position); + + position = editMask.setCharAt('7', position); + position = editMask.setCharAt('8', position); + + position = editMask.setCharAt('9', position); + position = editMask.setCharAt('0', position); + + //Then + assert.equal(position, 17); + assert.equal(editMask.getValue(), '+7 (123)456-78-90'); + }); + + it('successful to set char without MaskSaveLiteral', function () { + //Given + var editMask = new InfinniUI.TemplateEditMask(); + editMask.mask = '+7 (999)000-00-00'; + editMask.maskSaveLiteral = false; + + //When + editMask.reset(); + var position = editMask.moveToPrevChar(0); + position = editMask.setCharAt('1', position); + position = editMask.setCharAt('2', position); + position = editMask.setCharAt('3', position); + + position = editMask.setCharAt('4', position); + position = editMask.setCharAt('5', position); + position = editMask.setCharAt('6', position); + + position = editMask.setCharAt('7', position); + position = editMask.setCharAt('8', position); + + position = editMask.setCharAt('9', position); + position = editMask.setCharAt('0', position); + + //Then + assert.equal(position, 17); + assert.equal(editMask.getValue(), '1234567890'); + }); + + it('successful getRegExpForMask with maskSaveLiteral', function () { + //Given + var editMask = new InfinniUI.TemplateEditMask(); + editMask.mask = '+7 (999)000-00-00'; + editMask.maskSaveLiteral = true; + + //When + var regexp = editMask.getRegExpForMask(); + + //Then + assert.isTrue(regexp.test('+7 (123)456-78-91')); + assert.isTrue(regexp.test('+7 ()456-78-91')); + assert.isTrue(regexp.test('+7 (1)456-78-91')); + assert.isFalse(regexp.test('+7 (123)456-78-9')); + }); + + + it('successful getRegExpForMask without maskSaveLiteral', function () { + //Given + var editMask = new InfinniUI.TemplateEditMask(); + editMask.mask = '+7 (999)000-00-00'; + editMask.maskSaveLiteral = false; + + //When + var regexp = editMask.getRegExpForMask(); + + //Then + assert.isTrue(regexp.test('1234567891')); + assert.isTrue(regexp.test('1234567')); + assert.isFalse(regexp.test('123456')); + }); + + it('successful set value without maskSaveLiteral', function () { + //Given + var editMask = new InfinniUI.TemplateEditMask(); + editMask.mask = '+7 (999)000-00-00'; + editMask.maskSaveLiteral = false; + + //When + editMask.reset('1234567890'); + + //Then + assert.equal(editMask.getValue(), '1234567890'); + assert.equal(editMask.getText(), '+7 (123)456-78-90'); + }); + + it('successful set value with maskSaveLiteral', function () { + //Given + var editMask = new InfinniUI.TemplateEditMask(); + editMask.mask = '+7 (999)000-00-00'; + editMask.maskSaveLiteral = true; + + //When + editMask.reset('+7 (123)456-78-90'); + + //Then + assert.equal(editMask.getValue(), '+7 (123)456-78-90'); + assert.equal(editMask.getText(), '+7 (123)456-78-90'); + }); + + it('successful format special chars', function () { + //Given + var editMask = new InfinniUI.TemplateEditMask(); + editMask.mask = '00/00/0000 \\at 99:99 99% (99$)'; + + //When + editMask.reset(); + + //Then + assert.equal(editMask.getText(), '__.__.____ at __:__ __% (__р.)'); + }); + + }); + + describe('template mask', function () { + var editMask; + var chars; + var char; + var position; + + + beforeEach(function () { + chars = '@@55ЦЦ+-'.split(''); + editMask = new InfinniUI.TemplateEditMask(); + editMask.maskSaveLiteral = false; + position = 0; + }); + + it('successful input mask "c"', function () { + //Given + editMask.mask = Array(chars.length + 1).join('c'); + editMask.reset(); + + //When + position = editMask.moveToPrevChar(0); + do { + char = chars.shift(); + position = editMask.setCharAt(char, position); + } while (chars.length > 0); + + var position = editMask.moveToPrevChar(0); + + //Then + assert.equal(editMask.getValue(), '@@55ЦЦ+-'); + }); + + it('successful input mask "C"', function () { + //Given + editMask.mask = Array(chars.length + 1).join('C'); + editMask.reset(); + + //When + position = editMask.moveToPrevChar(0); + do { + char = chars.shift(); + position = editMask.setCharAt(char, position); + } while (chars.length > 0); + + var position = editMask.moveToPrevChar(0); + + //Then + assert.equal(editMask.getValue(), '@@55ЦЦ+-'); + }); + + it('successful input mask "l"', function () { + //Given + editMask.mask = Array(chars.length + 1).join('l'); + editMask.reset(); + + //When + position = editMask.moveToPrevChar(0); + do { + char = chars.shift(); + position = editMask.setCharAt(char, position); + } while (chars.length > 0); + + var position = editMask.moveToPrevChar(0); + + //Then + assert.equal(editMask.getValue(), 'ЦЦ'); + }); + + it('successful input mask "L"', function () { + //Given + editMask.mask = Array(chars.length + 1).join('l'); + editMask.reset(); + + //When + position = editMask.moveToPrevChar(0); + do { + char = chars.shift(); + position = editMask.setCharAt(char, position); + } while (chars.length > 0); + + var position = editMask.moveToPrevChar(0); + + //Then + assert.equal(editMask.getValue(), 'ЦЦ'); + }); + + it('successful input mask "a"', function () { + //Given + editMask.mask = Array(chars.length + 1).join('a'); + editMask.reset(); + + //When + position = editMask.moveToPrevChar(0); + do { + char = chars.shift(); + position = editMask.setCharAt(char, position); + } while (chars.length > 0); + + var position = editMask.moveToPrevChar(0); + + //Then + assert.equal(editMask.getValue(), '55ЦЦ');//@@55ЦЦ+- + }); + + it('successful input mask "A"', function () { + //Given + editMask.mask = Array(chars.length + 1).join('A'); + editMask.reset(); + + //When + position = editMask.moveToPrevChar(0); + do { + char = chars.shift(); + position = editMask.setCharAt(char, position); + } while (chars.length > 0); + + var position = editMask.moveToPrevChar(0); + + //Then + assert.equal(editMask.getValue(), '55ЦЦ');//@@55ЦЦ+- + }); + + it('successful input mask "#"', function () { + //Given + editMask.mask = Array(chars.length + 1).join('#'); + editMask.reset(); + + //When + position = editMask.moveToPrevChar(0); + do { + char = chars.shift(); + position = editMask.setCharAt(char, position); + } while (chars.length > 0); + + var position = editMask.moveToPrevChar(0); + + //Then + assert.equal(editMask.getValue(), '+-');//@@55ЦЦ+- + }); + + it('successful input mask "#"', function () { + //Given + editMask.mask = Array(chars.length + 1).join('#'); + editMask.reset(); + + //When + position = editMask.moveToPrevChar(0); + do { + char = chars.shift(); + position = editMask.setCharAt(char, position); + } while (chars.length > 0); + + var position = editMask.moveToPrevChar(0); + + //Then + assert.equal(editMask.getValue(), '+-');//@@55ЦЦ+- + }); + + it('successful input mask "9"', function () { + //Given + editMask.mask = Array(chars.length + 1).join('9'); + editMask.reset(); + + //When + position = editMask.moveToPrevChar(0); + do { + char = chars.shift(); + position = editMask.setCharAt(char, position); + } while (chars.length > 0); + + var position = editMask.moveToPrevChar(0); + + //Then + assert.equal(editMask.getValue(), '55');//@@55ЦЦ+- + }); + + it('successful input mask "0"', function () { + //Given + editMask.mask = Array(chars.length + 1).join('0'); + editMask.reset(); + + //When + position = editMask.moveToPrevChar(0); + do { + char = chars.shift(); + position = editMask.setCharAt(char, position); + } while (chars.length > 0); + + var position = editMask.moveToPrevChar(0); + + //Then + assert.equal(editMask.getValue(), '55');//@@55ЦЦ+- + }); + }); + + + +}); + +describe('BooleanFormat', function () { + describe('format', function () { + + it('successful build', function () { + //Given + var metadata = {TrueText: "+", FalseText: "-"}; + var builder = new InfinniUI.BooleanFormatBuilder(); + //When + var format = builder.build(null, {metadata: metadata} ); + //Then + assert.isFunction(format.format); + assert.isFunction(format.getTrueText); + assert.isFunction(format.getFalseText); + assert.isFunction(format.setFalseText); + assert.isFunction(format.setTrueText); + assert.equal(format.format(true), '+'); + assert.equal(format.format(false), '-'); + }); + + it('should have default value', function () { + //Given + var format = new InfinniUI.BooleanFormat(); + //When + var value = true; + //Then + assert.equal(format.getFalseText(), 'False'); + assert.equal(format.getTrueText(), 'True'); + assert.equal(format.format(value), 'True'); + }); + + it('should format boolean', function () { + //Given + var format = new InfinniUI.BooleanFormat(); + //When + var value_1 = false; + var value_2 = true; + format.setFalseText('Нет'); + format.setTrueText('Да'); + //Then + assert.equal(format.format(value_1), 'Нет'); + assert.equal(format.format(value_2), 'Да'); + }); + + it('should format collection', function () { + //Given + var format = new InfinniUI.BooleanFormat(); + //When + var value = [true, true, false, true]; + format.setFalseText('Нет'); + format.setTrueText('Да'); + //Then + assert.equal(format.format(value), 'Да, Да, Нет, Да'); + }); + + }); + + +}); + +describe('DateTimeFormat', function () { + + describe('format', function () { + it('successful build', function () { + //Given + var builder = new InfinniUI.DateTimeFormatBuilder(); + //When + var format = builder.build(null, {metadata: {}}); + //Then + assert.isFunction(format.format); + assert.equal(format.getFormat(), 'G'); + }); + + it('should format year', function () { + //Given + var formattingFull = new InfinniUI.DateTimeFormat('yyyy'); + var formattingShort = new InfinniUI.DateTimeFormat('yy'); + var formattingTooShort = new InfinniUI.DateTimeFormat('%y'); + + //When + var date = new Date("21 May 1908 10:12"); + + //Then + assert.equal(formattingFull.format(date), '1908'); + assert.equal(formattingShort.format(date), '08'); + assert.equal(formattingTooShort.format(date), '8'); + }); + + it('should format month', function () { + //Given + var formattingFull = new InfinniUI.DateTimeFormat('MMMM'), + formattingAbbr = new InfinniUI.DateTimeFormat('MMM'), + formattingIndex = new InfinniUI.DateTimeFormat('MM'), + formattingShortIndex = new InfinniUI.DateTimeFormat('%M'), + enCulture = new InfinniUI.Culture('en-US'); + + //When + var date = new Date("21 January 1908 10:12"); + + //Then + assert.equal(formattingFull.format(date), 'Январь'); + assert.equal(formattingAbbr.format(date), 'янв'); + assert.equal(formattingIndex.format(date), '01'); + assert.equal(formattingShortIndex.format(date), '1'); + + assert.equal(formattingFull.format(date, enCulture), 'January'); + }); + + it('should format day', function () { + //Given + var formattingFull = new InfinniUI.DateTimeFormat('dddd'), + formattingAbbr = new InfinniUI.DateTimeFormat('ddd'), + formattingIndex = new InfinniUI.DateTimeFormat('dd'), + formattingShortIndex = new InfinniUI.DateTimeFormat('%d'), + enCulture = new InfinniUI.Culture('en-US'); + + //When + var date = new Date("2 January 1908 10:12"); + + //Then + assert.equal(formattingFull.format(date), 'среда'); + assert.equal(formattingAbbr.format(date), 'Ср'); + assert.equal(formattingIndex.format(date), '02'); + assert.equal(formattingShortIndex.format(date), '2'); + + assert.equal(formattingFull.format(date, enCulture), 'Wednesday'); + }); + + it('should format day', function () { + //Given + var formattingFull = new InfinniUI.DateTimeFormat('HH'), + formattingAbbr = new InfinniUI.DateTimeFormat('%H'), + formattingIndex = new InfinniUI.DateTimeFormat('hh'), + formattingShortIndex = new InfinniUI.DateTimeFormat('h'); + + //When + var date = new Date("2 January 1908 13:12"); + + //Then + assert.equal(formattingFull.format(date), '13'); + assert.equal(formattingAbbr.format(date), '13'); + assert.equal(formattingIndex.format(date), '01'); + assert.equal(formattingShortIndex.format(date), '1'); + }); + + it('should format minutes', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('mm'), + formattingShort = new InfinniUI.DateTimeFormat('%m'); + + //When + var date = new Date("2 January 1908 13:02"); + + //Then + assert.equal(formatting.format(date), '02'); + assert.equal(formattingShort.format(date), '2'); + }); + + it('should format seconds', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('ss'), + formattingShort = new InfinniUI.DateTimeFormat('%s'); + + //When + var date = new Date("2 January 1908 13:02:02"); + + //Then + assert.equal(formatting.format(date), '02'); + assert.equal(formattingShort.format(date), '2'); + }); + + it('should format pm/am designator', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('tt'), + formattingShort = new InfinniUI.DateTimeFormat('%t'), + enCulture = new InfinniUI.Culture('en-US'); + + //When + var datePM = new Date("2 January 1908 13:02"); + var dateAM = new Date("2 January 1908 11:02"); + + //Then + assert.equal(formatting.format(datePM, enCulture), 'PM'); + assert.equal(formatting.format(dateAM, enCulture), 'AM'); + assert.equal(formattingShort.format(dateAM, enCulture), 'A'); + assert.equal(formattingShort.format(dateAM), ''); + }); + + it('should format pm/am designator', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('zzz'); + + //When + var date = new Date("2 January 1908 13:02:00"); + + //Then + assert.equal(formatting.format(date), extractTimezoneOffset(date)); + }); + + it('should format date and time separators', function () { + //Given + var formattingTime = new InfinniUI.DateTimeFormat('12:23'), + formattingDate = new InfinniUI.DateTimeFormat('12/23'), + enCulture = new InfinniUI.Culture('en-US'); + + //When + var date = new Date("2 January 1908 13:02:00"); + + //Then + assert.equal(formattingTime.format(date), '12:23'); + assert.equal(formattingDate.format(date), '12.23'); + assert.equal(formattingDate.format(date, enCulture), '12/23'); + }); + + it('escaping strings', function () { + //Given + var formatting1 = new InfinniUI.DateTimeFormat('"HH"'), + formatting2 = new InfinniUI.DateTimeFormat("'HH'"), + formatting3 = new InfinniUI.DateTimeFormat('HH "HH"'); + + //When + var date = new Date("2 January 1908 13:12"); + + //Then + assert.equal(formatting1.format(date), 'HH'); + assert.equal(formatting2.format(date), 'HH'); + assert.equal(formatting3.format(date), '13 HH'); + }); + + + it('format by pattern f', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('f'), + enCulture = new InfinniUI.Culture('en-US'); + + //When + var date = new Date("4 January 1908 13:12"); + + //Then + assert.equal(formatting.format(date), '04 Январь 1908 г. 13:12'); + assert.equal(formatting.format(date, enCulture), 'Friday, January 04, 1908 1:12 PM'); + }); + + it('format by pattern F', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('F'), + enCulture = new InfinniUI.Culture('en-US'), + ruCulture = new InfinniUI.Culture('ru-RU'); + + //When + var date = new Date("4 January 1908 13:12:08"); + + //Then + assert.equal(formatting.format(date, ruCulture), '04 Январь 1908 г. 13:12:08'); + assert.equal(formatting.format(date, enCulture), 'Friday, January 04, 1908 1:12:8 PM'); + }); + + + it('format by pattern g', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('g'), + enCulture = new InfinniUI.Culture('en-US'); + + //When + var date = new Date("4 January 1908 13:12"); + + //Then + assert.equal(formatting.format(date), '04.01.1908 13:12'); + assert.equal(formatting.format(date, enCulture), '1/4/1908 1:12 PM'); + }); + + it('format by pattern G', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('G'), + ruCulture = new InfinniUI.Culture('ru-RU'), + enCulture = new InfinniUI.Culture('en-US'); + + //When + var date = new Date("4 January 1908 13:12:06"); + + //Then + assert.equal(formatting.format(date, ruCulture), '04.01.1908 13:12:06'); + assert.equal(formatting.format(date, enCulture), '1/4/1908 1:12:6 PM'); + }); + + it('format by pattern d', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('d'), + ruCulture = new InfinniUI.Culture('ru-RU'), + enCulture = new InfinniUI.Culture('en-US'); + + //When + var date = new Date("4 January 1908 13:12:06"); + + //Then + assert.equal(formatting.format(date, ruCulture), '04.01.1908'); + assert.equal(formatting.format(date, enCulture), '1/4/1908'); + }); + + it('format by pattern D', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('D'), + ruCulture = new InfinniUI.Culture('ru-RU'), + enCulture = new InfinniUI.Culture('en-US'); + + //When + var date = new Date("4 January 1908 13:12:06"); + + //Then + assert.equal(formatting.format(date, ruCulture), '04 Январь 1908 г.'); + assert.equal(formatting.format(date, enCulture), 'Friday, January 04, 1908'); + }); + + it('format by pattern t', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('t'), + ruCulture = new InfinniUI.Culture('ru-RU'), + enCulture = new InfinniUI.Culture('en-US'); + + //When + var date = new Date("4 January 1908 13:12:06"); + + //Then + assert.equal(formatting.format(date, ruCulture), '13:12'); + assert.equal(formatting.format(date, enCulture), '1:12 PM'); + }); + + it('format by pattern T', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('T'); + + //When + var date = new Date("4 January 1908 13:12:01"); + + //Then + assert.equal(formatting.format(date), '13:12:01'); + }); + + it('format by pattern Y', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('Y'), + ruCulture = new InfinniUI.Culture('ru-RU'), + enCulture = new InfinniUI.Culture('en-US'); + + //When + var date = new Date("4 January 1908 13:12:06"); + + //Then + assert.equal(formatting.format(date, ruCulture), 'Январь 1908'); + assert.equal(formatting.format(date, enCulture), 'January, 1908'); + }); + + it('format by pattern M', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('M'), + ruCulture = new InfinniUI.Culture('ru-RU'), + enCulture = new InfinniUI.Culture('en-US'); + + //When + var date = new Date("4 January 1908 13:12:06"); + + //Then + assert.equal(formatting.format(date, ruCulture), 'Январь 04'); + assert.equal(formatting.format(date, enCulture), 'January 04'); + }); + + it('format by pattern s', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('s'), + ruCulture = new InfinniUI.Culture('ru-RU'), + enCulture = new InfinniUI.Culture('en-US'); + + //When + var date = new Date("4 January 1908 13:12:06"); + + //Then + assert.equal(formatting.format(date, ruCulture), '1908-01-04T13:12:06'); + assert.equal(formatting.format(date, enCulture), '1908-01-04T13:12:06'); + }); + + it('format by pattern H', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('H'); + + //When + var date = new Date("4 January 1908 13:12:01"); + + //Then + assert.equal(formatting.format(date), '13'); + }); + + it('format collection', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('s'); + + //When + var date = [new Date("4 January 1908 13:12:1"), new Date("5 January 1908 13:12:1"), new Date("6 January 1908 13:12:1")]; + + //Then + assert.equal(formatting.format(date), '1908-01-04T13:12:01, 1908-01-05T13:12:01, 1908-01-06T13:12:01'); + }); + + it('format collection t', function () { + //Given + var formatting = new InfinniUI.DateTimeFormat('t'); + + //When + var date = [new Date("4 January 1908 13:12:1"), new Date("5 January 1908 13:02:1"), new Date("6 January 1908 13:12:1")]; + + //Then + assert.equal(formatting.format(date), '13:12, 13:02, 13:12'); + }); + + function extractTimezoneOffset(date){ + var offset; + date.toString().replace(/GMT([\s\S]{5})/, function(s, inner){ + offset = inner; + return ''; + }); + offset = offset.split(''); + offset.splice(3, 0, ':'); + offset = offset.join(''); + return offset; + } + }); +}); + +describe('NumberFormatting', function () { + describe('format', function () { + it('successful build', function () { + //Given + var builder = new InfinniUI.NumberFormatBuilder(); + //When + var format = builder.build(null, { metadata: {} }); + //Then + assert.isFunction(format.format); + assert.equal(format.getFormat(), 'n'); + }); + + it('should format percent', function () { + //Given + var formatting_p = new InfinniUI.NumberFormat('p'); + var formatting_p0 = new InfinniUI.NumberFormat('p0'); + var formatting_p1 = new InfinniUI.NumberFormat('p1'); + var enCulture = new InfinniUI.Culture('en-US'); + + //When + var val = 123.4567; + + //Then + assert.equal(formatting_p.format(val), '12 345,67%'); + assert.equal(formatting_p0.format(val), '12 346%'); + assert.equal(formatting_p1.format(val), '12 345,7%'); + + assert.equal(formatting_p1.format(val, enCulture), '12,345.7 %'); + }); + + it('should format number', function () { + //Given + var formatting_n = new InfinniUI.NumberFormat('n'); + var formatting_n0 = new InfinniUI.NumberFormat('n0'); + var formatting_n1 = new InfinniUI.NumberFormat('n1'); + var enCulture = new InfinniUI.Culture('en-US'); + + //When + var val = 1234.5678; + + //Then + assert.equal(formatting_n.format(val), '1 234,57'); + assert.equal(formatting_n0.format(val), '1 235'); + assert.equal(formatting_n1.format(val), '1 234,6'); + + assert.equal(formatting_n1.format(val, enCulture), '1,234.6'); + }); + + it('should format currency', function () { + //Given + var formatting_c = new InfinniUI.NumberFormat('c'); + var formatting_c0 = new InfinniUI.NumberFormat('c0'); + var formatting_c1 = new InfinniUI.NumberFormat('c1'); + var enCulture = new InfinniUI.Culture('en-US'); + + //When + var val = 1234.5678; + + //Then + assert.equal(formatting_c.format(val), '1 234,57р.'); + assert.equal(formatting_c0.format(val), '1 235р.'); + assert.equal(formatting_c1.format(val), '1 234,6р.'); + + assert.equal(formatting_c1.format(val, enCulture), '$1,234.6'); + }); + + it('should format collections', function () { + //Given + var formatting_c = new InfinniUI.NumberFormat('c'); + var formatting_c0 = new InfinniUI.NumberFormat('c0'); + var formatting_c1 = new InfinniUI.NumberFormat('c1'); + var enCulture = new InfinniUI.Culture('en-US'); + + //When + var val = [1234.5678, 2901.2345, 2678.9012]; + + //Then + assert.equal(formatting_c.format(val), '1 234,57р., 2 901,23р., 2 678,90р.'); + assert.equal(formatting_c0.format(val), '1 235р., 2 901р., 2 679р.'); + assert.equal(formatting_c1.format(val), '1 234,6р., 2 901,2р., 2 678,9р.'); + + assert.equal(formatting_c1.format(val, enCulture), '$1,234.6, $2,901.2, $2,678.9'); + }); + + }); + +}); + +describe('ObjectFormat', function () { + describe('format', function () { + + it('successful build', function () { + //Given + var metadata = {Format: '{}'}; + var builder = new InfinniUI.ObjectFormatBuilder(); + //When + var format = builder.build(null, { metadata: metadata } ); + //Then + assert.isFunction(format.format); + assert.equal(format.getFormat(), '{}'); + }); + + it('should format simple data type ', function () { + //Given + var formatter_1 = new InfinniUI.ObjectFormat("Hello, {}!"); + var formatter_2 = new InfinniUI.ObjectFormat("Birth date: {:d}"); + var formatter_3 = new InfinniUI.ObjectFormat("Birth time: {:T}"); + var formatter_4 = new InfinniUI.ObjectFormat("Weight: {:n2} kg"); + var enCulture = new InfinniUI.Culture('en-US'); + + //When + var value_1 = 'Ivan'; + var value_2 = new Date("4 January 1908 12:34:56"); + var value_3 = new Date("4 January 1908 12:34:56"); + var value_4 = 123.456; + + //Then + assert.equal(formatter_1.format(value_1, enCulture), 'Hello, Ivan!'); + assert.equal(formatter_2.format(value_2, enCulture), 'Birth date: 1/4/1908'); + assert.equal(formatter_3.format(value_3, enCulture), 'Birth time: 12:34:56 PM'); + assert.equal(formatter_4.format(value_4, enCulture), 'Weight: 123.46 kg'); + assert.equal(formatter_4.format(value_4), 'Weight: 123,46 kg'); + }); + + it('should format complex data type ', function () { + //Given + var formatter_1 = new InfinniUI.ObjectFormat("Hello, {FirstName} {MiddleName}!"); + var formatter_2 = new InfinniUI.ObjectFormat("Birth date: {BirthDate:d}"); + var formatter_3 = new InfinniUI.ObjectFormat("Birth time: {BirthDate:T}"); + var formatter_4 = new InfinniUI.ObjectFormat("Weight: {Weight:n2} kg"); + var enCulture = new InfinniUI.Culture('en-US'); + + //When + var value_1 = { FirstName: "Ivan", MiddleName: "Ivanovich" }; + var value_2 = { BirthDate: new Date("4 January 1908 12:34:56") }; + var value_3 = { BirthDate: new Date("4 January 1908 12:34:56") }; + var value_4 = { Weight: 123.456 }; + + //Then + assert.equal(formatter_1.format(value_1, enCulture), "Hello, Ivan Ivanovich!"); + assert.equal(formatter_2.format(value_2, enCulture), "Birth date: 1/4/1908"); + assert.equal(formatter_3.format(value_3, enCulture), "Birth time: 12:34:56 PM"); + assert.equal(formatter_4.format(value_4, enCulture), "Weight: 123.46 kg" ); + }); + + it('should format collection ', function () { + //Given + var formatter_1 = new InfinniUI.ObjectFormat("Hello, {FirstName} {MiddleName}!"); + var formatter_2 = new InfinniUI.ObjectFormat("Birth date: {BirthDate:d}"); + var formatter_3 = new InfinniUI.ObjectFormat("Birth time: {BirthDate:T}"); + var formatter_4 = new InfinniUI.ObjectFormat("Weight: {Weight:n2} kg"); + var enCulture = new InfinniUI.Culture('en-US'); + + //When + var value_1 = [{ FirstName: "Ivan", MiddleName: "Ivanovich" }, { FirstName: "Petr", MiddleName: "Petrov" }]; + var value_2 = { BirthDate: new Date("4 January 1908 12:34:56") }; + var value_3 = { BirthDate: new Date("4 January 1908 12:34:56") }; + var value_4 = [{ Weight: 123.456 }, { Weight: 789.012 }]; + + //Then + assert.equal(formatter_1.format(value_1, enCulture), "Hello, Ivan Ivanovich!, Hello, Petr Petrov!"); + assert.equal(formatter_2.format(value_2, enCulture), "Birth date: 1/4/1908"); + assert.equal(formatter_3.format(value_3, enCulture), "Birth time: 12:34:56 PM"); + assert.equal(formatter_4.format(value_4, enCulture), "Weight: 123.46 kg, Weight: 789.01 kg" ); + }); + + it('should format when value is undefined', function () { + //Given + var formatter = new InfinniUI.ObjectFormat("Hello, {FirstName} {MiddleName}!"); + //When + //Then + assert.equal(formatter.format(), "Hello, !"); + }); + + it('should format when value is null', function () { + //Given + var formatter = new InfinniUI.ObjectFormat("Hello, {FirstName} {MiddleName}!"); + //When + //Then + assert.equal(formatter.format(null), "Hello, !"); + }); + }); + +}); + +describe('LinkView', function () { + + describe('setOpenMode', function () { + it('should set openMode', function () { + //Given + var view = new InfinniUI.LinkView(); + + //When + view.setOpenMode('Dialog'); + + //Then + assert.equal(view.getOpenMode(), 'Dialog'); + }); + + it('should set openMode Default by default', function () { + //Given + var view = new InfinniUI.LinkView(); + + //Then + assert.equal(view.getOpenMode(), 'Default'); + }); + + it('should set openMode Default if no mode passed', function () { + //Given + var view = new InfinniUI.LinkView(); + + //When + view.setOpenMode(null); + + //Then + assert.equal(view.getOpenMode(), 'Default'); + }); + }); +}); + +describe('MetadataViewBuilder', function () { + + /*var builder = new InfinniUI.ApplicationBuilder(); + + window.providerRegister.register('MetadataDataSource', function (metadataValue) { + return { + "getViewMetadata": function () { + return metadata; + } + }; + }); + + var metadata = { + "DataSources": [ + + { + "DocumentDataSource": { + "Name": 'PatientDataSource', + "ConfigId": 'ReceivingRoom', + "DocumentId": 'HospitalizationRefusal' + } + } + ], + "OpenMode": "Application", + "ConfigId": 'ReceivingRoom', + "DocumentId": 'HospitalizationRefusal', + "ViewType": 'ListView', + "MetadataName": 'HospitalizationRefusalListView', + //"Parameters": [ + // { + // "Name" : 'Param1', + // "Value" : { + // "PropertyBinding": { + // "DataSource": 'PatientDataSource', + // "Property": 'LastName' + // } + // } + // } + //], + "LayoutPanel" : { + + } + }; + + it('should build exists view', function () { + + var applicationBuilder = new InfinniUI.ApplicationBuilder(); + var builder = new MetadataViewBuilder(); + var view = builder.build(null, {builder: applicationBuilder, view: {}, metadata: metadata}); + + applicationBuilder.appView = view; + applicationBuilder.appView.createView(function(view){ + //assert.isNotNull(view.getParameter('Param1')); + assert.isNotNull(view.getDataSource('PatientDataSource')); + }); + });*/ +}); + + +describe('MessageBus', function () { + var messageBus; + + beforeEach(function () { + messageBus = window.InfinniUI.global.messageBus; + }); + + describe('send', function () { + it('should send', function () { + var flag = 0; + + messageBus.subscribe('myEvent', function (context, obj) { + flag += obj.value; + }); + messageBus.subscribe('myEvent', function (context, obj) { + flag += obj.value; + }); + messageBus.subscribe('myEvent', function (context, obj) { + flag += obj.value; + }); + + messageBus.send('myEvent', 2); + + assert.equal(flag, 6); + }); + + it('should deliver message to valid subscribers', function () { + var flag1 = 0, + flag2 = 0; + + messageBus.subscribe('myEvent_1', function (context, obj) { + flag1 += obj.value; + }); + messageBus.subscribe('myEvent_1', function (context, obj) { + flag1 += obj.value; + }); + messageBus.subscribe('myEvent_2', function (context, obj) { + flag2 += obj.value; + }); + messageBus.subscribe('myEvent_2', function (context, obj) { + flag2 += obj.value; + }); + + messageBus.send('myEvent_1', 1); + messageBus.send('myEvent_2', 2); + + assert.equal(flag1, 2, 'first handler flag is right'); + assert.equal(flag2, 4, 'second handler flag is right'); + }); + }); +}); + +describe('ScriptExecutor', function () { + var builder; + beforeEach(function () { + builder = new InfinniUI.ScriptBuilder(); + }); + + it('should build script handler', function () { + + var metadata = { + Name: "Name", + Body: "return 5;" + }; + + var func = builder.build(null, {metadata: metadata}); + + assert.equal(func.call(), 5); + }); + + it('should pass arguments to handler', function () { + + var metadata = { + Name: "Name", + Body: "return [context,args].join(':');" + }; + + var func = builder.build(null, {metadata: metadata}); + + assert.equal(func.call(undefined, "Context", "Args"), "Context:Args"); + }); +}); + +describe('ScriptExecutor', function () { + + var builder = new InfinniUI.ApplicationBuilder(); + + window.InfinniUI.providerRegister.register('MetadataDataSource', function (metadataValue) { + return { + "getMetadata": function () { + return metadata; + } + }; + }); + + var metadata = { + "Scripts" :[ + { + "Name" : "OpenViewScript", + "Body" : "context.Controls['TextBox1'].setText('Hello world from script!');" + }, + { + "Name" : "TestRunScript", + "Body" : "context.TestValue = args['test'];" + } + ], + "DataSources": [ + + { + "DocumentDataSource": { + "Name": 'PatientDataSource', + "ConfigId": 'ReceivingRoom', + "DocumentId": 'HospitalizationRefusal' + } + }, + { + "DocumentDataSource" : { + "Name" : 'ClassifierDataSource', + "ConfigId" : 'ClassifierStorage', + "DocumentId" : 'SomeClassifier' + } + } + ], + "OpenMode": "Application", + "ViewType": 'ListView', + //"Parameters": [ + // { + // "Name" : 'Param1' + // } + //], + "LayoutPanel" : { + "StackPanel": { + "Name": "MainViewPanel", + "Items": [ + { + "TextBox": { + "Name": "TextBox1", + "Multiline": true + } + }, + { + "TextBox": { + "Name": "TextBox2" + } + }, + { + "ComboBox": { + "Name": "ComboBox1", + "DisplayProperty": "", + "ValueProperty": "", + "MultiSelect": true, + "ShowClear": true, + "Value" : { + "DataSource" : "PatientDataSource", + "Property" : "LastName" + } + } + } + ] + } + } + }; + +// it('should create script context for opened view', function (done) { +// +// var linkView = new InfinniUI.LinkView(null, function (resultCallback) { +// var builder = new InfinniUI.ApplicationBuilder(); +// var view = builder.buildType(fakeView(), 'View', metadata); +// resultCallback(view); +// }); +// linkView.setOpenMode('Application'); +// +// linkView.createView(function(view){ +// +// assert.isNotNull(view.getContext()); +// assert.isNotNull(view.getContext().DataSources['PatientDataSource']); +// assert.isNotNull(view.getContext().DataSources['ClassifierDataSource']); +// //assert.isNotNull(view.getContext().Parameters['Param1']); +// //assert.equal(view.getContext().Parameters['Param1'].getValue(),'1'); +// assert.isNotNull(view.getContext().Controls['TextBox1']); +// assert.isNotNull(view.getContext().Controls['TextBox2']); +// assert.isNotNull(view.getContext().Controls['ComboBox1']); +// +// var textBox1 = view.getContext().Controls['TextBox1']; +// +// textBox1.setText('Hello world!'); +// assert.equal(textBox1.getText(),'Hello world!'); +// +// var dataSource = view.getContext().DataSources["PatientDataSource"]; +// assert.equal(dataSource.getName(),"PatientDataSource"); +// +// done(); +// }); +// }); +// +// it('should invoke script from ScriptExecutor', function(done){ +// +// var linkView = new InfinniUI.LinkView(null, function (resultCallback) { +// var builder = new InfinniUI.ApplicationBuilder(); +// var view = builder.buildType(fakeView(), 'View', metadata); +// resultCallback(view); +// }); +// linkView.setOpenMode('Application'); +// +// linkView.createView(function(view){ +// +// var scriptExecutor = new ScriptExecutor(view); +// scriptExecutor.executeScript('OpenViewScript'); +// +// var textBox1 = view.getContext().Controls["TextBox1"]; +// assert.equal(textBox1.getText(),'Hello world from script!'); +// +// var args = { +// "test" : 1 +// }; +// +// var context = view.getContext(); +// context.Scripts["TestRunScript"].Run(context,args); +// +// assert.equal(context.TestValue,1); +// +// done(); +// +// }); +// +// }); + + +}); + +describe("Collection", function () { + + var items; + var objects; + var itemsCollections; + var objectsCollections; + var idProperty = 'id'; + + + + function bindAllEvents(collection) { + var events = 'onAdd,onReplace,onRemove,onMove,onReset,onChange'.split(','); + var handlers = []; + + events.forEach(function (event) { + + collection[event](function (context, argument) { + handlers.push(event); + }); + }); + + return { + checkEvent: function (event, count) { + if (typeof count === 'undefined') { + count = 1; + } + return handlers.filter(function (name) { + return name === event; + }).length === count; + }, + reset: function () { + handlers = []; + } + } + } + + function getArray(length, value) { + value = value || null; + + switch (length) { + case 0: + return []; + case 1: + return [null]; + default: + return Array(length).join(',').split(',').map(function () { + return value; + }); + } + } + + + beforeEach(function () { + var COUNT = 5; + + items = []; + for (var i = 0; i < COUNT; i = i + 1) { + items.push(getArray(i).map(function (itm, idx) { + return 'Item ' + idx; + })); + } + itemsCollections = items.map(function (items) { + return new InfinniUI.Collection(items); + }); + }); + + beforeEach(function () { + var COUNT = 5; + + objects = []; + for (var i = 0; i < COUNT; i = i + 1) { + objects.push(getArray(i).map(function (itm, idx) { + return {id: idx + 1, title: idx}; + })); + } + objectsCollections = objects.map(function (objects) { + return new InfinniUI.Collection(objects, idProperty); + }); + }); + + describe("length", function () { + + it("should return 0", function () { + // When + var collection = new InfinniUI.Collection(); + // Then + assert.strictEqual(collection.length, 0); + }); + + it("should return length items collection", function () { + // When + // Then + for (var i = 0; i < itemsCollections.length; i++) { + assert.strictEqual(itemsCollections[i].length, items[i].length); + } + }); + + it("should return length objects collection", function () { + // When + // Then + for (var i = 0; i < objectsCollections.length; i++) { + assert.strictEqual(objectsCollections[i].length, objects[i].length); + } + }); + + }); + + describe("idProperty", function () { + it("should return undefined", function () { + // When + var collection = new InfinniUI.Collection(); + // Then + assert.isUndefined(collection.idProperty); + }); + + it("should return idProperty", function () { + // When + var collection = new InfinniUI.Collection([], idProperty); + // Then + assert.equal(collection.idProperty, idProperty); + }); + + }); + + + describe("comparator", function () { + it("should has comparator", function () { + var + comparator = function (a, b) { + return a - b + }, + collection = new InfinniUI.Collection([], null, comparator); + + assert.isFunction(collection.comparator); + assert.equal(collection.comparator, comparator); + }); + }); + + describe("size()", function () { + it("should return size items collection", function () { + // When + // Then + for (var i = 0; i < itemsCollections.length; i++) { + assert.strictEqual(itemsCollections[i].size(), items[i].length); + } + }); + + it("should return size objects collection", function () { + // When + // Then + for (var i = 0; i < objectsCollections.length; i++) { + assert.strictEqual(objectsCollections[i].size(), objects[i].length); + } + }); + }); + + + describe("push()", function () { + it("should add item", function () { + //When + var + changed, + collection = new InfinniUI.Collection(), + handlers = bindAllEvents(collection); + + changed = collection.push('A'); + assert.isTrue(changed); + assert.equal(String(collection), '"A"'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + + handlers.reset(); + changed = collection.push('B'); + assert.isTrue(changed); + assert.equal(String(collection), '"A","B"'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + + handlers.reset(); + changed = collection.push('C'); + assert.isTrue(changed); + assert.equal(String(collection), '"A","B","C"'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + }); + + it("should add objects", function () { + //When + var + objects = [ + {id: 1, title: 'One'}, + {id: 2, title: 'Two'}, + {id: 3, title: 'Three'} + ], + changed, + collection = new InfinniUI.Collection([], idProperty), + handlers = bindAllEvents(collection); + + changed = collection.push(objects[0]); + assert.isTrue(changed, 'One changed'); + assert.equal(String(collection), '{"id":1,"title":"One"}'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + + handlers.reset(); + changed = collection.push(objects[1]); + assert.isTrue(changed, 'Two changed'); + assert.equal(String(collection), '{"id":1,"title":"One"},{"id":2,"title":"Two"}'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + + handlers.reset(); + changed = collection.push(objects[2]); + assert.isTrue(changed, 'Three changed'); + assert.equal(String(collection), '{"id":1,"title":"One"},{"id":2,"title":"Two"},{"id":3,"title":"Three"}'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + }); + + }); + + describe("add()", function () { + it("should add item", function () { + //When + var + changed, + collection = new InfinniUI.Collection(), + handlers = bindAllEvents(collection); + + changed = collection.add('A'); + assert.isTrue(changed); + assert.equal(String(collection), '"A"'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + + handlers.reset(); + changed = collection.add('B'); + assert.isTrue(changed); + assert.equal(String(collection), '"A","B"'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + + handlers.reset(); + changed = collection.add('C'); + assert.isTrue(changed); + assert.equal(String(collection), '"A","B","C"'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + }); + + it("should add objects", function () { + //When + var + objects = [ + {id: 1, title: 'One'}, + {id: 2, title: 'Two'}, + {id: 3, title: 'Three'} + ], + changed, + collection = new InfinniUI.Collection([], idProperty), + handlers = bindAllEvents(collection); + + changed = collection.add(objects[0]); + assert.isTrue(changed, 'One changed'); + assert.equal(String(collection), '{"id":1,"title":"One"}'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + + handlers.reset(); + changed = collection.add(objects[1]); + assert.isTrue(changed, 'Two changed'); + assert.equal(String(collection), '{"id":1,"title":"One"},{"id":2,"title":"Two"}'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + + handlers.reset(); + changed = collection.add(objects[2]); + assert.isTrue(changed, 'Three changed'); + assert.equal(String(collection), '{"id":1,"title":"One"},{"id":2,"title":"Two"},{"id":3,"title":"Three"}'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + }); + }); + + describe("addAll()", function () { + it("should add all item", function () { + //When + var + changed, + collection = new InfinniUI.Collection(), + handlers = bindAllEvents(collection); + + changed = collection.addAll(['A', 'B']); + assert.isTrue(changed); + assert.equal(String(collection), '"A","B"'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + + handlers.reset(); + changed = collection.addAll(['C', 'D']); + assert.isTrue(changed); + assert.equal(String(collection), '"A","B","C","D"'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + }); + + it("should add all objects", function () { + //When + var + changed, + collection = new InfinniUI.Collection([], 'id'), + handlers = bindAllEvents(collection); + + changed = collection.addAll([{id: 1, title: 'One'}, {id: 2, title: 'Two'}]); + assert.isTrue(changed); + assert.equal(String(collection), '{"id":1,"title":"One"},{"id":2,"title":"Two"}'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + + handlers.reset(); + changed = collection.addAll([{id: 3, title: 'Three'}, {id: 4, title: 'Four'}]); + assert.isTrue(changed); + assert.equal(String(collection), '{"id":1,"title":"One"},{"id":2,"title":"Two"},{"id":3,"title":"Three"},{"id":4,"title":"Four"}'); + assert.isTrue(handlers.checkEvent('onAdd')); + assert.isTrue(handlers.checkEvent('onChange')); + }); + }); + + describe("insert()", function () { + it("should insert item", function () { + //When + var + changed, + collection = new InfinniUI.Collection(), + handlers = bindAllEvents(collection); + + changed = collection.insert(0, 'A'); + assert.isTrue(changed, 'Changed on insert "A"'); + assert.equal(String(collection), '"A"'); + assert.isTrue(handlers.checkEvent('onAdd'), 'onAdd event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + + handlers.reset(); + changed = collection.insert(0, 'B'); + assert.isTrue(changed, 'Changed on insert "B"'); + assert.equal(String(collection), '"B","A"'); + assert.isTrue(handlers.checkEvent('onAdd'), 'onAdd event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + + handlers.reset(); + changed = collection.insert(0, 'C'); + assert.isTrue(changed, 'Changed on insert "C"'); + assert.equal(String(collection), '"C","B","A"'); + assert.isTrue(handlers.checkEvent('onAdd'), 'onAdd event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }); + + it("should insert objects", function () { + //When + var + changed, + collection = new InfinniUI.Collection([], idProperty), + handlers = bindAllEvents(collection); + + changed = collection.insert(0, {id: 1, title: 'One'}); + assert.isTrue(changed, 'One changed'); + assert.equal(String(collection), '{"id":1,"title":"One"}'); + assert.isTrue(handlers.checkEvent('onAdd'), 'onAdd event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + + handlers.reset(); + changed = collection.insert(0, {id: 2, title: 'Two'}); + assert.isTrue(changed, 'Two changed'); + assert.equal(String(collection), '{"id":2,"title":"Two"},{"id":1,"title":"One"}'); + assert.isTrue(handlers.checkEvent('onAdd'), 'onAdd event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + + handlers.reset(); + changed = collection.insert(0, {id: 3, title: 'Three'}); + assert.isTrue(changed, 'Three changed'); + assert.equal(String(collection), '{"id":3,"title":"Three"},{"id":2,"title":"Two"},{"id":1,"title":"One"}'); + assert.isTrue(handlers.checkEvent('onAdd'), 'onAdd event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }); + }); + + describe("insertAll()", function () { + + it("should insert all item", function () { + //When + var + changed, + collection = new InfinniUI.Collection(), + handlers = bindAllEvents(collection); + + changed = collection.insertAll(0, ['A', 'B']); + assert.isTrue(changed, 'Changed on insert ["A", "B"]'); + assert.equal(String(collection), '"A","B"'); + assert.isTrue(handlers.checkEvent('onAdd'), 'onAdd event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + + handlers.reset(); + changed = collection.insertAll(0, ['C', 'D']); + assert.isTrue(changed, 'Changed on insert ["C", "D"'); + assert.equal(String(collection), '"C","D","A","B"'); + assert.isTrue(handlers.checkEvent('onAdd'), 'onAdd event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }); + + it("should insert all objects", function () { + //When + var + changed, + collection = new InfinniUI.Collection([], 'id'), + handlers = bindAllEvents(collection); + + changed = collection.insertAll(0, [{id: 1, title: 'One'}, {id: 2, title: 'Two'}]); + assert.isTrue(changed, 'Changed step 1'); + assert.equal(String(collection), '{"id":1,"title":"One"},{"id":2,"title":"Two"}'); + assert.isTrue(handlers.checkEvent('onAdd'), 'onAdd event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + + handlers.reset(); + changed = collection.insertAll(0, [{id: 3, title: 'Three'}, {id: 4, title: 'Four'}]); + assert.isTrue(changed, 'Changed step 2'); + assert.equal(String(collection), '{"id":3,"title":"Three"},{"id":4,"title":"Four"},{"id":1,"title":"One"},{"id":2,"title":"Two"}'); + assert.isTrue(handlers.checkEvent('onAdd'), 'onAdd event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }); + }); + + describe("reset()", function () { + + it("should reset item", function () { + //When + var + changed, + collection = new InfinniUI.Collection(), + handlers = bindAllEvents(collection); + + changed = collection.reset(['A', 'B']); + assert.isTrue(changed, 'Changed on step 1'); + assert.equal(String(collection), '"A","B"'); + assert.isTrue(handlers.checkEvent('onReset'), 'onReset event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + + handlers.reset(); + changed = collection.reset(['C', 'D']); + assert.isTrue(changed, 'Changed on step 2'); + assert.equal(String(collection), '"C","D"'); + assert.isTrue(handlers.checkEvent('onReset'), 'onReset event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + + handlers.reset(); + changed = collection.reset(['C', 'D']); + assert.isFalse(changed, 'Not changed on step 3'); + assert.equal(String(collection), '"C","D"'); + assert.isFalse(handlers.checkEvent('onReset'), 'onReset event'); + assert.isFalse(handlers.checkEvent('onChange'), 'onChange event'); + }); + + it("should reset objects", function () { + //When + var + changed, + collection = new InfinniUI.Collection([], 'id'), + handlers = bindAllEvents(collection); + + changed = collection.reset([{id: 1, title: 'One'}, {id: 2, title: 'Two'}]); + assert.isTrue(changed, 'Changed step 1'); + assert.equal(String(collection), '{"id":1,"title":"One"},{"id":2,"title":"Two"}'); + assert.isTrue(handlers.checkEvent('onReset'), 'onReset event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + + handlers.reset(); + changed = collection.reset([{id: 3, title: 'Three'}, {id: 4, title: 'Four'}]); + assert.isTrue(changed, 'Changed step 2'); + assert.equal(String(collection), '{"id":3,"title":"Three"},{"id":4,"title":"Four"}'); + assert.isTrue(handlers.checkEvent('onReset'), 'onReset event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }); + + }); + + describe("set()", function () { + it("should set items", function () { + var collection = new InfinniUI.Collection(['Apple', 'Banana', 'Pineapple']), + handlers = bindAllEvents(collection); + + assert.deepEqual(collection.toArray(), ['Apple', 'Banana', 'Pineapple']); + + collection.set(['Apple', 'Melon']); + + assert.deepEqual(collection.toArray(), ['Apple', 'Melon']); + assert.isTrue(handlers.checkEvent('onReset'), 'onReset event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }); + + it("should set objects", function () { + var collection = new InfinniUI.Collection([ + {key: 1, value: 'Apple'}, + {key: 2, value: 'Banana'}, + {key: 3, value: 'Pineapple'} + ], 'key'), + handlers = bindAllEvents(collection); + + assert.deepEqual(collection.toArray().map(function (item) { + return item.value; + }), ['Apple', 'Banana', 'Pineapple']); + + collection.set([ + {key: 1, value: 'Apple'}, + {key: 2, value: 'Melon'} + ]); + + assert.deepEqual(collection.toArray().map(function (item) { + return item.value; + }), ['Apple', 'Melon']); + assert.isTrue(handlers.checkEvent('onReset'), 'onReset event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }); + + }); + + describe("replace()", function () { + it("should replace item", function () { + //When + var collection = new InfinniUI.Collection(['A', 'B', 'C']); + var handlers = bindAllEvents(collection); + + var changed = collection.replace('C', 'D'); + //Then + assert.isTrue(changed); + assert.equal(String(collection), '"A","B","D"'); + assert.isTrue(handlers.checkEvent('onReplace'), 'onReplace event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }); + + it("should replace object", function () { + //When + var collection = new InfinniUI.Collection([{id: 1, title: "A"}, {id: 2, title: "B"}], 'id'); + var handlers = bindAllEvents(collection); + var changed = collection.replace({id: 2, title: "B"}, {id: 3, title: "C"}); + + assert.isTrue(changed); + assert.equal(String(collection), '{"id":1,"title":"A"},{"id":3,"title":"C"}'); + assert.isTrue(handlers.checkEvent('onReplace'), 'onReplace event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }) + }); + + describe("pop()", function () { + + it("should pop item", function () { + //When + var items = ['A', 'B', 'C'], + collection = new InfinniUI.Collection(['A', 'B', 'C']), + handlers = bindAllEvents(collection); + + var item2 = collection.pop(); // 'C' + var item1 = collection.pop(); // 'B' + var item0 = collection.pop(); // 'A + + //Then + assert.equal(item2, items[2]); + assert.equal(item1, items[1]); + assert.equal(item0, items[0]); + assert.isTrue(handlers.checkEvent('onRemove', 3), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange', 3), 'onChange event'); + }); + + it("should pop object", function () { + //When + var objects = [ + {id: 1, title: 'One'}, + {id: 2, title: 'Two'}, + {id: 3, title: 'Three'} + ], + collection = new InfinniUI.Collection(objects, 'id'); + + //Then + while (collection.length > 0) { + assert.equal(collection.pop(), objects.pop()); + } + }); + + }); + + describe("remove()", function () { + + it("should remove item", function () { + var + collection = new InfinniUI.Collection(['A', 'B', 'C']), + handlers = bindAllEvents(collection), + change; + + change = collection.remove('B'); // [ 'A', 'C' ] + assert.equal('"A","C"', String(collection)); + assert.isTrue(change); + + change = collection.remove('A'); // [ 'C' ] + assert.equal('"C"', String(collection)); + assert.isTrue(change); + + change = collection.remove('C'); // [ ] + assert.equal(collection.length, 0); + assert.isTrue(change); + + assert.isTrue(handlers.checkEvent('onRemove', 3), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange', 3), 'onChange event'); + }); + + it("should remove object", function () { + var collection = new InfinniUI.Collection([ + {id: 1, title: "One"}, + {id: 2, title: "Two"}, + {id: 3, title: "Three"} + ], 'id'), change, + handlers = bindAllEvents(collection); + + change = collection.remove({id: 2, title: "Two"}); + assert.isTrue(change); + assert.equal(String(collection), '{"id":1,"title":"One"},{"id":3,"title":"Three"}'); + + change = collection.remove({id: 1, title: "One"}); + assert.isTrue(change); + assert.equal(String(collection), '{"id":3,"title":"Three"}'); + + change = collection.remove({id: 3, title: "Three"}); + assert.isTrue(change); + assert.equal(collection.length, 0); + + assert.isTrue(handlers.checkEvent('onRemove', 3), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange', 3), 'onChange event'); + }); + + }); + + describe("removeById()", function () { + + it("should remove object by id", function () { + var collection = new InfinniUI.Collection([ + {key: 1, value: 'A'}, + {key: 2, value: 'B'}, + {key: 3, value: 'C'} + ], 'key'), + handlers = bindAllEvents(collection), + changed; + + changed = collection.removeById(2); + assert.equal(String(collection), '{"key":1,"value":"A"},{"key":3,"value":"C"}'); + assert.isTrue(changed, 'deleted 2'); + + changed = collection.removeById(1); + assert.equal(String(collection), '{"key":3,"value":"C"}'); + assert.isTrue(changed, 'deleted 1'); + + changed = collection.removeById(3); + assert.equal(collection.length, 0); + assert.isTrue(changed, 'deleted 3'); + + assert.isTrue(handlers.checkEvent('onRemove', 3), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange', 3), 'onChange event'); + }); + + }); + + describe("removeAt()", function () { + + it("should remove item by index", function () { + var collection = new InfinniUI.Collection(['A', 'B', 'C']), + handlers = bindAllEvents(collection); + + assert.isTrue(collection.removeAt(1)); + assert.deepEqual(collection.toArray(), ['A', 'C']); + + assert.isTrue(collection.removeAt(0)); + assert.deepEqual(collection.toArray(), ['C']); + + assert.isTrue(collection.removeAt(0)); + assert.deepEqual(collection.toArray(), []); + + assert.isTrue(handlers.checkEvent('onRemove', 3), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange', 3), 'onChange event'); + }); + + it("should remove object by index", function () { + var collection = new InfinniUI.Collection([ + {key: 1, value: 'A'}, + {key: 2, value: 'B'}, + {key: 3, value: 'C'} + ], 'key'), + handlers = bindAllEvents(collection), + changed; + + assert.isTrue(collection.removeAt(1)); + assert.deepEqual(collection.toArray(), [ + {key: 1, value: 'A'}, + {key: 3, value: 'C'} + ]); + + assert.isTrue(collection.removeAt(0)); + assert.deepEqual(collection.toArray(), [ + {key: 3, value: 'C'} + ]); + + assert.isTrue(collection.removeAt(0)); + assert.deepEqual(collection.toArray(), []); + + assert.isTrue(handlers.checkEvent('onRemove', 3), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange', 3), 'onChange event'); + }); + + }); + + describe("removeAll()", function () { + it("should remove all item", function () { + var collection = new InfinniUI.Collection(['A', 'B', 'C', 'D']), + handlers = bindAllEvents(collection); + + assert.isTrue(collection.removeAll(['A', 'C'])); + assert.deepEqual(collection.toArray(), ['B', 'D']); + + assert.isTrue(collection.removeAll(['B', 'D'])); + assert.deepEqual(collection.toArray(), []); + + assert.isTrue(handlers.checkEvent('onRemove', 2), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange', 2), 'onChange event'); + }); + + it("should remove all objects", function () { + var collection = new InfinniUI.Collection([ + {key: 1, value: 'A'}, + {key: 2, value: 'B'}, + {key: 3, value: 'C'}, + {key: 4, value: 'D'} + ], 'key'), + handlers = bindAllEvents(collection); + + assert.isTrue(collection.removeAll([ + {key: 1, value: 'A'}, + {key: 3, value: 'C'}])); + + assert.deepEqual(collection.toArray(), [ + {key: 2, value: 'B'}, + {key: 4, value: 'D'}]); + + assert.isTrue(collection.removeAll([ + {key: 2, value: 'B'}, + {key: 4, value: 'D'}])); + assert.deepEqual(collection.toArray(), []); + + assert.isTrue(handlers.checkEvent('onRemove', 2), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange', 2), 'onChange event'); + }); + }); + + describe("removeRange", function () { + + it("should remove range items", function () { + var collection = new InfinniUI.Collection(['A', 'B', 'C', 'D']), + handlers = bindAllEvents(collection); + + assert.isTrue(collection.removeRange(1, 2)); + assert.deepEqual(collection.toArray(), ['A', 'D']); + + assert.isTrue(collection.removeRange(0)); + assert.deepEqual(collection.toArray(), []); + + assert.isTrue(handlers.checkEvent('onRemove', 2), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange', 2), 'onChange event'); + }); + + it("should remove range items", function () { + var collection = new InfinniUI.Collection([ + null, + null, + {key: 1, value: 'A'}, {key: 2, value: 'B'} + ], 'key'), + handlers = bindAllEvents(collection); + + assert.isTrue(collection.removeRange(1, 2)); + assert.deepEqual(collection.toArray(), [null, {key: 2, value: 'B'}]); + + assert.isTrue(collection.removeRange(0)); + assert.deepEqual(collection.toArray(), []); + + assert.isTrue(handlers.checkEvent('onRemove', 2), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange', 2), 'onChange event'); + }); + + }); + + describe("removeEvery()", function () { + + it("should remove every item", function () { + var + changed, + collection = new InfinniUI.Collection([1, 10, 2, 20, 3, 30]), + handlers = bindAllEvents(collection); + + changed = collection.removeEvery(function (item, index, collection) { + return item >= 10; + }); + assert.isTrue(changed); + assert.deepEqual(collection.toArray(), [1, 2, 3]); + assert.isTrue(handlers.checkEvent('onRemove'), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }); + + it("should remove every object", function () { + var changed, + collection = new InfinniUI.Collection([ + null, + null, + {key: 1, value: 'A'}, + {key: 2, value: 'B'}, + {key: 3, value: 'A'} + ], 'key'), + handlers = bindAllEvents(collection); + + changed = collection.removeEvery(function (item, index, collection) { + return item && item.key % 2 === 1; + }); + + assert.isTrue(changed); + assert.deepEqual(collection.toArray(), [ + null, + null, + {key: 2, value: 'B'} + ]); + assert.isTrue(handlers.checkEvent('onRemove'), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + + handlers.reset(); + changed = collection.removeEvery(function (item, index, collection) { + return item === null; + }); + + assert.isTrue(changed); + assert.deepEqual(collection.toArray(), [ + {key: 2, value: 'B'} + ]); + assert.isTrue(handlers.checkEvent('onRemove'), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }); + }); + + describe("clear()", function () { + it("should clear collection", function () { + var collection = new InfinniUI.Collection(['A', 'B', 'C']), + handlers = bindAllEvents(collection); + + assert.isTrue(collection.clear()); + assert.equal(collection.length, 0); + assert.isTrue(handlers.checkEvent('onRemove'), 'onRemove event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }); + }); + + describe("getById()", function () { + + it("should get object by id", function () { + var objects = [ + {key: 1, value: 'A'}, + {key: 2, value: 'B'}, + {key: 3, value: 'C'} + ], + collection = new InfinniUI.Collection(objects, 'key'); + + assert.equal(collection.getById(1), objects[0]); + assert.equal(collection.getById(2), objects[1]); + assert.equal(collection.getById(3), objects[2]); + }); + + it("should return undefined on missing id", function () { + var objects = [ + {key: 1, value: 'A'}, + {key: 2, value: 'B'}, + {key: 3, value: 'C'} + ], + collection = new InfinniUI.Collection(objects, 'key'); + + assert.isTrue(typeof collection.getById(4) === 'undefined'); + }); + }); + + describe("getByIndex()", function () { + it("should return item by index", function () { + var collection = new InfinniUI.Collection(['A', 'B', 'C']); + + assert.equal(collection.getByIndex(0), 'A'); + assert.equal(collection.getByIndex(1), 'B'); + assert.equal(collection.getByIndex(2), 'C'); + }); + }); + + describe("find()", function () { + + it("should return item", function () { + //When + var collection = new InfinniUI.Collection([1, 3, 5, 6, 7, 9, 11, 12]); + //Then + var item = collection.find(function (item, index, collection) { + return item % 2 === 0; + }); + assert.equal(item, 6); + }); + + it("should return object", function () { + //When + var objects = [ + {key: 1, value: 'A'}, + {key: 3, value: 'B'}, + {key: 5, value: 'C'}, + {key: 6, value: 'A'}, + {key: 7, value: 'B'}, + {key: 9, value: 'C'}, + {key: 11, value: 'B'}, + {key: 12, value: 'C'} + ], + collection = new InfinniUI.Collection(objects, 'key'); + //Then + var item = collection.find(function (item, index, collection) { + return item.key % 2 === 0; + }); + assert.equal(item, objects[3]); + }); + + }); + + describe("indexOf()", function () { + + it("should return index of item", function () { + //When + var collection = new InfinniUI.Collection(['A', 'B', 'C', 'A', 'B', 'C']); + //Then + assert.equal(collection.indexOf('C'), 2); + assert.equal(collection.indexOf('C', 3), 5); + assert.equal(collection.indexOf('D'), -1); + }); + + it("should return index of object", function () { + //When + var collection = new InfinniUI.Collection([ + {key: 1, value: 'A'}, + {key: 2, value: 'B'}, + {key: 3, value: 'C'}, + {key: 1, value: 'A'}, + {key: 2, value: 'B'}, + {key: 3, value: 'C'} + ], 'key'); + + //Then + assert.equal(collection.indexOf({key: 3, value: 'C'}), 2); + assert.equal(collection.indexOf({key: 3, value: 'C'}, 3), 5); + assert.equal(collection.indexOf({key: 4, value: 'D'}), -1); + }) + + }); + + describe("lastIndexOf()", function () { + + it("should return last index of item", function () { + //When + var collection = new InfinniUI.Collection(['A', 'B', 'C', 'A', 'B', 'C']); + //Then + assert.equal(collection.lastIndexOf('C'), 5); + assert.equal(collection.lastIndexOf('C', 4), 2); + assert.equal(collection.lastIndexOf('D'), -1); + }); + + it("should return last index of object", function () { + //When + var collection = new InfinniUI.Collection([ + {key: 1, value: 'A'}, + {key: 2, value: 'B'}, + {key: 3, value: 'C'}, + {key: 1, value: 'A'}, + {key: 2, value: 'B'}, + {key: 3, value: 'C'} + ], 'key'); + //Then + assert.equal(collection.lastIndexOf({key: 3, value: 'C'}), 5); + assert.equal(collection.lastIndexOf({key: 3, value: 'C'}, 4), 2); + assert.equal(collection.lastIndexOf({key: 4, value: 'D'}), -1); + }); + }); + + describe("findIndex()", function () { + + it("should return index of item", function () { + //When + var collection = new InfinniUI.Collection([1, 3, 5, 6, 7, 9, 11, 12]); + //Then + var index = collection.findIndex(function (item, index, collection) { + return item % 2 === 0; + }); + assert.equal(index, 3); + }); + + it("should return index of object", function () { + //When + var collection = new InfinniUI.Collection([ + {key: 1, value: 'A'}, + {key: 3, value: 'B'}, + {key: 5, value: 'C'}, + {key: 6, value: 'A'}, + {key: 7, value: 'B'}, + {key: 9, value: 'C'}, + {key: 11, value: 'B'}, + {key: 12, value: 'C'} + ], 'key'); + //Then + var index = collection.findIndex(function (item, index, collection) { + return item.key % 2 === 0; + }); + assert.equal(index, 3); + }); + + }); + + describe("contains()", function () { + + it("should check item in collection", function () { + //When + var collection = new InfinniUI.Collection(['A', 'B', 'C']); + //Then + assert.isTrue(collection.contains('A'), 'A'); + assert.isTrue(collection.contains('B'), 'B'); + assert.isTrue(collection.contains('C'), 'C'); + assert.isFalse(collection.contains('A', 1), 'A'); + assert.isFalse(collection.contains('B', 2), 'B'); + assert.isFalse(collection.contains('C', 3), 'C'); + }); + + it("should check object in collection", function () { + //When + var collection = new InfinniUI.Collection([ + {key: 1, value: 'A'}, + {key: 2, value: 'B'}, + {key: 3, value: 'C'} + ], 'key'); + //Then + assert.isTrue(collection.contains({key: 1, value: 'A'}), 'contains A'); + assert.isTrue(collection.contains({key: 2, value: 'B'}), 'contains B'); + assert.isTrue(collection.contains({key: 3, value: 'C'}), 'contains C'); + assert.isFalse(collection.contains({key: 1, value: 'A'}, 1), '!contains A'); + assert.isFalse(collection.contains({key: 2, value: 'B'}, 2), '!contains B'); + assert.isFalse(collection.contains({key: 3, value: 'C'}, 3), '!contains C'); + }); + }); + + describe("every()", function () { + + it("should check every item", function () { + var isBigEnough = function (item, index, collection) { + return item >= 10; + }; + + assert.isFalse(new InfinniUI.Collection([12, 5, 8, 130, 44]).every(isBigEnough)); + assert.isTrue(new InfinniUI.Collection([12, 54, 18, 130, 44]).every(isBigEnough)); + }); + + it("should check every object", function () { + var isBigEnough = function (item, index, collection) { + return item.value >= 10; + }; + + assert.isFalse(new InfinniUI.Collection([ + {id: 1, value: 12}, + {id: 2, value: 5}, + {id: 3, value: 8}, + {id: 4, value: 130}, + {id: 5, value: 44}]).every(isBigEnough)); + + assert.isTrue(new InfinniUI.Collection([ + {id: 1, value: 12}, + {id: 2, value: 54}, + {id: 3, value: 18}, + {id: 4, value: 130}, + {id: 5, value: 44}]).every(isBigEnough)); + }); + }); + + describe("some()", function () { + + it("should check some item", function () { + function isBiggerThan10(item, index, collection) { + return item > 10; + } + + assert.isFalse(new InfinniUI.Collection([2, 5, 8, 1, 4]).some(isBiggerThan10)); + assert.isTrue(new InfinniUI.Collection([12, 5, 8, 1, 4]).some(isBiggerThan10)); + }); + + it("should check some object", function () { + function isBiggerThan10(item, index, collection) { + return item.value > 10; + } + + assert.isFalse(new InfinniUI.Collection([ + {id: 1, value: 2}, + {id: 2, value: 5}, + {id: 3, value: 8}, + {id: 4, value: 1}, + {id: 5, value: 4}]).some(isBiggerThan10)); + assert.isTrue(new InfinniUI.Collection([ + {id: 1, value: 12}, + {id: 2, value: 5}, + {id: 3, value: 8}, + {id: 4, value: 1}, + {id: 5, value: 4}]).some(isBiggerThan10)); + }); + + }); + + describe("forEach()", function () { + + it("should call for each item", function () { + //When + var objects = ['A', 'B', 'C']; + var collection = new InfinniUI.Collection(objects); + var result = []; + collection.forEach(function (item, index, collection) { + result.push(item); + }); + //Then + assert.deepEqual(result, objects); + }); + + }); + + describe("filter()", function () { + + it("should filter items", function () { + //When + var isBigEnough = function (item, index, collection) { + return item >= 10; + }; + var collection = new InfinniUI.Collection([12, 5, 8, 130, 44]); + //Then + assert.deepEqual(collection.filter(isBigEnough), [12, 130, 44]); + }); + + }); + + describe("take()", function () { + it("should return items", function () { + //When + var collection = new InfinniUI.Collection(['A', 'B', 'C', 'D']); + //Then + assert.deepEqual(collection.take(1, 2), ['B', 'C']); + assert.deepEqual(collection.take(2), ['C', 'D']); + }); + }); + + describe("toArray()", function () { + + it("should return items", function () { + var collection = new InfinniUI.Collection(['A', 'B', 'C']); + var array = collection.toArray(); + + collection.push('X'); + array.push('Y'); + + var items = []; + collection.forEach(function (item) { + items.push(item); + }); + assert.deepEqual(items, ['A', 'B', 'C', 'X']); + assert.deepEqual(array, ['A', 'B', 'C', 'Y']); + }); + }); + + describe("move()", function () { + + it("should move items", function () { + var collection = new InfinniUI.Collection(['A', 'B', 'C']), + handlers = bindAllEvents(collection); + + collection.move(2, 0); + assert.deepEqual(collection.toArray(), ['C', 'A', 'B']); + assert.isTrue(handlers.checkEvent('onMove'), 'onMove event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + + handlers.reset(); + collection.move(2, 1); + assert.deepEqual(collection.toArray(), ['C', 'B', 'A']); + assert.isTrue(handlers.checkEvent('onMove'), 'onMove event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }); + }); + + describe("sort()", function () { + + it("should sort items", function () { + var collection = new InfinniUI.Collection([3, 30, 2, 20, 1, 10]), + handlers = bindAllEvents(collection), + comparator = function (a, b) { + return a - b + }; + + var changed = collection.sort(comparator); + + assert.isTrue(changed); + assert.deepEqual(collection.toArray(), [1, 2, 3, 10, 20, 30]); + assert.isTrue(handlers.checkEvent('onReset'), 'onReset event'); + assert.isTrue(handlers.checkEvent('onChange'), 'onChange event'); + }); + + it("should sort items", function () { + var collection = new InfinniUI.Collection([ + {value: 3, title: "3"}, + {value: 30, title: "30"}, + {value: 2, title: "2"}, + {value: 20, title: "20"}, + {value: 1, title: "1"}, + {value: 10, title: "10"}], 'value'), + comparator = function (a, b) { + return a.value - b.value; + }; + + var changed = collection.sort(comparator); + + assert.isTrue(changed); + assert.deepEqual(collection.toArray(), [ + {value: 1, title: "1"}, + {value: 2, title: "2"}, + {value: 3, title: "3"}, + {value: 10, title: "10"}, + {value: 20, title: "20"}, + {value: 30, title: "30"}]); + }); + + }); + + describe("clone()", function () { + + it("should clone collection", function () { + var collection1 = new InfinniUI.Collection(['A', 'B', 'C']); + var collection2 = collection1.clone(); + + collection1.add('X'); + collection2.add('Y'); + + assert.deepEqual(collection1.toArray(), ['A', 'B', 'C', 'X']); + assert.deepEqual(collection2.toArray(), ['A', 'B', 'C', 'Y']); + }); + }); + + describe('Custom properties', function () { + + it ('should set property', function () { + // Given + var collection = new InfinniUI.Collection([3,2,1]); + collection + .setProperty(0, 'name', 'three') + .setProperty(1, 'name', 'two') + .setProperty(2, 'name', 'one'); + + // When + collection.sort(); + + // Then + assert.deepEqual(collection.toArray(), [1, 2, 3]); + assert.equal(collection.getProperty(0, 'name'), 'one'); + assert.equal(collection.getProperty(1, 'name'), 'two'); + assert.equal(collection.getProperty(2, 'name'), 'three'); + }); + + }); + + describe("Events", function () { + var + collection, + events = 'onAdd,onReplace,onRemove,onMove,onReset,onChange'.split(','), + handlers, + bindEvents = function () { + handlers = []; + + events.forEach(function (event) { + + collection[event](function (context, argument) { + handlers.push(event); + }); + }); + } + + + describe("Collection.onAdd", function () { + it("should raise onAdd & onChange event", function () { + //when + collection = new InfinniUI.Collection(); + bindEvents(); + collection.add('A'); + //then + assert.equal("onAdd,onChange", handlers.join(',')); + }); + }); + + describe("Collection.onReplace", function () { + it("should raise onReplace & onChange event", function () { + //when + collection = new InfinniUI.Collection(['A']); + bindEvents(); + collection.replace('A', 'B'); + //then + assert.equal("onReplace,onChange", handlers.join(',')); + assert.deepEqual(collection.toArray(), ['B']); + }); + }); + + describe("Collection.onRemove", function () { + it("should raise onRemove & onChange event", function () { + //when + collection = new InfinniUI.Collection(['A']); + bindEvents(); + collection.remove('A'); + //then + assert.equal("onRemove,onChange", handlers.join(',')); + assert.deepEqual(collection.toArray(), []); + }); + }); + + describe("Collection.onMove", function () { + it("should raise onMove & onChange event", function () { + //when + collection = new InfinniUI.Collection(['A', 'B']); + bindEvents(); + collection.move(1, 0); + //then + assert.equal("onMove,onChange", handlers.join(',')); + assert.deepEqual(collection.toArray(), ['B', 'A']); + }); + }); + + describe("Collection.onReset", function () { + it("should raise onReset & onChange event", function () { + //when + collection = new InfinniUI.Collection(); + bindEvents(); + collection.reset(['A', 'B']); + //then + assert.equal("onReset,onChange", handlers.join(',')); + assert.deepEqual(collection.toArray(), ['A', 'B']); + }); + }); + + describe("Collection.onChange", function () { + it("should raise onChange event on setElements", function () { + //when + collection = new InfinniUI.Collection(); + bindEvents(); + collection.set(['A', 'B']); + //then + assert.equal("onReset,onChange", handlers.join(',')); + assert.deepEqual(collection.toArray(), ['A', 'B']); + }); + }); + }) + + +}); + + + + +describe("dateUtils", function () { + + describe("toISO8601", function () { + //Format DateTime: "YYYY-MM-DDTHH:MM:SS.SSSS+hh:mm + var date, timezoneOffset; + + + it("should return date for current timezone offset", function () { + //Given + date = new Date(2016, 2, 18, 15, 58, 30); + timezoneOffset = date.getTimezoneOffset(); + + // When + var strDate = InfinniUI.DateUtils.toISO8601(date); + // Then + var dtPart = getDateTimePart(strDate); + var tzPart = getTimeZoneOffset(strDate); + + assert.equal(dtPart, "2016-03-18T15:58:30.0000", 'Check DateTime part'); + assert.equal(tzPart, timezoneOffset, 'Check TimeZoneOffset part'); + }); + + it("should return date for given timezone offset", function () { + //Given + var tzOffset = 0 - 60*3; //UTC + 3 + date = new Date('2016-03-18T10:58:30Z'); + timezoneOffset = date.getTimezoneOffset(); + + // When + var strDate = InfinniUI.DateUtils.toISO8601(date, { + timezoneOffset: tzOffset + }); + //Then + var dtPart = getDateTimePart(strDate); + var tzPart = getTimeZoneOffset(strDate); + + assert.equal(dtPart, "2016-03-18T13:58:30.0000", 'Check DateTime part'); + assert.equal(tzPart, tzOffset, 'Check TimeZoneOffset part'); + }); + + function getDateTimePart(strDate) { + return strDate.substr(0, 'yyyy-mm-ddThh:mm:ss.SSSS'.length); + } + + function getTimeZoneOffset(strDate) { + return 60 * strDate.substr(0 - '+HH:MM'.length) + .split(':') + .map(function (val) { + return parseInt(val, 10); + }) + .reduce(function (sum, val) { + return sum - val; + }, 0); + } + + }); +}); +describe("Filter items", function () { + describe("Filter items", function () { + it("FilterItems should return all items that have given param", function () { + // Given + var filter = 'eq(index,-1.9)'; + var items = [ + {Id: 1, index: -1.9}, + {Id: 2}, + {Id: 3} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].index, -1.9, 'filtered item is correct'); + }); + + it("FilterItems should return all items that have all given params", function () { + // Given + var filter = "and(eq(phrase,'param'),eq(index,2))"; + var items = [ + {Id: 1, phrase: 'param', index: 2}, + {Id: 2, index: 2}, + {Id: 3} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + }); + + it("FilterItems should return all items that have at least one of given params", function () { + // Given + var filter = 'or(eq(Id,1),eq(props.fontSize,30))'; + var items = [ + {Id: 1}, + {Id: 2}, + {Id: 3}, + {Id: 4, props: {fontSize: 30}} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 4, 'filtered item is correct'); + }); + + it("FilterItems should return all items but not given item(s)", function () { + // Given + var filter = 'not(eq(Id,3))'; + // var filter = 'not(or(eq(Id,3),eq(Id,1)))'; + var items = [ + {Id: 1}, + {Id: 2}, + {Id: 3} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 2, 'filtered item is correct'); + }); + + it("FilterItems should return all items accept given item with given param", function () { + // Given + var filter = 'notEq(Id,2)'; + var items = [ + {Id: 1}, + {Id: 2}, + {Id: 3} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 3, 'filtered item is correct'); + }); + + it("FilterItems should return all items that have value of given param greater then given value", function () { + // Given + var filter = 'gt(Id,2)'; + var items = [ + {Id: 1}, + {Id: 2}, + {Id: 3}, + {Id: 4}, + {Id: 5} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 3, 'length of filtered items is right'); + assert.equal(result1[0].Id, 3, 'filtered item is correct'); + assert.equal(result1[1].Id, 4, 'filtered item is correct'); + assert.equal(result1[2].Id, 5, 'filtered item is correct'); + }); + + it("FilterItems should return all items that have value of given param greater then given value or equal to it", function () { + // Given + var filter = "gte(birthday,date('2012-01-26T13:51:50.417Z'))"; + var items = [ + {Id: 1, birthday: 1327515910.417}, + {Id: 2, birthday: 1327512910.417}, + {Id: 3, birthday: 1327594910.417}, + {Id: 4, birthday: 1327591910.417}, + {Id: 5, birthday: 1327597910.417} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 3, 'length of filtered items is right'); + assert.equal(result1[0].Id, 3, 'filtered item is correct'); + assert.equal(result1[1].Id, 4, 'filtered item is correct'); + assert.equal(result1[2].Id, 5, 'filtered item is correct'); + }); + + it("FilterItems should return all items that have value of given param lower then given value", function () { + // Given + var filter = 'lt(Id,2)'; + var items = [ + {Id: 1}, + {Id: 2}, + {Id: 3}, + {Id: 4}, + {Id: 5} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + }); + + it("FilterItems should return all items that have value of given param lower then given value or equal to it", function () { + // Given + var filter = 'lte(Id,3)'; + var items = [ + {Id: 1}, + {Id: 2}, + {Id: 3}, + {Id: 4}, + {Id: 5} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 3, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 2, 'filtered item is correct'); + assert.equal(result1[2].Id, 3, 'filtered item is correct'); + }); + + it("FilterItems should return all items that have in the given param value that match to one of given in values", function () { + // Given + var filter = 'in(index,1,3,4)'; + var items = [ + {Id: 1, index: 2}, + {Id: 2, index: 3}, + {Id: 3, index: 2}, + {Id: 4, index: 4}, + {Id: 5, index: 1} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 3, 'length of filtered items is right'); + assert.equal(result1[0].Id, 2, 'filtered item is correct'); + assert.equal(result1[1].Id, 4, 'filtered item is correct'); + assert.equal(result1[2].Id, 5, 'filtered item is correct'); + }); + + it("FilterItems should return all items that have NOT in the given param value that match to one of given in values", function () { + // Given + var filter = 'notIn(index,1,3,4)'; + var items = [ + {Id: 1, index: 2}, + {Id: 2, index: 3}, + {Id: 3, index: 2}, + {Id: 4, index: 4}, + {Id: 5, index: 1} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 3, 'filtered item is correct'); + }); + + it("FilterItems should return all items where exist the given param and it NOT equal to null or undefined", function () { + // Given + var filter = 'exists(index)'; + var items = [ + {Id: 1, index: 2}, + {Id: 2, index: 3}, + {Id: 3, index: null}, + {Id: 4, index: 4}, + {Id: 5} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 3, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 2, 'filtered item is correct'); + assert.equal(result1[2].Id, 4, 'filtered item is correct'); + }); + + it("FilterItems should return all items where exist the given param and it NOT equal to null or undefined", function () { + // Given + var filter = 'exists(index,true)'; + var items = [ + {Id: 1, index: null}, + {Id: 2, index: 3}, + {Id: 3, index: 5}, + {Id: 4, index: 4}, + {Id: 5} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 3, 'length of filtered items is right'); + assert.equal(result1[0].Id, 2, 'filtered item is correct'); + assert.equal(result1[1].Id, 3, 'filtered item is correct'); + assert.equal(result1[2].Id, 4, 'filtered item is correct'); + }); + + it("FilterItems should return all items where doesn't exist the given param or it equal to null or undefined", function () { + // Given + var filter = 'exists(index,false)'; + var items = [ + {Id: 1}, + {Id: 2, index: 3}, + {Id: 3, index: 5}, + {Id: 4, index: 4}, + {Id: 5, index: null} + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 5, 'filtered item is correct'); + }); + + it("FilterItems should return all items that have param with array of objects that all have the second param", function () { + // Given + var filter = "match(props,eq(name,'font'))"; + var items = [ + { + Id: 1, + props: [ {name: 'font', size: 20}, {name: 'font', family: 'Arial'}, {name: 'font', weight: 'bold'} ] + }, + { + Id: 2, + props: [ {name: 'fontCommon', size: 24}, {name: 'fontCommon', family: 'Tahoma'}, {name: 'fontCommon', weight: 'bold'} ] + }, + { + Id: 3, + props: [ {name: 'font', size: 22}, {name: 'font', family: 'Arial'}, {name: 'font', weight: 'bold'} ] + }, + { + Id: 4, + props: [ {name: 'font', size: 20}, {name: 'textIndent', size: 10}, {name: 'font', weight: 'bold'} ] + }, + { + Id: 5, + props: [ {name: 'font', size: 20}, {name: 'font', family: 'Arial'}, {name: 'textIndent', size: 10} ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 3, 'filtered item is correct'); + }); + + it("FilterItems should return all items that suit to filter param", function () { + // Given + var filter = "match(props,or(and(eq(name,'font'),eq(size,20)),and(eq(name,'font'),eq(size,10))))"; + var items = [ + { + Id: 1, + props: [ {name: 'font', size: 20}, {name: 'font', size: 20}, {name: 'font', size: 20} ] + }, + { + Id: 2, + props: [ {name: 'fontCommon', size: 24}, {name: 'fontCommon', size: 20}, {name: 'fontCommon', size: 20} ] + }, + { + Id: 3, + props: [ {name: 'font', size: 20}, {name: 'font', size: 20}, {name: 'font', size: 20} ] + }, + { + Id: 4, + props: [ {name: 'font', size: 20}, {name: 'textIndent', size: 10}, {name: 'font', weight: 'bold'} ] + }, + { + Id: 5, + props: [ {name: 'font', size: 25}, {name: 'font', size: 25}, {name: 'font', size: 25} ] + }, + { + Id: 6, + props: [ {name: 'font', size: 10}, {name: 'font', size: 10}, {name: 'font', size: 10} ] + }, + { + Id: 7, + props: [ {name: 'font', size: 10}, {name: 'font', size: 10}, {name: 'font', size: 10} ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 4, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 3, 'filtered item is correct'); + assert.equal(result1[2].Id, 6, 'filtered item is correct'); + assert.equal(result1[3].Id, 7, 'filtered item is correct'); + }); + + it("FilterItems should return all items that suit to filter param", function () { + // Given + var filter = "match(props,not(eq(name,'font')))"; + var items = [ + { + Id: 1, + props: [ {name: 'font', size: 20}, {name: 'font', family: 'Arial'}, {name: 'font', weight: 'bold'} ] + }, + { + Id: 2, + props: [ {name: 'fontCommon', size: 24}, {name: 'fontCommon', family: 'Tahoma'}, {name: 'fontCommon', weight: 'bold'} ] + }, + { + Id: 3, + props: [ {name: 'font', size: 22}, {name: 'font', family: 'Arial'}, {name: 'font', weight: 'bold'} ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 2, 'filtered item is correct'); + }); + + it("FilterItems should return all items that suit to filter param", function () { + // Given + var filter = "match(props,not(notEq(name,'font')))"; + var items = [ + { + Id: 1, + props: [ {name: 'font', size: 20}, {name: 'font', family: 'Arial'}, {name: 'font', weight: 'bold'} ] + }, + { + Id: 2, + props: [ {name: 'fontCommon', size: 24}, {name: 'fontCommon', family: 'Tahoma'}, {name: 'fontCommon', weight: 'bold'} ] + }, + { + Id: 3, + props: [ {name: 'font', size: 22}, {name: 'font', family: 'Arial'}, {name: 'font', weight: 'bold'} ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 3, 'filtered item is correct'); + }); + + it("FilterItems should return all items where all elements in array from first param suit to a bunch of second param", function () { + // Given + var filter = "all(items, 1, 2, 3, 4)"; + var items = [ + { + Id: 1, + items: [ 1, 2, 3, 4 ] + }, + { + Id: 2, + items: [ 2, 3, 4, 5 ] + }, + { + Id: 3, + items: [ 4, 6, 7, 8 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + }); + + it("FilterItems should return all items where all elements in array from first param suit to a bunch of second param", function () { + // Given + var filter = "all(items, 'hello', 'world')"; + var items = [ + { + Id: 1, + items: [ 'hello', 'world', 'from', 'russia' ] + }, + { + Id: 2, + items: [ 'hello', 'world' ] + }, + { + Id: 3, + items: [ 'hello', 'world', 'from', 'russia' ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 2, 'filtered item is correct'); + }); + + it("FilterItems should return all items where at least one element in array from first param suit to a bunch of second param", function () { + // Given + var filter = "anyIn(items, 1, 2, 3, 4)"; + var items = [ + { + Id: 1, + items: [ 1, 2, 3, 4 ] + }, + { + Id: 2, + items: [ 5, 6, 7, 8 ] + }, + { + Id: 3, + items: [ 4, 6, 7, 8 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 3, 'filtered item is correct'); + }); + + it("FilterItems should return all items where all elements in array from first param NOT suit to a bunch of second param", function () { + // Given + var filter = "anyNotIn(items, 1, 2, 3, 4)"; + var items = [ + { + Id: 1, + items: [ 1, 2, 3, 4 ] + }, + { + Id: 2, + items: [ 5, 6, 7, 8 ] + }, + { + Id: 3, + items: [ 4, 6, 7, 8 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 2, 'filtered item is correct'); + }); + + it("FilterItems should return all items where at least one element in array from first param suit to second param", function () { + // Given + var filter = "anyEq(items, 144)"; + var items = [ + { + Id: 1, + items: [ 1, 2, 3, 4 ] + }, + { + Id: 2, + items: [ 5, 144, 7, 8 ] + }, + { + Id: 3, + items: [ 4, 6, 7, 8 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 2, 'filtered item is correct'); + }); + + it("FilterItems should return all items where at least one element in array from first param NOT suit to second param", function () { + // Given + var filter = "anyNotEq(items, 144)"; + var items = [ + { + Id: 1, + items: [ 144, 144, 144, 144 ] + }, + { + Id: 2, + items: [ 144, 144, 144, 144 ] + }, + { + Id: 3, + items: [ 144, 8, 144, 144 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 3, 'filtered item is correct'); + }); + + it("FilterItems should return all items where at least one element in array from first param greater then second param", function () { + // Given + var filter = "anyGt(items, 144)"; + var items = [ + { + Id: 1, + items: [ 144, 333, 144, 144 ] + }, + { + Id: 2, + items: [ 144, 144, 144, 144 ] + }, + { + Id: 3, + items: [ 144, 8, 144, 144 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + }); + + it("FilterItems should return all items where at least one element in array from first param greater or equal then second param", function () { + // Given + var filter = "anyGte(items, 145)"; + var items = [ + { + Id: 1, + items: [ 144, 333, 144, 144 ] + }, + { + Id: 2, + items: [ 144, 145, 144, 144 ] + }, + { + Id: 3, + items: [ 144, 8, 144, 144 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 2, 'filtered item is correct'); + }); + + it("FilterItems should return all items where at least one element in array from first param lower then second param", function () { + // Given + var filter = "anyLt(items, 144)"; + var items = [ + { + Id: 1, + items: [ 144, 144, 144, 144 ] + }, + { + Id: 2, + items: [ 144, 144, 144, 144 ] + }, + { + Id: 3, + items: [ 144, 8, 144, 144 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 3, 'filtered item is correct'); + }); + + it("FilterItems should return all items where at least one element in array from first param lower or equal then second param", function () { + // Given + var filter = "anyLte(items, 140)"; + var items = [ + { + Id: 1, + items: [ 144, 144, 144, 144 ] + }, + { + Id: 2, + items: [ 144, 140, 144, 144 ] + }, + { + Id: 3, + items: [ 144, 8, 144, 144 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 2, 'filtered item is correct'); + assert.equal(result1[1].Id, 3, 'filtered item is correct'); + }); + + it("FilterItems should return all items where length of array form first param equal to second param", function () { + // Given + var filter = "sizeEq(items, 4)"; + var items = [ + { + Id: 1, + items: [ 144, 144, 144, 144, 544 ] + }, + { + Id: 2, + items: [ 144, 140, 144, 144 ] + }, + { + Id: 3, + items: [ 144, 8, 144, 144 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 2, 'filtered item is correct'); + assert.equal(result1[1].Id, 3, 'filtered item is correct'); + }); + + it("FilterItems should return all items where length of array form first param NOT equal to second param", function () { + // Given + var filter = "sizeNotEq(items, 4)"; + var items = [ + { + Id: 1, + items: [ 144, 144, 144, 144, 544 ] + }, + { + Id: 2, + items: [ 144, 140, 144, 144 ] + }, + { + Id: 3, + items: [ 144, 8, 144, 144 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + }); + + it("FilterItems should return all items where length of array form first param greater then second param", function () { + // Given + var filter = "sizeGt(items, 4)"; + var items = [ + { + Id: 1, + items: [ 144, 144, 144, 144, 544 ] + }, + { + Id: 2, + items: [ 144, 140, 144, 144 ] + }, + { + Id: 3, + items: [ 144, 8, 144, 144 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + }); + + it("FilterItems should return all items where length of array form first param greater or equal then second param", function () { + // Given + var filter = "sizeGte(items, 4)"; + var items = [ + { + Id: 1, + items: [ 144, 144, 144, 144, 544 ] + }, + { + Id: 2, + items: [ 144, 140, 144, 144 ] + }, + { + Id: 3, + items: [ 144, 8, 144 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 2, 'filtered item is correct'); + }); + + it("FilterItems should return all items where length of array form first param lower then second param", function () { + // Given + var filter = "sizeLt(items, 4)"; + var items = [ + { + Id: 1, + items: [ 144, 144, 144, 144, 544 ] + }, + { + Id: 2, + items: [ 144, 140, 144, 144 ] + }, + { + Id: 3, + items: [ 144, 8, 144 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 3, 'filtered item is correct'); + }); + + it("FilterItems should return all items where length of array form first param lower or equal then second param", function () { + // Given + var filter = "sizeLte(items, 4)"; + var items = [ + { + Id: 1, + items: [ 144, 144, 144, 144, 544 ] + }, + { + Id: 2, + items: [ 144, 140, 144, 144 ] + }, + { + Id: 3, + items: [ 144, 8, 144 ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 2, 'filtered item is correct'); + assert.equal(result1[1].Id, 3, 'filtered item is correct'); + }); + + it("FilterItems should return all items which suit to regexp expression", function () { + // Given + var filter = "regexp(propName, '[0-9]+', g, i)"; + var items = [ + { + Id: 1, + propName: 'font123' + }, + { + Id: 2, + propName: 'borderWidth' + }, + { + Id: 3, + propName: 'backgroundSize' + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 1, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + }); + + it("FilterItems should return all items which suit to regexp expression", function () { + // Given + var filter = "regexp(firstName, '^И(ван|рина)$', g, i)"; + var items = [ + { + Id: 1, + firstName: 'Иван' + }, + { + Id: 2, + firstName: 'Ирина' + }, + { + Id: 3, + firstName: 'Вася' + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 2, 'filtered item is correct'); + }); + + it("FilterItems should return all items have a text inner", function () { + // Given + var filter = "text('hello world')"; + var items = [ + { + Id: 1, + phrase: 'Hello world' + }, + { + Id: 2, + friendPhrase: 'hello Ivan!' + }, + { + Id: 3, + welcomePhrase: 'hello bro!', + friendList: [ + {name: 'Vasya', welcomePhrase: 'hello world'}, + {name: 'Ivan', welcomePhrase: 'hello there!'} + ] + } + ]; + // When + var result1 = InfinniUI.FilterItems(items, filter); + // Then + assert.lengthOf(result1, 2, 'length of filtered items is right'); + assert.equal(result1[0].Id, 1, 'filtered item is correct'); + assert.equal(result1[1].Id, 3, 'filtered item is correct'); + }); + + + }); +}); + +describe("ObjectUtils", function () { + describe("getPropertyValue", function () { + it("should return null when target is null or undefined", function () { + // When + var result1 = InfinniUI.ObjectUtils.getPropertyValue(null, "Property1"); + var result2 = InfinniUI.ObjectUtils.getPropertyValue(undefined, "Property1"); + + // Then + assert.isNull(result1); + assert.isNull(result2); + }); + + it("should return null when property is not exists", function () { + // Given + var target = { }; + + // When + var result = InfinniUI.ObjectUtils.getPropertyValue(target, "NotExistsProperty"); + + // Then + assert.isNull(result); + }); + + it("should return collection item when target is collection", function () { + // Given + var target = [ 11, 22, 33 ]; + + // When + var item0 = InfinniUI.ObjectUtils.getPropertyValue(target, "0"); + var item1 = InfinniUI.ObjectUtils.getPropertyValue(target, "1"); + var item2 = InfinniUI.ObjectUtils.getPropertyValue(target, "2"); + var item3 = InfinniUI.ObjectUtils.getPropertyValue(target, "3"); + + // Then + assert.equal(item0, 11); + assert.equal(item1, 22); + assert.equal(item2, 33); + assert.isNull(item3); + }); + + it("should return property value", function () { + // Given + var value = { }; + var target = { Property1: value }; + + // When + var result = InfinniUI.ObjectUtils.getPropertyValue(target, "Property1"); + + // Then + assert.equal(result, value); + }); + + it("should return nested property value", function () { + // Given + var value = { }; + var target = { Property1: { Property2: value } }; + + // When + var result = InfinniUI.ObjectUtils.getPropertyValue(target, "Property1.Property2"); + + // Then + assert.equal(result, value); + }); + + it("should return property value of specified collection item", function () { + // Given + var target = { + Collection1: [ + { Property1: 11 }, + { Property1: 22 }, + { Property1: 33 } + ] + }; + + // When + var item0 = InfinniUI.ObjectUtils.getPropertyValue(target, "Collection1.0.Property1"); + var item1 = InfinniUI.ObjectUtils.getPropertyValue(target, "Collection1.1.Property1"); + var item2 = InfinniUI.ObjectUtils.getPropertyValue(target, "Collection1.2.Property1"); + var item3 = InfinniUI.ObjectUtils.getPropertyValue(target, "Collection1.3.Property1"); + + // Then + assert.equal(item0, 11); + assert.equal(item1, 22); + assert.equal(item2, 33); + assert.isNull(item3); + }); + }); + + describe("setPropertyValue", function () { + it("should not throw exception when target is null or undefined", function () { + InfinniUI.ObjectUtils.setPropertyValue(null, "property1", { }); + InfinniUI.ObjectUtils.setPropertyValue(undefined, "property1", { }); + }); + + it("should set property value", function () { + // Given + var target = { property1: 123 }; + var propertyValue = 321; + + // When + InfinniUI.ObjectUtils.setPropertyValue(target, "property1", propertyValue); + + // Then + assert.equal(target.property1, propertyValue); + }); + + it("should set nested property value", function () { + // Given + var target = { property1: { property2: 123 } }; + var propertyValue = 321; + + // When + InfinniUI.ObjectUtils.setPropertyValue(target, "property1.property2", propertyValue); + + // Then + assert.equal(target.property1.property2, propertyValue); + }); + + it("should create all not exists properties in path", function () { + // Given + var target = { }; + var propertyValue = { }; + + // When + InfinniUI.ObjectUtils.setPropertyValue(target, "property1.property2.property3", propertyValue); + + // Then + assert.isObject(target.property1.property2.property3); + assert.isObject(propertyValue); + assert.equal(_.isEmpty(target.property1.property2.property3), _.isEmpty(propertyValue)); + }); + + it("should replace collection item when target is collection", function () { + // Given + var target = [ 11, 0, 33 ]; + + // When + InfinniUI.ObjectUtils.setPropertyValue(target, "1", 22); + + // Then + assert.equal(target.length, 3); + assert.equal(target[0], 11); + assert.equal(target[1], 22); + assert.equal(target[2], 33); + }); + + it("should set property of specified collection item", function () { + // Given + var target = { collection1: [ { property1: 11 }, { property1: 0 }, { property1: 33 } ] }; + + // When + InfinniUI.ObjectUtils.setPropertyValue(target, "collection1.1.property1", 22); + + // Then + assert.equal(target.collection1.length, 3); + assert.equal(target.collection1[0].property1, 11); + assert.equal(target.collection1[1].property1, 22); + assert.equal(target.collection1[2].property1, 33); + }); + }); +}); +describe('ButtonControl', function () { + describe('render', function () { + var builder = new InfinniUI.ApplicationBuilder() + , button; + + beforeEach(function () { + button = builder.buildType('Button', {}); + }); + + it('should render button with correct class', function () { + //Given + button.setText('Click me!'); + + //When + var $el = button.render(); + + //Then + assert.isTrue($el.hasClass('pl-button')); + assert.equal($.trim($el.text()), 'Click me!'); + }); + }); +}); + +describe('CheckBox', function () { + var checkbox; + + beforeEach(function () { + checkbox = new InfinniUI.CheckBox(); + }); + + describe('Render', function () { + + describe('Setting the properties', function () { + + it('Setting property: visible', function () { + //Given + var $el = checkbox.render(); + assert.isFalse($el.hasClass('hidden')); + + //When + checkbox.setVisible(false); + + //Then + assert.isTrue($el.hasClass('hidden')); + }); + + it('Setting property: text', function () { + //Given + checkbox.setText('Text 1'); + + var $el = checkbox.render(), + $label = $('.checkbox-label', $el); + + assert.equal($label.html(), 'Text 1'); + + //When + checkbox.setText('Text 2'); + + //Then + assert.equal($label.html(), 'Text 2'); + }); + + it('Setting property: Enabled', function () { + //Given + var $el = checkbox.render(), + $input = $('input', $el); + + assert.equal($input.prop('disabled'), false, 'Enabled by default'); + + //When + checkbox.setEnabled(false); + + //Then + assert.equal($input.prop('disabled'), true, 'Disable element'); + }); + + }); + + describe('events', function () { + it('Change value on click', function () { + //Given + var $el = checkbox.render(), + $input = $('input', $el); + + checkbox.setValue(false); + + //When + $input.click(); + + //Then + assert.equal(checkbox.getValue(), true, 'value changed'); + assert.equal($input.prop('checked'), true, 'checkbox checked'); + }); + }); + + }); + +}); + +describe('Container (Control)', function () { + + describe('StackPanel as exemplar of Container', function () { + + it('should render stackPanel with templating items', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "LTE" }, + { "Id": 2, "Display": "3G" }, + { "Id": 3, "Display": "2G" } + ] + } + } + ], + Items: [{ + + StackPanel: { + Name: 'MainViewPanel', + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + } + } + }] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.lengthOf($layout.find('.pl-stack-panel-i'), 3, 'length of rendered stackPanel'); + assert.lengthOf($layout.find('.pl-text-box-input'), 3, 'length of rendered textbox'); + assert.equal($layout.find('.pl-text-box-input:first').val(), 'LTE', 'binding in itemTemplate is right'); + } + }); + + + it('should render stackPanel with not templating items', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "LTE" }, + { "Id": 2, "Display": "3G" }, + { "Id": 3, "Display": "2G" } + ] + } + } + ], + Items: [{ + + StackPanel: { + Name: 'MainViewPanel', + "Items" : [ + { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "Display" + } + } + },{ + "TextBox": { + "Name": "TextBox2", + "Value": { + "Source": "ObjectDataSource1", + "Property": "Id" + } + } + } + ] + } + }] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.lengthOf($layout.find('.pl-stack-panel-i'), 2, 'length of rendered stackPanel'); + assert.lengthOf($layout.find('.pl-text-box-input'), 2, 'length of rendered textbox'); + assert.equal($layout.find('.pl-text-box-input:first').val(), 'LTE', 'binding in itemTemplate is right'); + } + }); + + + it('should render stackPanel with simple items', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + "LTE", + "3G", + "2G" + ] + } + } + ], + Items: [{ + + StackPanel: { + Name: 'MainViewPanel', + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + } + } + }] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.lengthOf($layout.find('.pl-stack-panel-i'), 3, 'length of rendered stackPanel'); + assert.lengthOf($layout.find('.pl-label').not(':empty'), 3, 'length of rendered stackPanel'); + assert.equal($layout.find('.pl-label').first().text(), 'LTE', 'content of first element is right'); + } + }); + + + it('should render stackPanel with property items', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { + Name: {Temp: "LTE"} + }, + { + Name: {Temp: "3G"} + }, + { + Name: {Temp: "2G"} + } + ] + } + } + ], + Items: [{ + + StackPanel: { + Name: 'MainViewPanel', + "ItemProperty": "Name.Temp", + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + } + } + }] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.lengthOf($layout.find('.pl-stack-panel-i'), 3, 'length of rendered stackPanel'); + assert.lengthOf($layout.find('.pl-label').not(':empty'), 3, 'length of rendered stackPanel'); + assert.equal($layout.find('.pl-label').first().text(), 'LTE', 'content of first element is right'); + } + }); + + + + it('should render stackPanel with formatting items', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { + Name: {Temp: "LTE"} + }, + { + Name: {Temp: "3G"} + }, + { + Name: {Temp: "2G"} + } + ] + } + } + ], + Items: [{ + + StackPanel: { + Name: 'MainViewPanel', + "ItemFormat": "Connect: {Name.Temp}", + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + } + } + }] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.lengthOf($layout.find('.pl-stack-panel-i'), 3, 'length of rendered stackPanel'); + assert.lengthOf($layout.find('.pl-label').not(':empty'), 3, 'length of rendered stackPanel'); + assert.equal($layout.find('.pl-label').first().text(), 'Connect: LTE', 'content of first element is right'); + } + }); + + + it('should render stackPanel with selector items', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { + Name: {Temp: "LTE"} + }, + { + Name: {Temp: "3G"} + }, + { + Name: {Temp: "2G"} + } + ] + } + } + ], + Items: [{ + + StackPanel: { + Name: 'MainViewPanel', + "ItemSelector":{ + Name: 'GetTitle' + }, + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + } + } + }], + + Scripts: [ + { + Name: 'GetTitle', + Body: "return '!! ' + args.value.Name.Temp;" + } + ] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.lengthOf($layout.find('.pl-stack-panel-i'), 3, 'length of rendered stackPanel'); + assert.lengthOf($layout.find('.pl-label').not(':empty'), 3, 'length of rendered stackPanel'); + assert.equal($layout.find('.pl-label').first().text(), '!! LTE', 'content of first element is right'); + } + }); + + + it('should stackPanel has child and parent (templating items)', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "LTE" }, + { "Id": 2, "Display": "3G" }, + { "Id": 3, "Display": "2G" } + ] + } + } + ], + Items: [{ + + StackPanel: { + Name: 'MainViewPanel', + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + } + } + }] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + var stackPanel = view.getContext().controls['MainViewPanel']; + + assert.instanceOf(stackPanel.getParent(), InfinniUI.View, 'stackPanel parent is View'); + assert.lengthOf(stackPanel.getChildElements(), 3, 'length of stackPanel children is right'); + assert.equal(stackPanel.getChildElements()[0].getParent(), stackPanel, 'child of stackPanel has parent - stackPanel'); + + // When + var ds = view.getContext().dataSources['ObjectDataSource1'], + items = ds.getItems(); + + items.reverse(); + + ds.setItems(items); + ds.updateItems(); + + // Then + assert.lengthOf(stackPanel.getChildElements(), 3, 'length of stackPanel children is right (after updating items)'); + } + }); + + it('should stackPanel working with relative binding', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [{ + "It": [{ "Id": 1, "Display": "LTE" }, + { "Id": 2, "Display": "3G" }, + { "Id": 3, "Display": "2G" } + ] + }] + } + } + ], + Items: [{ + + StackPanel: { + Name: 'MainViewPanel', + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "@.#.Display" + } + } + }, + "Items" : { + "Source": "ObjectDataSource1", + "Property": "$.It" + } + } + }] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.lengthOf($layout.find('.pl-text-box-input'), 3, 'count of textboxes is right'); + assert.equal($layout.find('.pl-text-box-input:first').val(), 'LTE', 'value in first textbox is right'); + assert.equal($layout.find('.pl-text-box-input:last').val(), '2G', 'value in last textbox is right'); + } + }); + + it('should stackPanel working with deep relative binding', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [{ + "It": [{ + id: 1, + subIt: [{ "Id": 1, "Display": "LTE" }, + { "Id": 2, "Display": "3G" }, + { "Id": 3, "Display": "2G" }] + },{ + id: 2, + subIt: [{ "Id": 1, "Display": "LTE-2" }, + { "Id": 2, "Display": "3G-2" }, + { "Id": 3, "Display": "2G-2" }] + } + ] + }] + } + } + ], + Items: [{ + + StackPanel: { + Name: 'MainViewPanel', + "ItemTemplate": { + "StackPanel": { + "Items" : [ + { + "Label":{ + "Value":{ + "Source": "ObjectDataSource1", + "Property": "@.#.id" + } + } + }, + { + "StackPanel": { + "Items" : { + "Source": "ObjectDataSource1", + "Property": "@.#.subIt" + }, + "ItemTemplate":{ + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "@.#.Display" + } + } + } + } + } + ] + } + + }, + "Items" : { + "Source": "ObjectDataSource1", + "Property": "$.It" + } + } + }] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.lengthOf($layout.find('.pl-text-box-input'), 6, 'count of textboxes is right'); + assert.equal($layout.find('.pl-text-box-input:first').val(), 'LTE', 'value in first textbox is right'); + assert.equal($layout.find('.pl-text-box-input:last').val(), '2G-2', 'value in last textbox is right'); + } + }); + }); + + + + describe('ListBox as exemplar of Container', function (){ + + it('should render listBox without grouping', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "LTE" }, + { "Id": 2, "Display": "2G" }, + { "Id": 3, "Display": "2G" } + ] + } + } + ], + Items: [{ + + ListBox: { + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + } + } + }] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.lengthOf($layout.find('.pl-listbox-body'), 3, 'length of rendered listbox'); + assert.equal($layout.find('.pl-text-box-input').first().val(), 'LTE', 'value in template is right'); + } + }); + + }); + + it('should render listBox with grouping (with template group title)', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "LTE" }, + { "Id": 2, "Display": "2G" }, + { "Id": 3, "Display": "2G" } + ] + } + } + ], + Items: [{ + + StackPanel: { + Name: 'MainViewPanel', + "Items" : [ + { + ListBox: { + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "GroupItemTemplate": { + "Label": { + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "GroupValueProperty": "Display", + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + } + } + } + ] + } + }] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.lengthOf($layout.find('.pl-listbox-body'), 3, 'length of rendered listbox is right'); + assert.lengthOf($layout.find('.pl-listbox-group-i'), 2, 'length of rendered group is right'); + assert.equal($layout.find('.pl-text-box-input').first().val(), 'LTE', 'value in template is right'); + assert.equal($.trim( $layout.find('.pl-listbox-group-title').last().text() ), '2G', 'group value in template is right'); + } + }); + + + it('should render listBox with grouping (with format group title)', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "LTE" }, + { "Id": 2, "Display": "2G" }, + { "Id": 3, "Display": "2G" } + ] + } + } + ], + Items: [{ + + StackPanel: { + Name: 'MainViewPanel', + "Items" : [ + { + ListBox: { + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "GroupItemFormat": "Connect: {Display}", + "GroupValueProperty": "Display", + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + } + } + } + ] + } + }] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.lengthOf($layout.find('.pl-listbox-body'), 3, 'length of rendered listbox is right'); + assert.lengthOf($layout.find('.pl-listbox-group-i'), 2, 'length of rendered group is right'); + assert.equal($layout.find('.pl-text-box-input').first().val(), 'LTE', 'value in template is right'); + assert.equal($.trim( $layout.find('.pl-listbox-group-title').last().text() ), 'Connect: 2G', 'group value in template is right'); + } + }); + + it('should render listBox with sorting items', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 2, "Display": "LTE" }, + { "Id": 1, "Display": "2G" }, + { "Id": 3, "Display": "2G" } + ] + } + } + ], + Items: [{ + + ListBox: { + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + }, + + "ItemComparator": { + "Name": "IdComparator" + } + } + }], + + "Scripts":[ + { + Name: 'IdComparator', + Body: "return args.item2.Id - args.item1.Id;" + } + ] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.lengthOf($layout.find('.pl-listbox-body'), 3, 'length of rendered listbox'); + assert.equal($layout.find('.pl-text-box-input').eq(0).val(), '2G', 'value in template is right'); + assert.equal($layout.find('.pl-text-box-input').eq(1).val(), 'LTE', 'value in template is right'); + assert.equal($layout.find('.pl-text-box-input').eq(2).val(), '2G', 'value in template is right'); + } + }); +}); + +describe('ContextMenu (Control)', function () { + + describe('Remove element from ListBox by clicking on button from ContextMenu', function () { + + it('should remove selected item from DS', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "LTE" }, + { "Id": 2, "Display": "3G" }, + { "Id": 3, "Display": "2G" } + ] + } + } + ], + Items: [ + { + ListBox: { + ViewMode: "common", + ItemProperty: "Display", + Items: { + Source: "ObjectDataSource1" + }, + "ItemTemplate":{ + "Label": { + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + ContextMenu: { + Items: [ + { + Button: { + ViewMode: "link", + Text: "RemoveElement", + Action: { + DeleteAction: { + DestinationValue: { + Source: "ObjectDataSource1", + Property: "$" + } + } + } + } + } + ] + } + } + } + ] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + $($layout.find('.pl-listbox-i')[1]).trigger('click'); + view.childElements[0].childElements[0].childElements[0].click(); + $('a[data-index=0]').trigger('click'); + assert.lengthOf($layout.find('.pl-listbox-i'), 2, 'length of rest items in listbox'); + assert.equal($layout.find('.pl-listbox-i:nth-child(1) span[title]').text(), 'LTE', 'binding in itemTemplate is right'); + assert.equal($layout.find('.pl-listbox-i:nth-child(2) span[title]').text(), '2G', 'binding in itemTemplate is right'); + } + }); + }); +}); + +describe('DataNavigationControl', function () { + describe('render', function () { + var builder = new InfinniUI.ApplicationBuilder() + , button; + + beforeEach(function () { + button = builder.buildType('DataNavigation', {}); + }); + + it('should render dataNavigation with correct class', function () { + //Given + + //When + var $el = button.render(); + + //Then + assert.isTrue($el.hasClass('pl-data-navigation')); + }); + }); +}); + +describe('DateTimePickerControl', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + describe('render', function () { + it('should update date when change value', function () { + //Given + var dateTimePicker = builder.buildType('DateTimePicker', {}); + var oldDate = new Date(2012, 10, 2); + var newDate = new Date(2014, 7, 28); + var $el = dateTimePicker.render().find('.pl-datepicker-input'); + dateTimePicker.setValue(InfinniUI.DateUtils.toISO8601(oldDate)); + + //When + dateTimePicker.setValue(InfinniUI.DateUtils.toISO8601(newDate)); + + //Then + assert.equal($el.val(), '28.08.2014'); + }); + + it('should clear date when value is null', function () { + //Given + var dateTimePicker = new InfinniUI.DateTimePickerControl(); + var value = InfinniUI.DateUtils.toISO8601(new Date(2012, 10, 2)); + + dateTimePicker.setValue(value); + assert.equal( dateTimePicker.getValue(), value); + + //When + dateTimePicker.setValue(null); + + //Then + assert.isNull(dateTimePicker.getValue()); + }); + + it('should set minDate and maxDate', function () { + //Given + var dateTimePicker = builder.buildType('DateTimePicker', {}); + var minDate = InfinniUI.DateUtils.toISO8601(new Date(2010, 0, 1)); + var maxDate = InfinniUI.DateUtils.toISO8601(new Date(2014, 11, 31)); + + //When + dateTimePicker.setMinValue(minDate); + dateTimePicker.setMaxValue(maxDate); + + //Then + assert.equal(dateTimePicker.getMinValue(), minDate); + assert.equal(dateTimePicker.getMaxValue(), maxDate); + }); + + it('should set Enabled', function () { + //Given + var dateTimePicker = builder.buildType('DateTimePicker', {}); + dateTimePicker.setEnabled(false); + + var $el = dateTimePicker.render().find('.pl-datepicker-input, .pl-datepicker-calendar'); + assert.equal($el.length, 2); + $el.each(function (i, el) { + var $el = $(el); + assert.isTrue($el.prop('disabled')); + }); + + //When + dateTimePicker.setEnabled(true); + + //Then + $el.each(function (i, el) { + var $el = $(el); + assert.isFalse($el.prop('disabled')); + }); + + }); + + }); +}); + +describe('Form (Control)', function () { + + describe('Check Form element', function () { + + it('should update from default method attribute', function () { + // Given + var metadata = { + Items: [ + { + Form: { + "Items": [ + { + "TextBox": { + "Value": "username" + } + } + ] + } + } + ] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.equal($layout.find('.pl-form').attr('method'), '', 'attribute method is right'); + + view.childElements[0].setMethod('post'); + + assert.equal($layout.find('.pl-form').attr('method'), 'post', 'attribute method is right'); + + view.childElements[0].setMethod('get'); + + assert.equal($layout.find('.pl-form').attr('method'), 'get', 'attribute method is right'); + } + }); + + it('should update from default action attribute', function () { + // Given + var metadata = { + Items: [ + { + Form: { + "Items": [ + { + "TextBox": { + "Value": "username" + } + } + ] + } + } + ] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.equal($layout.find('.pl-form').attr('action'), '', 'attribute action is right'); + + view.childElements[0].setAction('/blabla'); + + assert.equal($layout.find('.pl-form').attr('action'), '/blabla', 'attribute action is right'); + } + }); + + it('should change value of attribute method on submit event', function () { + // Given + var metadata = { + Items: [ + { + Form: { + "Method": "get", + "OnSubmit": "{ context.view.childElements[0].setMethod('post') }", + "Items": [ + { + "Button": { + "Type": "submit" + } + } + ] + } + } + ] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.equal($layout.find('.pl-form').attr('method'), 'get', 'attribute method is right'); + + $layout.find('.pl-button button').click(); + + assert.equal($layout.find('.pl-form').attr('method'), 'post', 'attribute method is right'); + } + }); + }); +}); + +describe('Frame', function () { + var frame; + + beforeEach(function () { + frame = new InfinniUI.Frame(); + }); + + describe('Render', function () { + + describe('Setting the properties', function () { + + it('Setting property: value', function () { + //Given + var $el = frame.render(); + + //When + frame.setValue('http://docs.infinnity.ru/'); + + //Then + assert.equal($el.find('iframe').attr('src'), 'http://docs.infinnity.ru/'); + }); + + + }); + + }); + +}); + +describe('IndeterminateCheckBox', function () { + var indeterminateCheckBox; + + beforeEach(function () { + indeterminateCheckBox = new InfinniUI.IndeterminateCheckBox(); + }); + + describe('Render', function () { + + describe('Setting the properties', function () { + + it('Setting property: visible', function () { + //Given + var $el = indeterminateCheckBox.render(); + assert.isFalse($el.hasClass('hidden')); + + //When + indeterminateCheckBox.setVisible(false); + + //Then + assert.isTrue($el.hasClass('hidden')); + }); + + it('Setting property: text', function () { + //Given + indeterminateCheckBox.setText('Text 1'); + + var $el = indeterminateCheckBox.render(), + $label = $('.checkbox-label', $el); + + assert.equal($label.html(), 'Text 1'); + + //When + indeterminateCheckBox.setText('Text 2'); + + //Then + assert.equal($label.html(), 'Text 2'); + }); + + it('Setting property: Enabled', function () { + //Given + var $el = indeterminateCheckBox.render(), + $input = $('input', $el); + + assert.equal($input.prop('disabled'), false, 'Enabled by default'); + + //When + indeterminateCheckBox.setEnabled(false); + + //Then + assert.equal($input.prop('disabled'), true, 'Disable element'); + }); + + it('Setting property: indeterminate', function () { + //Given + var $el = indeterminateCheckBox.render(), + $input = $('input', $el); + + assert.equal($input.prop('indeterminate'), false, 'Indeterminate state by default'); + + //When + indeterminateCheckBox.setValue('indeterminate'); + + //Then + assert.equal($input.prop('indeterminate'), true, 'Indeterminate state for indeterminateCheckBox'); + }); + + }); + + describe('events', function () { + it('Change value on click', function () { + //Given + var $el = indeterminateCheckBox.render(), + $input = $('input', $el); + + indeterminateCheckBox.setValue('unchecked'); + + //When + $input.click(); + + //Then + assert.equal(indeterminateCheckBox.getValue(), 'checked', 'value changed'); + assert.equal($input.prop('checked'), true, 'indeterminateCheckBox checked'); + assert.equal($input.prop('indeterminate'), false, 'Indeterminate state by default'); + + //When + $input.click(); + + //Then + assert.equal(indeterminateCheckBox.getValue(), 'unchecked', 'value changed'); + assert.equal($input.prop('checked'), false, 'indeterminateCheckBox checked'); + assert.equal($input.prop('indeterminate'), false, 'Indeterminate state by default'); + + //When + $input.click(); + + //Then + assert.equal(indeterminateCheckBox.getValue(), 'checked', 'value changed'); + assert.equal($input.prop('checked'), true, 'indeterminateCheckBox checked'); + assert.equal($input.prop('indeterminate'), false, 'Indeterminate state by default'); + }); + }); + + }); + +}); + +describe('Label', function () { + var label; + + beforeEach(function () { + label = new InfinniUI.Label(); + }); + + describe('Render', function () { + + describe('Setting the properties', function () { + + it('Setting property: name', function () { + //Given + var $el = label.render(); + assert.isUndefined($el.attr('pl-data-pl-name')); + + //When + label.setName('NewLabel'); + + //Then + assert.equal($el.attr('data-pl-name'), 'NewLabel'); + }); + + it('Setting property: visible', function () { + //Given + var $el = label.render(); + assert.isFalse($el.hasClass('hidden')); + + //When + label.setVisible(false); + + //Then + assert.isTrue($el.hasClass('hidden')); + }); + + it('Setting property: horizontalAlignment', function () { + //Given + var $el = label.render(); + assert.isTrue($el.hasClass('pl-text-horizontal-Left')); + assert.isFalse($el.hasClass('pl-text-horizontal-Right')); + assert.isFalse($el.hasClass('pl-text-horizontal-Center')); + assert.isFalse($el.hasClass('pl-text-horizontal-Justify')); + + //When + label.setTextHorizontalAlignment('Right'); + + //Then + assert.isTrue($el.hasClass('pl-text-horizontal-Right')); + assert.isFalse($el.hasClass('pl-text-horizontal-Left')); + assert.isFalse($el.hasClass('pl-text-horizontal-Center')); + assert.isFalse($el.hasClass('pl-text-horizontal-Justify')); + }); + + it('Setting property: text', function () { + //Given + label.setText('Default Label'); + + var $label = label.render(); + + assert.equal($label.html(), 'Default Label'); + + //When + label.setText('New Label'); + + //Then + assert.equal($label.html(), 'New Label'); + }); + + it('Setting property: textWrapping', function () { + //Given + var $label = label.render(); + + assert.isTrue($label.hasClass('pl-text-wrapping'), 'default value must be true'); + + //When + label.setTextWrapping(false); + + //Then + assert.isFalse($label.hasClass('pl-text-wrapping'), 'should not wrap if value false'); + }); + + it('Setting property: textTrimming', function () { + //Given + var $label = label.render(); + + assert.isTrue($label.hasClass('pl-text-trimming'), 'default value must be true'); + + //When + label.setTextTrimming(false); + + //Then + assert.isFalse($label.hasClass('pl-text-trimming'), 'should not trim if value false'); + }); + }); + + }); +}); + +describe('Link (Control)', function () { + + describe('Check href and target params in LinkElement', function () { + + it('should update from default href attribute', function () { + // Given + var metadata = { + Items: [ + { + Link: { + + } + } + ] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.equal($layout.find('.pl-link').attr('href'), 'javascript:;', 'attribute href is right'); + + view.childElements[0].setHref('common.ru'); + assert.equal($layout.find('.pl-link').attr('href'), 'common.ru', 'attribute href is right'); + + view.childElements[0].setHref('example.com'); + assert.equal($layout.find('.pl-link').attr('href'), 'example.com', 'attribute href is right'); + } + }); + + it('should update from default target attribute', function () { + // Given + var metadata = { + Items: [ + { + Link: { + + } + } + ] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + + + assert.equal($layout.find('.pl-link').attr('target'), '_self', 'attribute target is right'); + + view.childElements[0].setTarget('blank'); + assert.equal($layout.find('.pl-link').attr('target'), '_blank', 'attribute target is right'); + } + }); + + it('should apply href and target attributes from metadata', function () { + // Given + var metadata = { + Items: [ + { + Link: { + "Href": "http://example.com", + "Target": "top" + } + } + ] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.equal($layout.find('.pl-link').attr('href'), 'http://example.com', 'attribute href is right'); + assert.equal($layout.find('.pl-link').attr('target'), '_top', 'attribute target is right'); + + view.childElements[0].setHref('http://exampleNew.com'); + assert.equal($layout.find('.pl-link').attr('href'), 'http://exampleNew.com', 'attribute href is right'); + + view.childElements[0].setTarget('blank'); + assert.equal($layout.find('.pl-link').attr('target'), '_blank', 'attribute target is right'); + } + }); + }); +}); + +describe('PanelControl', function () { + + describe('render', function () { + it('Should render StackPanel with 4 Panel as ItemTemplate', function () { + // Given + var metadata = { + "DataSources": [ + { + "ObjectDataSource": { + "Name": "BloodGroupDataSource", + "Items": [ + { + "Id": 1, + "DisplayName": "I", + "SomeField": "" + }, + { + "Id": 2, + "DisplayName": "II", + "SomeField": "val" + }, + { + "Id": 3, + "DisplayName": "III", + "SomeField": 3 + }, + { + "Id": 4, + "DisplayName": "IV", + "SomeField": null + } + ] + } + } + ], + "Items": [ + { + "TablePanel": { + "Name": "", + "Items": [ + { + "Row": { + "Items": [ + { + "Cell": { + "ColumnSpan": 3, + "Items": [ + { + "StackPanel": { + "Name": "StackPanel_1", + "Items": { + "Source": "BloodGroupDataSource", + "Property": "" + }, + "ItemTemplate": { + "Panel": { + "Collapsible": true, + "Header": { + "Source": "BloodGroupDataSource", + "Property": "#.DisplayName" + }, + "Items": [ + { + "Label": { + "Text": { + "Source": "BloodGroupDataSource", + "Property": "#.Id" + } + } + } + ] + } + } + } + } + ] + } + } + ] + } + } + ] + } + } + ], + "Scripts": [ + { + "Name": "OnExpanded", + "Body": "console.log('OnExpanded');" + }, + { + "Name": "OnCollapsed", + "Body": "console.log('OnCollapsed');" + }, + { + "Name": "OnExpanding", + "Body": "console.log('OnExpanding');" + }, + { + "Name": "OnCollapsing", + "Body": "console.log('OnCollapsing');" + } + ] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout) { + $layout.detach(); + var $panels = $layout.find('.pl-panel'); + + + assert.equal($panels.length, 4); + + $panels.each(function (index, el) { + var $el = $(el), + $header = $el.find('.pl-panel-header'), + $body = $el.find('.pl-panel-body'), + header = $header.find('.pl-label').text(), + body = $body.find('.pl-label').text(); + + assert.isTrue($header.hasClass('pl-collapsible')); + assert.isFalse($header.hasClass('pl-collapsed')); + switch (index) { + case 0: + assert.equal(header, 'I'); + assert.equal(body, '1'); + break; + case 1: + assert.equal(header, 'II'); + assert.equal(body, '2'); + break; + case 2: + assert.equal(header, 'III'); + assert.equal(body, '3'); + break; + case 3: + assert.equal(header, 'IV'); + assert.equal(body, '4'); + $header.click(); + assert.isTrue($header.hasClass('pl-collapsed'), 'collapse on click'); + break; + } + + }); + + } + }); + + it('Should render Panel with 3 items(as label)', function () { + // Given + var metadata = { + "DataSources": [ + { + "ObjectDataSource": { + "Name": "BloodGroupDataSource", + "Items": [ + { + "Id": 1, + "DisplayName": "I", + "SomeField": "" + }, + { + "Id": 2, + "DisplayName": "II", + "SomeField": "val" + }, + { + "Id": 3, + "DisplayName": "III", + "SomeField": 3 + }, + { + "Id": 4, + "DisplayName": "IV", + "SomeField": null + } + ] + } + } + ], + "Items": [ + { + "TablePanel": { + "Name": "", + "Items": [ + { + "Row": { + "Items": [ + { + "Cell": { + "ColumnSpan": 3, + "Items": [ + { + "Panel": { + "Collapsible": true, + "Collapsed": true, + "Header": "Header", + "Items": [ + { + "Label": { + "Text": "One" + } + }, + { + "Label": { + "Text": "Two" + } + }, + { + "Label": { + "Text": "Three" + } + } + ] + } + } + ] + } + } + ] + } + } + ] + } + } + ], + "Scripts": [ + { + "Name": "OnExpanded", + "Body": "console.log('OnExpanded');" + }, + { + "Name": "OnCollapsed", + "Body": "console.log('OnCollapsed');" + }, + { + "Name": "OnExpanding", + "Body": "console.log('OnExpanding');" + }, + { + "Name": "OnCollapsing", + "Body": "console.log('OnCollapsing');" + } + ] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout) { + $layout.detach(); + var $panel = $layout.find('.pl-panel'), + $header = $panel.find('.pl-panel-header'), + $body = $panel.find('.pl-panel-body'), + header = $header.find('.pl-label').text(), + $items = $body.find('.pl-panel-i'); + + + assert.equal($items.length, 3); + assert.isTrue($header.hasClass('pl-collapsible')); + assert.isTrue($header.hasClass('pl-collapsed')); + $items.each(function (index, el) { + var text = $('.pl-label', el).text(); + + switch(index) { + case 0: + assert.equal(text, 'One'); + break; + case 1: + assert.equal(text, 'Two'); + break; + case 2: + assert.equal(text, 'Three'); + break; + } + }); + + } + }); + }); +}); +describe('PasswordBox', function () { + + var element; + + beforeEach(function () { + element = new InfinniUI.PasswordBox(); + }); + + describe('Render', function () { + + describe('Setting the properties', function () { + + it('Setting property: name', function () { + //Given + var $el = element.render(); + assert.isUndefined($el.attr('pl-data-pl-name')); + + //When + element.setName('UserPassword'); + + //Then + assert.equal($el.attr('data-pl-name'), 'UserPassword'); + }); + + it('Setting property: visible', function () { + //Given + var $el = element.render(); + assert.isFalse($el.hasClass('hidden')); + + //When + element.setVisible(false); + + //Then + assert.isTrue($el.hasClass('hidden')); + }); + + it('Setting property: labelText', function () { + //Given + var + label = "User's password", + $el = element.render(), + $label = $('label', $el); + + //When + element.setLabelText(label); + + //Then + assert.equal($label.html(), label); + }); + + it('Setting property: hintText', function () { + //Given + var + hint = "my hint", + $el = element.render(), + $hint = $('.pl-control-hint-text ', $el); + + //When + element.setHintText(hint); + + //Then + assert.equal($hint.html(), hint); + assert.isFalse($hint.hasClass('hidden')); + }); + + it('Setting property: errorText', function () { + //Given + var + text = "error", + $el = element.render(), + $text = $('.pl-control-error-text ', $el); + + //When + element.setErrorText(text); + + //Then + assert.equal($text.html(), text); + assert.isFalse($text.hasClass('hidden')); + }); + + it('Setting property: warningText', function () { + //Given + var + text = "warning", + $el = element.render(), + $text = $('.pl-control-warning-text ', $el); + + //When + element.setWarningText(text); + + //Then + assert.equal($text.html(), text); + assert.isFalse($text.hasClass('hidden')); + }); + + it('Setting property: enabled', function () { + //Given + var + $el = element.render(), + $input = $('input', $el); + + //When + element.setEnabled(false); + + //Then + assert.isTrue($input.prop('disabled')); + assert.isTrue($el.hasClass('pl-disabled')); + }); + + }); + + }); + +}); + +describe('PopupButtonControl', function () { + describe('render', function () { + var builder = new InfinniUI.ApplicationBuilder(), + button; + + beforeEach(function () { + button = builder.buildType('PopupButton', { + Items: [ + { + "Button": { + "Name": "AddButton", + "Text": "Add" + } + }, + { + "Button": { + "Name": "DropButton", + "Text": "Drop" + } + }, + { + "Button": { + "Name": "BackButton", + "Text": "Back" + } + } + ] + }); + }); + + + it('should render button with correct class', function () { + //Given + button.setText('Click me!'); + //When + var $el = button.render(); + //Then + var $button = $el.find('.pl-popup-button__button'); + assert.isTrue($el.hasClass('pl-popup-button'), 'control class'); + assert.equal($button.length, 1, 'button render'); + assert.equal($button.text(), 'Click me!', 'button text'); + $('body').find('.pl-popup-button__dropdown').detach(); + }); + + it('should handle onClick', function () { + //Given + var click = 0; + button.setText('Click me!'); + button.onClick(function () { + click++; + }); + //When + var $el = button.render(); + button.click(); + //Then + assert.isTrue(click === 1); + $('body').find('.pl-popup-button__dropdown').detach(); + }); + + }); +}); + +describe('ScrollPanelControl', function () { + + describe('render', function () { + it('Should render ScrollPanel', function () { + + // Given + var metadata = { + "DataSources": [ + { + "ObjectDataSource": { + "Name": "BloodGroupDataSource", + "Items": [ + { + "Id": 1, + "DisplayName": "I", + "SomeField": "" + }, + { + "Id": 2, + "DisplayName": "II", + "SomeField": "val" + }, + { + "Id": 3, + "DisplayName": "III", + "SomeField": 3 + }, + { + "Id": 4, + "DisplayName": "IV", + "SomeField": null + } + ] + } + } + ], + "Items": [ + { + "TablePanel": { + "Name": "", + "Items": [ + { + "Row": { + "Items": [ + { + "Cell": { + "ColumnSpan": 3, + "Items": [ + { + "ScrollPanel": { + "Name":"ScrollPanel_1", + "Items": [{ + "Label": { + "Text": "Label 1" + } + }, + { + "Label": { + "Text": "Label 2" + } + }, + { + "Label": { + "Text": "Label 3" + } + }, + { + "Label": { + "Text": "Label 4" + } + } + ] + } + } + ] + } + } + ] + } + } + ] + } + } + ] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout) { + $layout.detach(); + var + $panel = $layout.find('.pl-scrollpanel'), + $body = $panel.find('.pl-scrollpanel-body'), + $content = $body.find('.pl-scrollpanel-i'); + + assert.equal($panel.length, 1, 'container'); + assert.equal($body.length, 1, 'body'); + assert.equal($content.length, 4, 'items'); + + assert.isTrue($panel.hasClass('pl-horizontal-scroll-auto')); + assert.isTrue($panel.hasClass('pl-vertical-scroll-auto')); + } + }); + }); +}); +describe('TabPanelControl', function () { + + describe('render', function () { + it('Should render TabPanel with 3 TabPages', function () { + + // Given + var metadata = { + "DataSources": [ + { + "ObjectDataSource": { + "Name": "BloodGroupDataSource", + "Items": [ + { + "Id": 1, + "DisplayName": "I", + "SomeField": "" + }, + { + "Id": 2, + "DisplayName": "II", + "SomeField": "val" + }, + { + "Id": 3, + "DisplayName": "III", + "SomeField": 3 + }, + { + "Id": 4, + "DisplayName": "IV", + "SomeField": null + } + ] + } + } + ], + "Items": [ + { + "TabPanel": { + "OnSelectedItemChanged": { + "Name": "OnSelectedItemChanged" + }, + "HeaderLocation": "Left", + "Items": [ + { + "TabPage": { + "Text": "Header of Page1", + "Items": [ + { + "Label": { + "Text": "Content of Page1" + } + } + ] + } + }, + { + "TabPage": { + "Text": "Header of Page2", + "CanClose": true, + "OnClosing": { + "Name": "OnClosing" + }, + "OnClosed": { + "Name": "OnClosed2" + }, + "Items": [ + { + "Label": { + "Text": "Content of Page2" + } + } + ] + } + }, + { + "TabPage": { + "Text": "Header of Page3", + "CanClose": true, + "Items": [ + { + "Label": { + "Text": "Content of Page3" + } + } + ] + } + } + ] + } + } + ], + "Scripts": [ + { + "Name": "OnClosing", + "Body": "var defer = $.Deferred(); setTimeout(function () {defer.resolve('ok');}, 3000); return defer.promise();" + }, + { + "Name": "OnClosed2", + "Body": "console.log('OnClosed2');" + }, + { + "Name": "OnSelectedItemChanged", + "Body": "console.log('OnSelectedItemChanged');" + } + ] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout) { + $layout.detach(); + var + $panel = $layout.find('.pl-tabpanel'), + $header = $layout.find('.pl-tabpanel-header'), + $content = $layout.find('.pl-tabpanel-content'), + + $headers = $header.find('.pl-tabheader'), + $pages = $content.find('.pl-tabpage'); + + assert.equal($panel.length, 1, 'container'); + assert.equal($header.length, 1, 'header'); + assert.equal($content.length, 1, 'content'); + assert.equal($headers.length, 3, 'headers'); + assert.equal($pages.length, 3, 'pages'); + } + }); + }); +}); +describe('TextBoxControl', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + + describe('render', function () { + it('Setting the properties: value, name, enabled, visible, horizontalAlignment', function () { + // Given + var element = builder.buildType('TextBox', {}); + var + $el = element.render(), + $control = $el.find('input'); + + assert.equal($control.val(), ''); + assert.isUndefined($el.attr('data-pl-name')); + assert.isFalse($control.prop('disabled')); + assert.isFalse($el.hasClass('hidden')); + assert.isFalse($el.hasClass('pl-horizontal-Left')); + + // When + element.setValue('new'); + element.setName('newName'); + element.setEnabled(false); + element.setVisible(false); + element.setHorizontalAlignment('Left'); + + // Then + assert.equal($control.val(), 'new'); + assert.equal($el.attr('data-pl-name'), 'newName'); + assert.isTrue($control.prop('disabled')); + assert.isTrue($el.hasClass('hidden')); + assert.isTrue($el.hasClass('pl-horizontal-Left')); + }); + + + describe('Multiline TextBox', function () { + it('textarea html input', function () { + // Given + var element = builder.buildType('TextBox', { + Multiline: true, + Enabled: false + }); + + // When + var $el = element.render(), + $input = $el.find('.pl-text-area-input'); + + // Then + assert.equal($input.length, 1, 'textarea control'); + assert.equal($input.prop('disabled'), true); + }); + + it('Setting LineCount', function () { + // Given + var element = builder.buildType('TextBox', { + Multiline: true, + LineCount: 4 + }); + + // When + var $el = element.render(), + $input = $el.find('.pl-text-area-input'); + + // Then + assert.equal($input.prop('rows'), 4, 'row count'); + }); + + it('Setting LabelText', function () { + // Given + var element = builder.buildType('TextBox', { + Multiline: true, + LabelText: "MyLabel" + }); + + // When + var $el = element.render(), + $label = $el.find('.pl-control-label'); + + // Then + assert.equal($label.length, 1, 'render Label'); + assert.equal($label.text(), 'MyLabel', 'setting label'); + }); + + it('Setting DisplayFormat', function () { + // Given + var element = builder.buildType('TextBox', { + Multiline: true, + LineCount: 4, + + DisplayFormat: "{title}" + }); + + // When + element.setValue({title: "Value"}); + var $el = element.render(), + $input = $el.find('.pl-text-area-input'); + + // Then + assert.equal($input.val(), 'Value'); + }); + + it('Setting HintText, ErrorText, WarningText', function () { + // Given + var element = builder.buildType('TextBox', { + Multiline: true, + LineCount: 4, + HintText: 'Default hint', + ErrorText: 'Default error', + WarningText: 'Default warning' + }); + + var $el = element.render(), + $hint = $el.find('.pl-control-hint-text'), + $error = $el.find('.pl-control-error-text'), + $warning = $el.find('.pl-control-warning-text'); + + assert.equal($hint.text(), 'Default hint'); + assert.equal($error.text(), 'Default error'); + assert.equal($warning.text(), 'Default warning'); + + // When + element.setHintText('Hint'); + element.setErrorText('Error'); + element.setWarningText('Warning'); + + // Then + assert.equal($hint.text(), 'Hint'); + assert.equal($error.text(), 'Error'); + assert.equal($warning.text(), 'Warning'); + }); + + }); + + describe('Not multiline TextBox', function () { + it('html input', function () { + // Given + var element = builder.buildType('TextBox', { + Multiline: false, + Enabled: false + }); + + // When + var $el = element.render(), + $input = $el.find('input.pl-text-box-input'); + + // Then + assert.equal($input.length, 1, 'input control'); + assert.equal($input.prop('disabled'), true); + }); + + it('Setting LabelText', function () { + // Given + var element = builder.buildType('TextBox', { + Multiline: false, + LabelText: "MyLabel" + }); + + // When + var $el = element.render(), + $label = $el.find('.pl-control-label'); + + // Then + assert.equal($label.length, 1, 'render Label'); + assert.equal($label.text(), 'MyLabel', 'setting label'); + }); + + it('Setting DisplayFormat', function () { + // Given + var element = builder.buildType('TextBox', { + Multiline: false, + DisplayFormat: "{title}" + }); + + // When + element.setValue({title: "Value"}); + var $el = element.render(), + $input = $el.find('input.pl-text-box-input'); + + // Then + assert.equal($input.val(), 'Value'); + }); + + it('Setting HintText, ErrorText, WarningText', function () { + // Given + var element = builder.buildType('TextBox', { + HintText: 'Default hint', + ErrorText: 'Default error', + WarningText: 'Default warning' + }); + + var $el = element.render(), + $hint = $el.find('.pl-control-hint-text'), + $error = $el.find('.pl-control-error-text'), + $warning = $el.find('.pl-control-warning-text'); + + assert.equal($hint.text(), 'Default hint'); + assert.equal($error.text(), 'Default error'); + assert.equal($warning.text(), 'Default warning'); + + // When + element.setHintText('Hint'); + element.setErrorText('Error'); + element.setWarningText('Warning'); + + // Then + assert.equal($hint.text(), 'Hint'); + assert.equal($error.text(), 'Error'); + assert.equal($warning.text(), 'Warning'); + }); + }); + + it('Setting element\'s property', function () { + // Given + var element = builder.buildType('TextBox', { + Name: 'TextBox1', + Enabled: false, + Visible: false, + HorizontalAlignment: 'Stretch', + VerticalAlignment: 'Bottom' + }); + + // When + var $el = element.render(); + + //Then + assert.equal($el.attr('data-pl-name'), 'TextBox1', 'Name'); + assert.isTrue($el.hasClass('pl-disabled'), 'Enabled'); + assert.isTrue($el.hasClass('hidden'), 'Visible'); + assert.isTrue($el.hasClass('pl-horizontal-Stretch'), 'HorizontalAlignment'); + assert.isTrue($el.hasClass('verticalAlignmentBottom'), 'VerticalAlignment'); + }); + + }) +}); + +describe('TextEditorBase (Control)', function () { + describe('Textbox as exemplar of TextEditorBase', function () { + var metadata_1 = { + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "2.2222" }, + { "Id": 2, "Display": "3.2222" }, + { "Id": 3, "Display": "4.2222" } + ] + } + } + ], + Items: [{ + + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "$.Display" + }, + "DisplayFormat": { + "NumberFormat": { + "Format": "n2" + } + }, + "EditMask": { + "NumberEditMask": { + "Mask": "n3" + } + } + } + }] + }; + + it('metadata', function () { + // Given + var metadata = metadata_1; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + + var $input = $layout.find('.pl-text-box-input'); + + assert.equal($input.val(), '2,22', 'binding and formatting is right'); + + $input.focus(); // тест иногда не срабатывает, потому что фокус находится вне окна => .focus() выполниться не может + assert.equal($input.val(), '2,222', 'mask is right'); + + $layout.detach(); + } + }); + + }); + +}); +describe('ToolBarControl', function () { + describe('render', function () { + var builder = new InfinniUI.ApplicationBuilder() + , toolbar; + + beforeEach(function () { + toolbar = builder.buildType('ToolBar', { + Items: [ + { + Button: { + Text: 'Button 1' + } + }, + { + Label: { + Text: 'Button 2' + } + } + ] + }); + }); + + it('should render button with correct class', function () { + //Given + + + //When + var $el = toolbar.render(); + + //Then + assert.isTrue($el.hasClass('pl-tool-bar')); + }); + }); +}); + +describe('TreeView', function () { + + describe('render', function () { + it('should apply value to control (single selecting mode)', function () { + // Given + var metadata = { + "DataSources": [ + { + "ObjectDataSource": { + "Name": "Geo", + "Items": [ + { + "Id": 1, + "ParentId": null, + "Name": "Челябинск" + }, + { + "Id": 2, + "ParentId": 1, + "Name": "Чичерина" + }, + { + "Id": 3, + "ParentId": 1, + "Name": "Комарова" + }, + { + "Id": 4, + "ParentId": null, + "Name": "Копейск" + }, + { + "Id": 5, + "ParentId": 4, + "Name": "Победы" + }, + { + "Id": 6, + "ParentId": 5, + "Name": "33/1" + } + ] + } + } + ], + "Items": [ + { + "TreeView": { + "KeyProperty": "Id", + "ParentProperty": "ParentId", + "ItemProperty": "Name", + "ValueProperty": "Name", + "MultiSelect": true, + "Items": { + "Source": "Geo" + } + } + } + ] + }; + + + // When + testHelper.applyViewMetadata(metadata, function (view, $view) { + + var $treeView = $view.find('.pl-treeview'); + var $treeViewNodes = $treeView.find('.pl-treeview-node'); + + //Then + assert.equal($treeView.length, 1, 'TreeView rendered in View'); + assert.equal($treeViewNodes.length, 6, 'TreeViewNodes rendered'); + + view.close(); + }); + + }); + }); + + describe('api', function () { + it('should update DisabledItemCondition', function () { + // Given + var metadata = { + "DataSources": [ + { + "ObjectDataSource": { + "Name": "Geo", + "Items": [ + { + "Id": 1, + "ParentId": null, + "Name": "Челябинск" + }, + { + "Id": 2, + "ParentId": 1, + "Name": "Чичерина" + }, + { + "Id": 3, + "ParentId": 1, + "Name": "Комарова" + }, + { + "Id": 4, + "ParentId": null, + "Name": "Копейск" + }, + { + "Id": 5, + "ParentId": 4, + "Name": "Победы" + }, + { + "Id": 6, + "ParentId": 5, + "Name": "33/1" + } + ] + } + } + ], + "Items": [ + { + "TreeView": { + "Name": "TreeView1", + "DisabledItemCondition": "{ return (args.value.Id == 3); }", + "KeyProperty": "Id", + "ParentProperty": "ParentId", + "ItemProperty": "Name", + "ValueProperty": "Name", + "MultiSelect": true, + "Items": { + "Source": "Geo" + } + } + } + ] + }; + + + // When + testHelper.applyViewMetadata(metadata, function (view, $view) { + + var treeView = view.context.controls['TreeView1']; + var nodes = $view.find('.pl-treeview-node'); + + assert.isFalse(nodes.eq(1).hasClass('pl-disabled-list-item'), 'bad render for enabled item'); + assert.isTrue(nodes.eq(2).hasClass('pl-disabled-list-item'), 'bad render for disabled item'); + + // When + treeView.setDisabledItemCondition( function (context, args) { + return args.value.Id == 2; + }); + + // Then + assert.isTrue(nodes.eq(1).hasClass('pl-disabled-list-item'), 'items not updated'); + assert.isFalse(nodes.eq(2).hasClass('pl-disabled-list-item'), 'items not updated'); + + view.close(); + }); + + }); + }); + +}); +describe('DataBinding', function () { + it('should bind source', function () { + // Given + var dataBinding = new InfinniUI.DataBinding(); + + assert.isNull(dataBinding.getSource()); + assert.isNull(dataBinding.getSourceProperty()); + + // When + dataBinding.bindSource(new FakeElement(), 'property'); + + // Then + assert.isNotNull(dataBinding.getSource()); + assert.isNotNull(dataBinding.getSourceProperty()); + }); + + it('should bind element', function () { + // Given + var dataBinding = new InfinniUI.DataBinding(); + + assert.isNull(dataBinding.getElement()); + assert.isNull(dataBinding.getElementProperty()); + + // When + dataBinding.bindElement(new FakeElement(), 'property'); + + // Then + assert.isNotNull(dataBinding.getElement()); + assert.isNotNull(dataBinding.getElementProperty()); + }); + + it('default mode should be twoWay', function () { + // Given + var dataBinding = new InfinniUI.DataBinding(); + + // Then + assert.equal(dataBinding.getMode(), InfinniUI.BindingModes.twoWay, 'default mode must be twoWay'); + }); + + it('should refresh source on element change if mode is twoWay', function () { + // Given + var dataBinding = new InfinniUI.DataBinding(); + dataBinding.setMode(InfinniUI.BindingModes.twoWay); + + var source = new FakeElement(); + var sourceProperty = 'sourceProperty'; + source.setProperty(sourceProperty, 'source property start value'); + + var element = new FakeElement(); + var elementProperty = 'elementProperty'; + element.setProperty(elementProperty, 'element property start value'); + + dataBinding.bindSource(source, sourceProperty); + dataBinding.bindElement(element, elementProperty); + + // When + element.setProperty(elementProperty, 'element property new value' ); + + // Then + assert.equal(dataBinding.getSource().getProperty(sourceProperty), 'element property new value'); + }); + + it('should refresh element on source change if mode is twoWay', function () { + // Given + var dataBinding = new InfinniUI.DataBinding(); + dataBinding.setMode(InfinniUI.BindingModes.twoWay); + + var source = new FakeElement(); + var sourceProperty = 'sourceProperty'; + source.setProperty(sourceProperty, 'source property start value'); + + var element = new FakeElement(); + var elementProperty = 'elementProperty'; + element.setProperty(elementProperty, 'element property start value'); + + dataBinding.bindSource(source, sourceProperty); + dataBinding.bindElement(element, elementProperty); + + // When + source.setProperty(sourceProperty, 'source property new value' ); + + // Then + assert.equal(dataBinding.getElement().getProperty(elementProperty), 'source property new value'); + }); + + it('should not refresh source on element change if mode is toElement', function () { + // Given + var dataBinding = new InfinniUI.DataBinding(); + dataBinding.setMode(InfinniUI.BindingModes.toElement); + + var source = new FakeElement(); + var sourceProperty = 'sourceProperty'; + source.setProperty(sourceProperty, 'source property start value'); + + var element = new FakeElement(); + var elementProperty = 'elementProperty'; + element.setProperty(elementProperty, 'element property start value'); + + dataBinding.bindSource(source, sourceProperty); + dataBinding.bindElement(element, elementProperty); + + // When + element.setProperty(elementProperty, 'element property new value' ); + + // Then + assert.equal(dataBinding.getSource().getProperty(sourceProperty), 'source property start value'); + }); + + it('should refresh element on source change if mode is toElement', function () { + // Given + var dataBinding = new InfinniUI.DataBinding(); + dataBinding.setMode(InfinniUI.BindingModes.toElement); + + var source = new FakeElement(); + var sourceProperty = 'sourceProperty'; + source.setProperty(sourceProperty, 'source property start value'); + + var element = new FakeElement(); + var elementProperty = 'elementProperty'; + element.setProperty(elementProperty, 'element property start value'); + + dataBinding.bindSource(source, sourceProperty); + dataBinding.bindElement(element, elementProperty); + + // When + source.setProperty(sourceProperty, 'source property new value' ); + + // Then + assert.equal(dataBinding.getElement().getProperty(elementProperty), 'source property new value'); + }); + + it('should refresh source on element change if mode is toSource', function () { + // Given + var dataBinding = new InfinniUI.DataBinding(); + dataBinding.setMode(InfinniUI.BindingModes.toSource); + + var source = new FakeElement(); + var sourceProperty = 'sourceProperty'; + source.setProperty(sourceProperty, 'source property start value'); + + var element = new FakeElement(); + var elementProperty = 'elementProperty'; + element.setProperty(elementProperty, 'element property start value'); + + dataBinding.bindSource(source, sourceProperty); + dataBinding.bindElement(element, elementProperty); + + // When + element.setProperty(elementProperty, 'element property new value' ); + + // Then + assert.equal(dataBinding.getSource().getProperty(sourceProperty), 'element property new value'); + }); + + it('should not refresh element on source change if mode is toSource', function () { + // Given + var dataBinding = new InfinniUI.DataBinding(); + dataBinding.setMode(InfinniUI.BindingModes.toSource); + + var source = new FakeElement(); + var sourceProperty = 'sourceProperty'; + source.setProperty(sourceProperty, 'source property start value'); + + var element = new FakeElement(); + var elementProperty = 'elementProperty'; + element.setProperty(elementProperty, 'element property start value'); + + dataBinding.bindSource(source, sourceProperty); + dataBinding.bindElement(element, elementProperty); + + // When + source.setProperty(sourceProperty, 'source property new value' ); + + // Then + assert.equal(dataBinding.getElement().getProperty(elementProperty), 'element property start value'); + }); + + it('should not refresh element if mode is wrong', function () { + // Given + var dataBinding = new InfinniUI.DataBinding(); + dataBinding.setMode('gubbish'); + + var source = new FakeElement(); + var sourceProperty = 'sourceProperty'; + source.setProperty(sourceProperty, 'source property start value'); + + var element = new FakeElement(); + var elementProperty = 'elementProperty'; + element.setProperty(elementProperty, 'element property start value'); + + dataBinding.bindSource(source, sourceProperty); + dataBinding.bindElement(element, elementProperty); + + // When + source.setProperty(sourceProperty, 'source property new value' ); + + // Then + assert.equal(dataBinding.getElement().getProperty(elementProperty), 'element property start value'); + }); + + it('should not refresh source if mode is wrong', function () { + // Given + var dataBinding = new InfinniUI.DataBinding(); + dataBinding.setMode('gubbish'); + + var source = new FakeElement(); + var sourceProperty = 'sourceProperty'; + source.setProperty(sourceProperty, 'source property start value'); + + var element = new FakeElement(); + var elementProperty = 'elementProperty'; + element.setProperty(elementProperty, 'element property start value'); + + dataBinding.bindSource(source, sourceProperty); + dataBinding.bindElement(element, elementProperty); + + // When + element.setProperty(elementProperty, 'element property new value' ); + + // Then + assert.equal(dataBinding.getSource().getProperty(sourceProperty), 'source property start value'); + }); + + it('should convert value if have converter', function () { + // Given + var dataBinding = new InfinniUI.DataBinding(); + dataBinding.setMode(InfinniUI.BindingModes.twoWay); + dataBinding.setConverter({ + toSource: function(context, argument) { + return argument.value ? 5 : 3; // string to integer + }, + toElement: function(context, argument) { + return argument.value > 4; // integer to string + } + }); + + var source = new FakeElement(); + var sourceProperty = 'sourceProperty'; + + var element = new FakeElement(); + var elementProperty = 'elementProperty'; + + dataBinding.bindSource(source, sourceProperty); + dataBinding.bindElement(element, elementProperty); + + // When + source.setProperty(sourceProperty, 5); + + // Then + assert.equal(dataBinding.getElement().getProperty(elementProperty), true, 'Ignored toElement converter'); + + // When + element.setProperty(elementProperty, false); + + // Then + assert.equal(dataBinding.getSource().getProperty(sourceProperty), 3, 'Ignored toSource converter'); + }); +}); + +describe('DataBindingBuilder', function () { + +/* it('should build DataBinding', function () { + // Given + var dataBindingBuilder = new InfinniUI.DataBindingBuilder(); + var view = { + getContext: function(){ + return { + dataSources: { + My_Source: { + onPropertyChanged: function(){} + } + }, + parameters: { + }, + controls: { + } + }; + }, + + getDeferredOfMember: function(){ + return { + done: function(handler){ + handler({}); + } + }; + } + }; + var metadata = { + Source: 'My_Source', + Property: '', + Mode: 'ToSource', + Converter: { + toSource: function(){}, + toElement: function(){} + } + }; + + // When + var dataBinding = dataBindingBuilder.build(null, {parentView: view, metadata: metadata}); + + // Then + assert.equal(dataBinding.getMode(), InfinniUI.BindingModes.toSource); + assert.isNotNull(dataBinding.getConverter()); + assert.isNotNull(dataBinding.getSource()); + assert.isNotNull(dataBinding.getSourceProperty()); + }); + + it('should bind all type of source', function () { + // Given + var dataBindingBuilder = new InfinniUI.DataBindingBuilder(); + var view = { + getContext: function(){ + return { + dataSources: { + My_DataSource: { + onPropertyChanged: function(){} + } + }, + parameters: { + My_Parameter: { + onPropertyChanged: function(){} + } + }, + controls: { + My_Button: { + onPropertyChanged: function(){} + } + } + }; + } + }; + + // Then + dataBindingBuilder.build(null, { parentView: view, metadata: { Source: 'My_DataSource'} }); + dataBindingBuilder.build(null, { parentView: view, metadata: { Source: 'My_Parameter'} }); + dataBindingBuilder.build(null, { parentView: view, metadata: { Source: 'My_Button'} }); + }); +*/ + it('should toElement converter work in inline style', function () { + // Given + var metadata = { + Text: '��������', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "LTE" }, + { "Id": 2, "Display": "3G" }, + { "Id": 3, "Display": "2G" } + ] + } + } + ], + Items: [{ + + StackPanel: { + Name: 'MainViewPanel', + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display", + "Converter": { + "ToElement": "{return args.value + '!';}" + }, + "Mode": "ToElement" + } + } + }, + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + } + } + }] + }; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + assert.equal($layout.find('.pl-text-box-input:first').val(), 'LTE!', 'binding in itemTemplate is right'); + } + }); +}); + +var FakeElement = Backbone.Model.extend({ + onPropertyChanged: function(prop, callback){ + this.set('callback', callback); + }, + + setName: function(name){ + this.set('name', name); + }, + + getName: function(){ + return this.get('name'); + }, + + setProperty: function(property, newValue){ + var oldValue = this.get(property); + + if(oldValue != newValue){ + this.set(property, newValue); + var callback = this.get('callback'); + if(callback){ + callback({}, {property: property, newValue: newValue}); + } + } + }, + + getProperty: function(property){ + return this.get(property); + } +}); +describe('baseDataSource', function () { + + it('should check ErrorValidator before save', function (done) { + // Given + var dataSource = new InfinniUI.ObjectDataSource( {view: fakeView()} ); + + dataSource.setErrorValidator(function(context, args) { + done(); + return { + IsValid: true + }; + }); + + dataSource.createItem(function(context, args){ + //When + var item = args.value; + + dataSource.saveItem(item) + }); + }); +}); + +describe('baseDataSourceBuilder', function () { + + it('should init CustomProperties', function () { + // Given + var builder = new InfinniUI.ApplicationBuilder(), + metadata = { + CustomProperties: { + pageNumber: 0, + pageSize: 10 + } + }; + + // When + var dataSource = builder.buildType('ObjectDataSource', metadata, {parentView: fakeView()}); + + // Then + assert.equal(dataSource.getProperty('.pageNumber'), 0); + assert.equal(dataSource.getProperty('.pageSize'), 10); + }); +}); + +describe('DataSourceBuilder', function () { + + var builder = new InfinniUI.ApplicationBuilder(); + var items = [ + { + "_id": '1', + "FirstName": "Иван", + "LastName": "Иванов" + }, + { + "_id": '2', + "FirstName": "Петр", + "LastName": "Петров" + }, + { + "_id": '3', + "FirstName": "Иван1", + "LastName": "Иванов1" + }, + { + "_id": '4', + "FirstName": "Петр2", + "LastName": "Петров2" + }, + { + "_id": '5', + "FirstName": "Иван3", + "LastName": "Иванов3" + }, + { + "_id": '6', + "FirstName": "Петр4", + "LastName": "Петров5" + }, + { + "_id": '10', + "FirstName": "Анна", + "LastName": "Сергеева" + + } + ]; + + FakeRestDataProvider.prototype.items = _.clone(items); + + window.InfinniUI.providerRegister.register('DocumentDataSource', FakeRestDataProvider); + + describe('build DocumentDataSource', function () { + it('should build documentDataSource', function () { + // Given When + var metadata = { + Name: 'PatientDataSource', + DocumentId: 'Patient', + FillCreatedItem: true, + PageNumber: 1, + PageSize: 5, + + onPropertyChanged: { + Name: 'onPropertyChanged' + } + }; + + var view = new InfinniUI.View(), + createdDataSource = builder.buildType('DocumentDataSource', metadata, {parentView: view}); + + // Then + assert.equal(createdDataSource.getDocumentId(), 'Patient'); + assert.equal(createdDataSource.getIdProperty(), '_id'); + assert.equal(createdDataSource.getPageSize(), 5, 'PageSize'); + assert.equal(createdDataSource.getPageNumber(), 1, 'PageNumber'); + assert.isTrue(createdDataSource.getFillCreatedItem(), 'Value of FillCreatedItem'); + }); + + it('should subscribe documentDataSource on changeProperty', function (done) { + // Given + var metadata = { + Name: 'PatientDataSource', + DocumentId: 'Patient', + FillCreatedItem: true, + PageNumber: 1, + PageSize: 5, + + OnPropertyChanged: { + Name: 'onPropertyChanged' + } + }; + + var view = new InfinniUI.View(), + createdDataSource = builder.buildType('DocumentDataSource', metadata, {parentView: view}), + scriptMetadata = { + Name:"onPropertyChanged", + Body: 'window.documentDataSourceTest = 1;' + }; + + view.getScripts().add({ + name: 'onPropertyChanged', + func: builder.buildType('Script', scriptMetadata, {parentView: view}) + }); + + createdDataSource.updateItems(onItemUpdates); + + // When + function onItemUpdates(context, args){ + createdDataSource.setProperty('FirstName', 'Иванидзе'); + } + + // Then + setTimeout(function(){ + assert.equal(window.documentDataSourceTest, 1, 'Event OnSelectedItemChanged is called'); + done(); + }, 200); + }); + + it('should create ds from metadata', function (done) { + // Given + window.InfinniUI.providerRegister.register('DocumentDataSource', FakeRestDataProvider); + + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + DocumentDataSource: { + "Name": "DataSource1", + "DocumentId": "Whatever" + } + } + ], + Items: [] + }; + + var dataSource; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + dataSource = view.getContext().dataSources['DataSource1']; + dataSource.updateItems(handleItemsReady); + } + + function handleItemsReady(){ + assert.isTrue(dataSource.getItems().length > 0, 'DS was update items'); + assert.equal(FakeRestDataProvider.prototype.lastSendedUrl, InfinniUI.config.serverUrl + '/documents/Whatever?skip=0&take=15', 'requested url is right'); + + done(); + } + }); + + it('should update items on filter changing', function (done) { + // Given + window.InfinniUI.providerRegister.register('DocumentDataSource', FakeRestDataProvider); + + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + DocumentDataSource: { + "Name": "DataSource1", + "DocumentId": "Whatever" + } + } + ], + Items: [] + }; + var result = ''; + + var dataSource; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + + $layout.detach(); + + dataSource = view.getContext().dataSources['DataSource1']; + + dataSource.onItemsUpdated(function(){ + result += '1'; + + if(result == '11'){ + assert.equal(FakeRestDataProvider.prototype.lastSendedUrl, InfinniUI.config.serverUrl + '/documents/Whatever?filter=eq(id,7)&skip=0&take=15', 'requested url is right (second)'); + done(); + } + }); + + dataSource.setFilter('eq(id,4)'); + + dataSource.updateItems(handleItemsReady1); + } + + function handleItemsReady1(){ + assert.equal(result, '', 'its first updated of item'); + assert.equal(FakeRestDataProvider.prototype.lastSendedUrl, InfinniUI.config.serverUrl + '/documents/Whatever?filter=eq(id,4)&skip=0&take=15', 'requested url is right (first)'); + + dataSource.setFilter('eq(id,<%uid%>)'); + dataSource.setFilterParams('uid', 7); + } + }); + + + it('should bind filter', function (done) { + // Given + FakeRestDataProvider.prototype.items = _.clone(items); + window.InfinniUI.providerRegister.register('DocumentDataSource', FakeRestDataProvider); + + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + DocumentDataSource: { + "Name": "DataSource1", + "DocumentId": "Whatever", + "Filter": "eq(_id,<%param%>)", + "FilterParams": { + "param": { + "Source": "DataSource2", + "Property": "0._id" + } + } + } + },{ + + DocumentDataSource: { + "Name": "DataSource2", + "DocumentId": "Whatever" + } + } + ], + Items: [] + }; + var result = ''; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + + $layout.detach(); + + var dataSource1 = view.getContext().dataSources['DataSource1']; + var dataSource2 = view.getContext().dataSources['DataSource2']; + + dataSource1.onItemsUpdated(function(){ + assert.equal(result, '2', 'second updated ds1'); + + result += '1'; + dataSource2; + assert.equal(FakeRestDataProvider.prototype.lastSendedUrl, InfinniUI.config.serverUrl + '/documents/Whatever?filter=eq(_id,1)&skip=0&take=15', 'requested url is right (ds1)'); + done(); + }); + + dataSource2.onItemsUpdated(function(){ + + assert.equal(result, '', 'first updated ds2'); + + result += '2'; + + dataSource1.updateItems(); + }); + + } + + }); + + }); + +}); + +describe('DocumentDataSource', function () { + window.InfinniUI.providerRegister.register('DocumentDataSource', FakeRestDataProvider); + + var dataItems = [ + { + "_id": '1', + "FirstName": "Иван", + "LastName": "Иванов" + }, + { + "_id": '2', + "FirstName": "Петр", + "LastName": "Петров" + }, + { + "_id": '3', + "FirstName": "Иван1", + "LastName": "Иванов1" + }, + { + "_id": '4', + "FirstName": "Петр2", + "LastName": "Петров2" + }, + { + "_id": '5', + "FirstName": "Иван3", + "LastName": "Иванов3" + }, + { + "_id": '6', + "FirstName": "Петр4", + "LastName": "Петров5" + }, + { + "_id": '10', + "FirstName": "Анна", + "LastName": "Сергеева" + + } + ]; + + describe('DocumentDataSource base api', function () { + it('should get list of data', function (done) { + // Given + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var dataSource = new InfinniUI.DocumentDataSource({ + view: fakeView() + }); + + assert.isFalse(dataSource.isDataReady(), 'dataReady status is right (false)'); + assert.isFalse(dataSource.get('isRequestInProcess'), 'is request not in process'); + + //When + dataSource.updateItems( + function(context, args){ + + // Then + assert.isTrue(args.value.length > 0, 'data provider returns items'); + assert.isTrue(dataSource.getItems().length > 0, 'data source have items'); + assert.isTrue(dataSource.isDataReady(), 'dataReady status is right (true)'); + done(); + + } + ); + }); + + it('should suspend DocumentDataSource from metadata', function (done) { + + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + // Given + var builder = new InfinniUI.ApplicationBuilder(); + var metadata = { + "SuspendUpdate": 'testSuspend' + }; + + // When + var documentDataSource = builder.buildType('DocumentDataSource', metadata, {parentView: fakeView()}); + + documentDataSource.updateItems(); + + // Then + setTimeout( function() { + assert.equal(documentDataSource.isDataReady(), false); + done(); + }, 10 ); + }); + + it('should resume DocumentDataSource from metadata suspend', function (done) { + + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + // Given + var builder = new InfinniUI.ApplicationBuilder(); + var metadata = { + "SuspendUpdate": 'testSuspend' + }; + + // When + var documentDataSource = builder.buildType('DocumentDataSource', metadata, {parentView: fakeView()}); + documentDataSource.updateItems(); + + // Then + documentDataSource.resumeUpdate( 'testSuspend' ); + + setTimeout( function() { + assert.equal(documentDataSource.isDataReady(), true); + done(); + }, 10 ); + }); + + it('should subscribe to property of selectedItem', function (done) { + // Given + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var result = ''; + + var dataSource = new InfinniUI.DocumentDataSource({ + view: fakeView() + }); + + dataSource.onPropertyChanged('$.FirstName', function(context, args){ + result += ', ' + args.newValue; + }); + + dataSource.updateItems( + function(context, args){ + + //When + dataSource.setProperty('$.FirstName', 'Иванов 2'); + dataSource.setProperty('0.FirstName', 'Иванов 3'); + dataSource.setProperty('3.FirstName', 'Иванов 4'); + dataSource.setSelectedItem(dataSource.getItems()[1]); + dataSource.setProperty('0.FirstName', 'Иванов 5'); + dataSource.setProperty('1.FirstName', 'Иванов 6'); + + // Then + assert.equal(result, ', Иван, Иванов 2, Иванов 3, Иванов 6', 'onPropertyChanged called in right order'); + done(); + + } + ); + }); + +/* TODO раскомментировать после фильтрации фейковых провайдеров + it('should get editing record', function (done) { + // Given + window.providerRegister.register('DocumentDataSource', FakeRestDataProvider); + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var builder = new InfinniUI.ApplicationBuilder(); + var view = fakeView(); + var dataSource = builder.buildType('DocumentDataSource', {}, {parent: view, parentView: view, builder: builder}); + + //When + dataSource.suspendUpdate(); + dataSource.setIdFilter('1'); + dataSource.resumeUpdate(); + + + + var items = dataSource.updateItems( + function (context, args) { + + // Then + assert.lengthOf(args.value, 1, 'length of filtered items set'); + assert.equal(args.value[0].Id, '1', 'value of filtered items set'); + + done(); + } + ); + }); + + + it('should update document', function (done) { + // Given + window.providerRegister.register('DocumentDataSource', FakeRestDataProvider); + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var dataSource = new InfinniUI.DocumentDataSource({ + view: fakeView() + }); + + dataSource.suspendUpdate(); + dataSource.setPageSize(5); + dataSource.resumeUpdate(); + + //When + dataSource.updateItems( + function(context, args){ + + assert.lengthOf(dataSource.getItems(), 5, 'data provider returns 5 items'); + + dataSource.suspendUpdate(); + dataSource.setPageNumber(1); + dataSource.resumeUpdate(); + dataSource.updateItems( + function(data){ + + // Then + assert.lengthOf(dataSource.getItems(), 2, 'data provider returns 2 items'); + done(); + + } + ); + + } + ); + });*/ + + it('should restore selected item after updating', function (done) { + // Given + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var dataSource = new InfinniUI.DocumentDataSource({ + view: fakeView() + }); + + dataSource.updateItems( + function(){ + var items = dataSource.getItems(); + var selectedItem = items[3]; + dataSource.setSelectedItem(selectedItem); + + //When + dataSource.updateItems( + function(context, args){ + //Then + assert.equal(dataSource.getSelectedItem(), selectedItem); + done(); + } + ); + } + ); + }); + + it('should create document', function (done) { + // Given + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var dataSource = new InfinniUI.DocumentDataSource({ + view: fakeView() + }); + + //When + dataSource.createItem( + function(context, argument){ + + // Then + var newItem = argument.value; + assert.ok(newItem, 'new item is ready'); + + var items = dataSource.getItems(); + assert.lengthOf(items, 1, 'one element (when was created) in items'); + //assert.equal(items[0].prefilledField, 1, 'is right element in items after creating'); + done(); + } + ); + }); + + it('should get document property', function (done) { + // Given + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var dataSource = new InfinniUI.DocumentDataSource({ + view: fakeView() + }); + + //When + dataSource.updateItems(handleItemsReady); + + function handleItemsReady(){ + // Then + assert.equal(dataSource.getProperty('FirstName'), 'Иван', 'return property value by simple property'); + assert.equal(dataSource.getProperty('$.FirstName'), 'Иван', 'return property value by relative property'); + assert.equal(dataSource.getProperty('$').FirstName, 'Иван', 'return property - full item by $ selector'); + assert.equal(dataSource.getProperty('2.FirstName'), 'Иван1', 'return property - full item by index selector'); + done(); + } + }); + + it('should select item', function (done) { + // Given + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var dataSource = new InfinniUI.DocumentDataSource({ + view: fakeView() + }); + + dataSource.updateItems(handleItemsReady); + + function handleItemsReady(){ + var items = dataSource.getItems(); + assert.equal(dataSource.getProperty('FirstName'), 'Иван', 'return property value by simple property'); + + //When + dataSource.setSelectedItem(items[1]); + + // Then + assert.equal(dataSource.getProperty('FirstName'), 'Петр', 'return property value by simple property after change selected item'); + done(); + } + }); + + it('should change document property', function (done) { + // Given + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var dataSource = new InfinniUI.DocumentDataSource({ + view: fakeView() + }); + + + dataSource.updateItems(handleItemsReady); + + + function handleItemsReady(){ + assert.equal(dataSource.getProperty('FirstName'),'Иван', 'return property value by property'); + + //When + dataSource.setProperty('FirstName', 'Иванидзе'); + dataSource.setProperty('2.FirstName', 'Иванидзе-дзе'); + + // Then + assert.equal(dataSource.getProperty('$').FirstName, 'Иванидзе', 'return property value by property after change property'); + assert.equal(dataSource.getProperty('2').FirstName, 'Иванидзе-дзе', 'return property value by property after change property by id'); + done(); + } + }); + + it('should change document property (full item change)', function (done) { + // Given + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var dataSource = new InfinniUI.DocumentDataSource({ + view: fakeView() + }); + + dataSource.updateItems(handleItemsReady); + + function handleItemsReady(){ + assert.equal(dataSource.getProperty('FirstName'), 'Иван', 'return property value by property'); + + //When + var newItemData = { + "_id": '1', + "FirstName": "Ивано", + "LastName": "Иванович" + }; + dataSource.setProperty('$', newItemData); + + // Then + assert.equal(dataSource.getProperty('$').FirstName, 'Ивано', 'return property value by property after change property'); + done(); + } + }); + + it('should validate item', function (done) { + // Given + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var dataSource = new InfinniUI.DocumentDataSource({ + view: fakeView() + }); + + dataSource.setErrorValidator(validator); + dataSource.updateItems(handleItemsReady); + + function handleItemsReady(){ + + //When + var items = dataSource.getItems(), + validateResult1 = dataSource.getValidationResult(items[0]), + validateResult2 = dataSource.getValidationResult(items[1]), + validateResult3 = dataSource.getValidationResult(); + + // Then + assert.isTrue(validateResult1.IsValid, 'successfully validation'); + + assert.isFalse(validateResult2.IsValid, 'fail validation'); + assert.lengthOf(validateResult2.Items, 1, 'fail validation results'); + assert.equal(validateResult2.Items[0].property, 'FirstName', 'fail validation property result'); + + assert.isFalse(validateResult3.IsValid, 'full validation'); + assert.lengthOf(validateResult3.Items, 6, 'full validation results'); + assert.equal(validateResult3.Items[3].property, '4.FirstName', 'full validation property result'); + done(); + } + + function validator(context, argument){ + var result = { + IsValid: true + }; + + if(argument.FirstName != 'Иван'){ + result.IsValid = false; + result.Items = [{ + property: 'FirstName', + message: 'Почему не Иван?!' + }]; + } + + return result; + } + }); + + it('should save item', function (done) { + // Given + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var dataSource = new InfinniUI.DocumentDataSource({ + view: fakeView() + }); + + dataSource.updateItems(handleItemsReady1); + + function handleItemsReady1(){ + + //When + var item = dataSource.getSelectedItem(); + + dataSource.setProperty('FirstName', 'Иванидзе'); + dataSource.saveItem(item); + + dataSource.updateItems(handleItemsReady2); + } + + function handleItemsReady2(){ + // Then + assert.equal(dataSource.getProperty('FirstName'), 'Иванидзе', 'item is saved'); + done(); + } + }); + + it('should delete item', function (done) { + // Given + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var dataSource = new InfinniUI.DocumentDataSource({ + view: fakeView() + }); + + dataSource.updateItems(handleItemsReady1); + + function handleItemsReady1(){ + + //When + var items = dataSource.getItems(), + itemsCount = items.length; + + dataSource.deleteItem(items[0], function(context, argument){ + // Then + items = dataSource.getItems(); + assert.lengthOf(items, itemsCount-1, 'items length is decrease'); + assert.equal(dataSource.getSelectedItem(), null, 'deleted item exclude from selected item'); + done(); + }); + } + }); + + /* TODO раскомментировать после фильтрации фейковых провайдеров + it('should add items', function (done) { + + // Given + window.providerRegister.register('DocumentDataSource', FakeRestDataProvider); + FakeRestDataProvider.prototype.items = JSON.parse(JSON.stringify(dataItems)); + + var dataSource = new InfinniUI.DocumentDataSource({ + view: fakeView() + }); + + dataSource.suspendUpdate(); + dataSource.setPageSize(5); + dataSource.resumeUpdate(); + + + dataSource.updateItems( + function(context, args){ + + assert.lengthOf(dataSource.getItems(), 5, 'datasource have 5 items'); + assert.equal(dataSource.getPageNumber(), 0, 'datasource at first page'); + + //When + dataSource.addNextItems( + function(data){ + + // Then + assert.lengthOf(dataSource.getItems(), 7, 'after adding datasource have 7 items'); + assert.equal(dataSource.getPageSize(), 5, 'after adding datasource still have page size equal 5'); + assert.equal(dataSource.getPageNumber(), 1, 'after adding datasource at second page'); + done(); + + } + ); + + } + ); + });*/ + }); +}); + +describe('TreeModel', function () { + + describe('TreeModel', function () { + it('Simple handling', function () { + // Given + var treeModel = new InfinniUI.TreeModel('context'); + var result = ''; + + treeModel.onPropertyChanged('p1', function(context, args){ + result = result + '1'; + + assert.equal(context, 'context', 'passed context argument is right'); + assert.isNull(args.oldValue, 'old value is right'); + assert.equal(args.newValue, 1, 'new value is right'); + + assert.equal(treeModel.getProperty('p1'), 1, 'value was saved before handling'); + }); + + //When + treeModel.setProperty('p1', 1); + + // Then + assert.equal(result, '1', 'Handler was triggered'); + assert.equal(treeModel.getProperty('p1'), 1, 'Value was right saved'); + }); + + + it('Handling many handlers', function () { + // Given + var treeModel = new InfinniUI.TreeModel('context'); + var result = ''; + + treeModel.onPropertyChanged('p1', function(context, args){ + result = result + '1'; + + assert.equal(context, 'context', 'passed context argument is right'); + assert.isNull(args.oldValue, 'old value is right'); + assert.equal(args.newValue, 1, 'new value is right'); + }); + + treeModel.onPropertyChanged('p2', function(context, args){ + result = result + '2'; + }); + + //When + treeModel.setProperty('p1', 1); + treeModel.setProperty('p2', 2); + treeModel.setProperty('p2', 3); + + // Then + assert.equal(result, '122', 'Handlers was triggered'); + + assert.equal(treeModel.getProperty('p1'), 1, 'Value p1 was right saved'); + assert.equal(treeModel.getProperty('p2'), 3, 'Value p2 was right saved'); + }); + + it('Handling deep sets', function () { + // Given + var treeModel = new InfinniUI.TreeModel('context'); + var result = ''; + var jsonOfVal; + + treeModel.onPropertyChanged('p1.p11', function(context, args){ + result = result + '1'; + + assert.isTrue(args.oldValue == undefined || args.oldValue == 1, 'old value is right'); + assert.isTrue(args.newValue == 1 || args.newValue == 4, 'new value is right'); + + assert.isTrue(treeModel.getProperty('p1.p11') == 1 || treeModel.getProperty('p1.p11') == 4, 'value was saved before handling'); + }); + + treeModel.onPropertyChanged('p1', function(context, args){ + result = result + '2'; + + assert.equal(context, 'context', 'passed context argument is right'); + + jsonOfVal = JSON.stringify(args.oldValue); + assert.equal(jsonOfVal, '{"p11":1}','old value is right'); + jsonOfVal = JSON.stringify(args.newValue); + assert.equal(jsonOfVal, '{"p11":4}', 'new value is right'); + + assert.equal(treeModel.getProperty('p1').p11, 4, 'value was saved before handling'); + }); + + //When + treeModel.setProperty('p1.p11', 1); + treeModel.setProperty('p2.p11', 3); + treeModel.setProperty('p2', 2); + treeModel.setProperty('p1', {p11: 4}); + + // Then + assert.equal(result, '121', 'Handler was triggered'); + assert.equal(treeModel.getProperty('p1').p11, 4, 'value was saved before handling'); + + jsonOfVal = JSON.stringify(treeModel.getProperty('')); + assert.equal(jsonOfVal, '{"p1":{"p11":4},"p2":2}', 'full data tree is right'); + }); + + it('Handling onChange, on all properties', function () { + // Given + var treeModel = new InfinniUI.TreeModel('context'); + var result = []; + var jsonOfVal; + + treeModel.onPropertyChanged(function(context, args){ + result.push(args.property); + }); + + + //When + treeModel.setProperty('p1.p11', 1); + treeModel.setProperty('p2.p11', 3); + treeModel.setProperty('p2', 2); + treeModel.setProperty('p1', {p11: 4}); + + // Then + assert.equal(result.join(','), 'p1.p11,p2.p11,p2,p1', 'Handler was right triggered'); + }); + + it('Handling onChange of subtree', function () { + // Given + var treeModel = new InfinniUI.TreeModel('context'); + var result = []; + var jsonOfVal; + + treeModel.onPropertyChanged('*', function(context, args){ + result.push(args.property); + }); + + treeModel.onPropertyChanged('p1.*', function(context, args){ + result.push(args.property); + }); + + + //When + treeModel.setProperty('p1.p11.p111', 1); + treeModel.setProperty('p2.p11', 3); + treeModel.setProperty('p2', 2); + treeModel.setProperty('p1', {p11: 4}); + + // Then + assert.equal(result.join(','), 'p1.p11.p111,p1.p11.p111,p2.p11,p2,p1,p1', 'Handler was right triggered'); + }); + + it('Auto unsubscribing if owner is checked as removed', function () { + // Given + var treeModel = new InfinniUI.TreeModel('context'); + var result = ''; + var jsonOfVal; + var owner1 = { + isRemoved: false + }, owner2 = { + isRemoved: false + }; + + treeModel.onPropertyChanged('p1.p11', function(context, args){ + result = result + '1'; + + assert.isTrue(args.oldValue == undefined || args.oldValue == 1 || args.oldValue == 2, 'old value is right'); + assert.isTrue(args.newValue == 1 || args.newValue == 4 || args.newValue == 2 || args.newValue == 8, 'new value is right'); + + }, {owner: owner1}); + + treeModel.onPropertyChanged('p1', function(context, args){ + + result = result + '2'; + + }, {owner: owner2}); + + //When + treeModel.setProperty('p1.p11', 1); + treeModel.setProperty('p2.p11', 3); + treeModel.setProperty('p2', 2); + treeModel.setProperty('p1', {p11: 4}); + + owner1.isRemoved = true; + + treeModel.setProperty('p1.p11', 2); + treeModel.setProperty('p2.p11', 6); + treeModel.setProperty('p1', {p11: 8}); + + // Then + assert.equal(result, '1212', 'Handler was triggered'); + assert.equal(treeModel.getProperty('p1').p11, 8, 'value was saved before handling'); + + jsonOfVal = JSON.stringify(treeModel.getProperty('')); + assert.equal(jsonOfVal, '{"p1":{"p11":8},"p2":{"p11":6}}', 'full data tree is right'); + }); + }) +}); + +describe('ObjectDataSource', function () { + var items = [ + { + "_id": '1', + "FirstName": "Иван", + "LastName": "Иванов" + }, + { + "_id": '2', + "FirstName": "Петр", + "LastName": "Петров" + }, + { + "_id": '3', + "FirstName": "Иван1", + "LastName": "Иванов1" + }, + { + "_id": '4', + "FirstName": "Петр2", + "LastName": "Петров2" + }, + { + "_id": '5', + "FirstName": "Иван3", + "LastName": "Иванов3" + }, + { + "_id": '6', + "FirstName": "Петр4", + "LastName": "Петров5" + }, + { + "_id": '10', + "FirstName": "Анна", + "LastName": "Сергеева" + + } + ]; + + window.InfinniUI.providerRegister.register('ObjectDataSource', InfinniUI.Providers.ObjectDataProvider); + + function createObjectDataSource(metadata){ + + metadata = metadata || {}; + + var builder = new InfinniUI.ApplicationBuilder(); + var view = fakeView(); + var dataSource = builder.buildType('ObjectDataSource', metadata, {parent: view, parentView: view, builder: builder}), + initItems = JSON.parse(JSON.stringify(items)); + + dataSource.setItems(initItems); + + return dataSource; + } + + describe('ObjectDataSource base api', function () { + it('should get list of data', function () { + // Given //When + var dataSource = createObjectDataSource(), + items = dataSource.getItems(); + + // Then + assert.isTrue(dataSource.isDataReady(), 'dataReady status is right'); + assert.isTrue(items.length > 0, 'data provider returns items'); + }); + + it('should create document', function (done) { + // Given + var dataSource = createObjectDataSource(); + + //When + dataSource.createItem( + function(context, argument){ + + // Then + var newItem = argument.value; + assert.ok(newItem, 'new item is ready'); + assert.ok(newItem._id, 'new item has _id'); + done(); + } + ); + }); + + it('should get document property', function (done) { + // Given + var dataSource = createObjectDataSource(); + + //When + dataSource.updateItems(handleItemsReady); + + function handleItemsReady(){ + // Then + assert.equal(dataSource.getProperty('FirstName'), 'Иван', 'return property value by simple property'); + assert.equal(dataSource.getProperty('$.FirstName'), 'Иван', 'return property value by relative property'); + assert.equal(dataSource.getProperty('$').FirstName, 'Иван', 'return property - full item by $ selector'); + done(); + } + }); + + it('should select item', function (done) { + // Given + var dataSource = createObjectDataSource(); + + dataSource.updateItems(handleItemsReady); + + function handleItemsReady(){ + var items = dataSource.getItems(); + assert.equal(dataSource.getProperty('FirstName'), 'Иван', 'return property value by simple property'); + + //When + dataSource.setSelectedItem(items[1]); + + // Then + assert.equal(dataSource.getProperty('FirstName'), 'Петр', 'return property value by simple property after change selected item'); + done(); + } + }); + + it('should change document property', function (done) { + // Given + var dataSource = createObjectDataSource(); + + dataSource.updateItems(handleItemsReady); + + function handleItemsReady(){ + assert.equal(dataSource.getProperty('FirstName'),'Иван', 'return property value by property'); + + //When + dataSource.setProperty('FirstName', 'Иванидзе'); + + // Then + assert.equal(dataSource.getProperty('$').FirstName, 'Иванидзе', 'return property value by property after change property'); + done(); + } + }); + + it('should change document property (full item change)', function (done) { + // Given + var dataSource = createObjectDataSource(); + + dataSource.updateItems(handleItemsReady); + + function handleItemsReady(){ + assert.equal(dataSource.getProperty('FirstName'), 'Иван', 'return property value by property'); + + //When + var newItemData = { + "_id": '1', + "FirstName": "Ивано", + "LastName": "Иванович" + }; + dataSource.setProperty('$', newItemData); + + // Then + assert.equal(dataSource.getProperty('$').FirstName, 'Ивано', 'return property value by property after change property'); + done(); + } + }); + + it('should validate item', function (done) { + // Given + var dataSource = createObjectDataSource(); + + dataSource.setErrorValidator(validator); + dataSource.updateItems(handleItemsReady); + + function handleItemsReady(){ + + //When + var items = dataSource.getItems(), + validateResult1 = dataSource.getValidationResult(items[0]), + validateResult2 = dataSource.getValidationResult(items[1]), + validateResult3 = dataSource.getValidationResult(); + + // Then + assert.isTrue(validateResult1.IsValid, 'successfully validation'); + + assert.isFalse(validateResult2.IsValid, 'fail validation'); + assert.lengthOf(validateResult2.Items, 1, 'fail validation results'); + assert.equal(validateResult2.Items[0].property, 'FirstName', 'fail validation property result'); + + assert.isFalse(validateResult3.IsValid, 'full validation'); + assert.lengthOf(validateResult3.Items, 6, 'full validation results'); + assert.equal(validateResult3.Items[3].property, '4.FirstName', 'full validation property result'); + done(); + } + + function validator(context, argument){ + var result = { + IsValid: true + }; + + if(argument.FirstName != 'Иван'){ + result.IsValid = false; + result.Items = [{ + property: 'FirstName', + message: 'Почему не Иван?!' + }]; + } + + return result; + } + }); + + it('should save item', function (done) { + // Given + var dataSource = createObjectDataSource(); + + dataSource.updateItems(handleItemsReady1); + + function handleItemsReady1(){ + + //When + var item = dataSource.getSelectedItem(); + + dataSource.setProperty('FirstName', 'Иванидзе'); + dataSource.saveItem(item); + + dataSource.updateItems(handleItemsReady2); + } + + function handleItemsReady2(){ + // Then + assert.equal(dataSource.getProperty('FirstName'), 'Иванидзе', 'item is saved'); + done(); + } + }); + + it('should delete item', function (done) { + // Given + var dataSource = createObjectDataSource(); + + dataSource.updateItems(handleItemsReady1); + + function handleItemsReady1(){ + + //When + var items = dataSource.getItems(), + itemsCount = items.length; + + dataSource.deleteItem(items[0], function(context, argument){ + // Then + items = dataSource.getItems(); + assert.lengthOf(items, itemsCount-1, 'items length is decrease'); + assert.equal(dataSource.getSelectedItem(), null, 'deleted item exclude from selected item'); + done(); + }); + } + }); + + it('should subscribe on itemsUpdated from metadata', function (done) { + var metadata = { + OnItemsUpdated: '{window.testCount = window.testCount || 0; window.testCount++; window.testArgs = args; window.testContext = context;}' + }; + + // Given + var dataSource = createObjectDataSource(metadata); + + //When + dataSource.updateItems(handleItemsReady1); + + function handleItemsReady1(){ + // Then + assert.equal(window.testCount, 1, 'on items updated was called right times'); + assert.isTrue(!!window.testArgs, 'on items updated handler passed args'); + assert.isTrue(!!window.testContext, 'on items updated handler passed context'); + + delete window['testCount']; + delete window['testArgs']; + delete window['testContext']; + + done(); + } + }); + }); + + /* TODO раскомментировать когда в object DS заработают фильтры + describe('ObjectDataSource filter', function () { + it('should get filtered list of data', function () { + // Given //When + var ds = createObjectDataSource(), + items; + + //When + ds.setFilter([ + { + CriteriaType: 64, + Property: "FirstName", + Value: "Иван" + } + ]); + + // Then + items = ds.getItems(); + assert.isTrue(ds.isDataReady(), 'dataReady status is right'); + assert.lengthOf(items, 3, 'data provider returns items'); + }); + + it('should reset filter', function () { + // Given //When + var ds = createObjectDataSource(), + items; + + //When + ds.setFilter([ + { + CriteriaType: 64, + Property: "FirstName", + Value: "Иван" + } + ]); + assert.lengthOf(ds.getItems(), 3, 'Apply filter'); + + ds.setFilter([]); + + // Then + items = ds.getItems(); + assert.isTrue(ds.isDataReady(), 'dataReady status is right'); + assert.lengthOf(items, 7, 'clear filter'); + }); + + });*/ +}); + +describe('RestDataSource', function () { + window.InfinniUI.providerRegister.register('RestDataSource', FakeRestDataProvider); + + var items = [ + { + "_id": '1', + "FirstName": "Иван", + "LastName": "Иванов" + }, + { + "_id": '2', + "FirstName": "Петр", + "LastName": "Петров" + }, + { + "_id": '3', + "FirstName": "Иван1", + "LastName": "Иванов1" + }, + { + "_id": '4', + "FirstName": "Петр2", + "LastName": "Петров2" + }, + { + "_id": '5', + "FirstName": "Иван3", + "LastName": "Иванов3" + }, + { + "_id": '6', + "FirstName": "Петр4", + "LastName": "Петров5" + }, + { + "_id": '10', + "FirstName": "Анна", + "LastName": "Сергеева" + + } + ]; + + function createRestDataSource(missParam){ + + var view = fakeView(); + var dataSource = new InfinniUI.RestDataSource({ view: view }), + newItems = JSON.parse(JSON.stringify(items)); + + dataSource.suspendUpdate('urlTuning'); + dataSource.setNewItemsHandler(function(newItemsData){ + if(newItemsData){ + return newItemsData['Result']['Items']; + + }else{ + return newItemsData; + + } + }); + + /* + * кейсы использования фильтров + * + * удобно ли будет биндить автокомплит комбобокса на ДС вручную? + * + * DS{ + * Autocomplete: true, + * AutocompleteValue: { + * Source: "SomeDocDS", + * Property: ".filter", + * Direction: "ToSource", + * Converters: { + * ToSource: "{return 'eq(' + args.value + ')';}" + * } + * } + * } + * */ + + dataSource.setGettingUrlParams({ + type: 'get', + origin:'http://some.ru', + path:'/some/id<%param1%><%param2%>?a=2&b=<%param1%><%param3%>', + data: {}, + + params: { + param1: 4, + param2: missParam ? undefined : '/', + param3: '&c=4' + } + }); + + dataSource.setSettingUrlParams({ + type: 'post', + origin:'http://some.ru', + path:'/some/<%param1%>/<%param2%>', + data: { + a:2, + b: '<%param1%>', + c: '!1<%param2%>2!' + }, + + params: { + param1: '', + param2: '' + } + }); + + dataSource.setDeletingUrlParams({ + type: 'delete', + origin:'http://some.ru', + path:'/some/<%param1%>/<%param2%>', + data: { + a:2, + b: '<%param1%>', + c: '!1<%param2%>2!' + }, + + params: { + param1: '', + param2: '' + } + }); + + dataSource.resumeUpdate('urlTuning'); + + FakeRestDataProvider.prototype.items = newItems; + FakeRestDataProvider.prototype.lastSendedUrl = ''; + + return dataSource; + } + + describe('RestDataSourceBuilder', function () { + + it('successful build', function () { + // Given + var builder = new InfinniUI.ApplicationBuilder(); + var metadata = { + GettingParams: { + Method: 'get', + Origin: 'http://some.ru', + Path: '/some/id<%param1%>', + Data: { + a: 'param1=<%param1%>' + }, + + Params: { + param1: 4 + } + } + }; + + // When + var restDataSource = builder.buildType('RestDataSource', metadata, {parentView: fakeView()}); + + // Then + var gettingParams = restDataSource.getGettingUrlParams(); + + assert.equal(gettingParams.method, 'get'); + assert.equal(gettingParams.origin, 'http://some.ru'); + assert.equal(gettingParams.path, '/some/id<%param1%>'); + assert.deepEqual(gettingParams.data, {a: 'param1=<%param1%>'}); + assert.deepEqual(gettingParams.params, {param1: 4}); + }); + + }); + + describe('RestDataSource base api', function () { + + it('should get list of data', function (done) { + // Given + + + var dataSource = createRestDataSource(); + + assert.isFalse(dataSource.isDataReady(), 'dataReady status is right (false)'); + assert.isFalse(dataSource.get('isRequestInProcess'), 'is request not in process'); + + //When + + dataSource.updateItems( + function(context, args){ + // Then + assert.isTrue(args.value.length > 0, 'data provider returns items'); + assert.isTrue(dataSource.getItems().length > 0, 'data source have items'); + assert.isTrue(dataSource.isDataReady(), 'dataReady status is right (true)'); + done(); + } + ); + }); + + it('should get document property', function (done) { + // Given + var dataSource = createRestDataSource(); + + //When + dataSource.updateItems(handleItemsReady); + + function handleItemsReady(){ + // Then + assert.equal(dataSource.getProperty('FirstName'), 'Иван', 'return property value by simple property'); + assert.equal(dataSource.getProperty('$.FirstName'), 'Иван', 'return property value by relative property'); + assert.equal(dataSource.getProperty('$').FirstName, 'Иван', 'return property - full item by $ selector'); + assert.equal(dataSource.getProperty('2.FirstName'), 'Иван1', 'return property - full item by index selector'); + assert.equal(dataSource.getProperty('.selectedItem._id'), 1, 'return right spec property'); + done(); + } + }); + + it('should change document property', function (done) { + // Given + var dataSource = createRestDataSource(); + var item3; + + + dataSource.updateItems(handleItemsReady); + + + function handleItemsReady(){ + assert.equal(dataSource.getProperty('FirstName'),'Иван', 'return property value by property'); + assert.equal(dataSource.getProperty('.selectedItem._id'), 1, 'return property value by property 2'); + item3 = dataSource.getProperty('3'); + + //When + dataSource.setProperty('FirstName', 'Иванидзе'); + dataSource.setProperty('$.LastName', 'Ивнв'); + dataSource.setProperty('2.FirstName', 'Иванидзе-дзе'); + dataSource.setProperty('3', { + "_id": '55', + "FirstName": "П2", + "LastName": "Пе2" + }); + dataSource.setProperty('3.FirstName', 'П22'); + + // Then + assert.equal(dataSource.getProperty('$').FirstName, 'Иванидзе', 'return property value by property after change property'); + assert.equal(dataSource.getProperty('LastName'), 'Ивнв', 'return property value by property after change property 2'); + assert.equal(dataSource.getProperty('2').FirstName, 'Иванидзе-дзе', 'return property value by property after change property by id'); + assert.equal(dataSource.getProperty('3.LastName'), "Пе2"); + assert.equal(dataSource.getProperty('3.FirstName'), "П22"); + assert.equal(dataSource.getProperty('3._id'), '55'); + done(); + } + }); + + it('should add changing items in modified set', function (done) { + // Given + var dataSource = createRestDataSource(); + var item; + + + dataSource.updateItems(handleItemsReady); + + + function handleItemsReady(){ + assert.isFalse(dataSource.isModified(), 'at first items is not modified'); + + //When + dataSource.setProperty('FirstName', 'Иванидзе'); + dataSource.setProperty('$.LastName', 'Ивнв'); + dataSource.setProperty('2.FirstName', 'Иванидзе-дзе'); + dataSource.setProperty('3.FirstName', 'Petrov'); + dataSource.setProperty('3', { + "_id": '55', + "FirstName": "П2", + "LastName": "Пе2" + }); + dataSource.setProperty('4', { + "_id": '5', + "FirstName": "П5", + "LastName": "Пе5" + }); + + // Then + assert.equal(_.size(dataSource.get('modifiedItems')), 4, 'length of modified items'); + item = dataSource.getProperty('0'); + assert.isTrue(dataSource.isModified(item), 'is modified 1'); + item = dataSource.getProperty('2'); + assert.isTrue(dataSource.isModified(item), 'is modified 2'); + item = dataSource.getProperty('3'); + assert.isTrue(dataSource.isModified(item), 'is modified 3'); + item = dataSource.getProperty('4'); + assert.isTrue(dataSource.isModified(item), 'is modified 4'); + + done(); + } + }); + + it('should change spec value as property', function (done) { + // Given + var dataSource = createRestDataSource(); + var item3; + + + dataSource.updateItems(handleItemsReady); + + + function handleItemsReady(){ + assert.equal(dataSource.getProperty('FirstName'),'Иван', 'return property value by property'); + assert.equal(dataSource.getProperty('.selectedItem._id'), 1, 'return property value by property 2'); + item3 = dataSource.getProperty('3'); + + //When + dataSource.setProperty('.selectedItem', {'a':3}); + + // Then + assert.equal(dataSource.getProperty('.selectedItem.a'), 3, 'return property value by property after change property 5'); + done(); + } + }); + + it('should handle property changed', function (done) { + // Given + var dataSource = createRestDataSource(); + var result = ''; + + + function subscribeOnPropertyChanged(){ + dataSource.onPropertyChanged('0.FirstName', function(context, args){ + result += '1'; + + assert.equal(args.oldValue, 'Иван', 'right old value in args'); + assert.equal(args.newValue, 'Иванидзе', 'right new value in args'); + assert.equal(dataSource.getProperty('FirstName'), 'Иванидзе', 'value in source is new, when onPropertyChanged called'); + }); + + dataSource.onPropertyChanged('0.LastName', function(context, args){ + result += '2'; + + assert.equal(args.oldValue, 'Иванов', 'right old value in args'); + assert.equal(args.newValue, 'Ивнв', 'right new value in args'); + assert.equal(dataSource.getProperty('LastName'), 'Ивнв', 'value in source is new, when onPropertyChanged called'); + }); + + dataSource.onPropertyChanged('.selectedItem', function(context, args){ + result += '3'; + + assert.equal(args.oldValue.FirstName, 'Иванидзе', 'right old value in args'); + assert.equal(args.newValue.a, 3, 'right new value in args'); + assert.equal(dataSource.getSelectedItem().a, 3, 'value in source is new, when onPropertyChanged called'); + }); + } + + + dataSource.updateItems(handleItemsReady); + + + function handleItemsReady(){ + subscribeOnPropertyChanged(); + + //When + dataSource.setProperty('FirstName', 'Иванидзе'); + dataSource.setProperty('$.LastName', 'Ивнв'); + dataSource.setProperty('2.FirstName', 'Иванидзе-дзе'); + dataSource.setProperty('3', { + "_id": '55', + "FirstName": "П2", + "LastName": "Пе2" + }); + dataSource.setProperty('3.FirstName', 'П22'); + + dataSource.setProperty('.selectedItem', {'a':3}); + + // Then + assert.equal(result, '123', 'all handlers called in correct order'); + done(); + } + }); + + it('should handle selectedItem changed', function (done) { + // Given + var dataSource = createRestDataSource(); + var result = ''; + var item; + + + dataSource.onSelectedItemChanged(function(context, args){ + result += '1'; + + //assert.isTrue(!args.oldValue || args.oldValue.FirstName == 'Иван', 'right old value in args'); + assert.isTrue(args.value.FirstName == 'Иван' || args.value.FirstName == 'Петр', 'right new value in args'); + }); + + + dataSource.updateItems(handleItemsReady); + + + function handleItemsReady(){ + item = dataSource.getItems()[1]; + + //When + dataSource.setSelectedItem(item); + + // Then + assert.equal(result, '11', 'all handlers called in correct order'); + done(); + } + }); + + it('should handle url params changing', function (done) { + // Given + var dataSource = createRestDataSource(true); + var item; + + assert.equal(FakeRestDataProvider.prototype.lastSendedUrl, '', 'request was not sended'); + + dataSource.updateItems(handleItemsReady); + + dataSource.setGettingUrlParams('params.param2', '/newVal/'); + + function handleItemsReady(){ + // Then + assert.equal(FakeRestDataProvider.prototype.lastSendedUrl, 'http://some.ru/some/id4/newVal/?a=2&b=4&c=4', 'request sended on right url'); + + done(); + } + }); + + }); +}); + +describe('Parameters', function () { + + it('Parameter base API', function () { + + // Given When + var view = fakeView(); + var parameter = new InfinniUI.Parameter({view: view, name: 'name'}); + + // Then + assert.equal(parameter.getView(), view, 'view is right'); + assert.equal(parameter.getName(), 'name', 'name is right'); + }); + + it('Parameter value and property', function () { + + // Given + var parameter = new InfinniUI.Parameter({view: fakeView(), name: 'name'}), + val = { + f1:{ + value: 5 + }, + f2: 3 + }; + + assert.isUndefined(parameter.getValue(), 'start value is undefined'); + assert.isUndefined(parameter.getProperty(''), 'start property is undefined'); + assert.isUndefined(parameter.getProperty('f1'), 'start property is undefined 2'); + assert.isUndefined(parameter.getProperty('f1.value'), 'start property is undefined 3'); + + //When + parameter.setValue(val); + + // Then + assert.equal(parameter.getValue(), val, 'value after setting is right'); + assert.equal(parameter.getProperty(''), val, 'property after setting is right'); + assert.equal(parameter.getProperty('f1'), val.f1, 'property after setting is right 2'); + assert.equal(parameter.getProperty('f1.value'), val.f1.value, 'property after setting is right 3'); + }); + + it('Parameter handling property changed', function () { + + // Given + var parameter = new InfinniUI.Parameter({view: fakeView(), name: 'name'}), + handlerWasCalled = false, + val = { + f1:{ + value: 5 + }, + f2: 3 + }; + + parameter.setValue(10); + + parameter.onPropertyChanged(onPropertyChangedHandler); + + //When + parameter.setValue(val); + + // Then + function onPropertyChangedHandler(context, args){ + assert.equal(args.newValue, val, 'new value is right'); + assert.equal(args.oldValue, 10, 'old value is right'); + + handlerWasCalled = true; + } + + assert.isTrue(handlerWasCalled, 'handler was called'); + }); + +}); + +describe('FileProvider', function () { + + function delay(min, max) { + if (typeof min === 'undefined') { + min = 100; + } + if (typeof max === 'undefined') { + max = 200; + } + + return Math.ceil(Math.random() * (max - min) + min); + } + + describe('DocumentFileProvider', function () { + + beforeEach(function () { + ////register fake upload provider + //window.InfinniUI.providerRegister.register('DocumentFileProvider', function (/*metadata*/) { + // return { + // uploadFile: function () { + // var deferred = $.Deferred(); + // setTimeout(function () { + // deferred.resolve(); + // }, delay()); + // + // return deferred.promise(); + // }, + // getFileUrl: function () { + // return 'fake.html'; + // } + // }; + //}); + // + ////register fake DocumentDataSource provider + //window.InfinniUI.providerRegister.register('DocumentDataSource', function (metadataValue) { + // return { + // getItems: function (criteriaList, pageNumber, pageSize, sorting, resultCallback) { + // resultCallback(); + // }, + // createItem: function (resultCallback, idProperty) { + // var response = { + // 'DisplayName': 'display name' + // }; + // setTimeout(function () { + // resultCallback(response); + // }, delay()); + // }, + // + // saveItem: function (value, resultCallback, warnings, idProperty) { + // var response = [{ + // InstanceId: "42" + // }]; + // + // setTimeout(function () { + // resultCallback(response); + // }, delay()); + // }, + // setOrigin: function(){}, + // setPath: function(){}, + // setData : function(){}, + // setFilter: function(){}, + // setDocumentId: function(){}, + // getDocumentId: function () {}, + // createLocalItem: function (idProperty) { + // var result = {}; + // + // result[idProperty] = window.InfinniUI.guid(); + // + // return result; + // } + // }; + // + //}); + }); + + + it('DocumentDataSource.saveItem without files', function (done) { + var builder = new InfinniUI.ApplicationBuilder(); + var view = new InfinniUI.View; + var ds = builder.buildType('DocumentDataSource', {}, {parent: view, parentView: view, builder: builder}); + + ds.createItem(function (context, args) { + var item = args.value; + ds.setProperty('title', 'some title'); + ds.saveItem(item, function (context, args) { + var value = args.item; + assert.equal(item, value); + done(); + }, function (args) { + done('Fail on saveItem'); + }); + + }); + }); +/* + it('DocumentDataSource.saveItem with 1 file', function (done) { + var builder = new InfinniUI.ApplicationBuilder(); + var view = new InfinniUI.View; + var ds = builder.buildType('DocumentDataSource', {}, {parent: view, parentView: view, builder: builder}); + var uploadedFiles = []; + + ds.on('onFileUploaded', function (context, args) { + uploadedFiles.push(args.value); + }); + + ds.createItem(function (context, args) { + var item = args.value; + ds.setProperty('title', 'some title'); + var content = 'html content'; + ds.setFile(content, 'photo'); + ds.saveItem(item, function (context, args) { + var value = args.value; + assert.equal(item, value); + assert.lengthOf(uploadedFiles, 1, 'One file uploaded'); + assert.equal(uploadedFiles[0], content); + done(); + }, function (args) { + done('Fail on saveItem'); + }); + }); + }); + + it('DocumentDataSource.saveItem with files', function (done) { + var builder = new InfinniUI.ApplicationBuilder(); + var view = new InfinniUI.View; + var ds = builder.buildType('DocumentDataSource', {}, {parent: view, parentView: view, builder: builder}); + var uploadedFiles = []; + var files = '1234567890'.split('') + .map(function (num) { + return { + property: 'protperty_' + num, + content: 'html content #'+ num + '' + }; + }); + + + ds.on('onFileUploaded', function (context, args) { + uploadedFiles.push(args.value); + }); + + ds.createItem(function (context, args) { + var item = args.value; + ds.setProperty('title', 'some title'); + var content = 'html content'; + files.forEach(function (file) { + ds.setFile(file.content, file.property); + }); + + ds.saveItem(item, function (context, args) { + var value = args.value; + var amount = files.filter(function(file) { + return uploadedFiles.indexOf(file.content !== -1); + }).length; + assert.equal(item, value); + assert.lengthOf(uploadedFiles, files.length, 'All files uploaded'); + assert.equal(amount, files.length, 'specified files uploaded'); + done(); + }, function (args) { + done('Fail on saveItem'); + }); + }); + }); +*/ + }); + +}); + +describe('Button', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + describe('API', function () { + var element = builder.buildType('Button', {}); + + describe('Implementing Element Methods', function () { + testHelper.checkElementMethods(element); + }); + + it('should set getContent', function () { + + var element = new InfinniUI.Button(); + assert.isNull(element.getContent()); + + // when + element.setContent(content); + + // then + assert.isTrue(element.getContent() === content); + + function content(context, args) { + return 'button content'; + } + }); + + }); + + + describe('render', function () { + var button; + + beforeEach(function () { + button = builder.buildType('Button', {}); + }); + + it('should create', function () { + // Given + //var button = new InfinniUI.Button(); + + // When + var $el = button.render(); + + // Then + assert.equal($el.find('button').length, 1); + }); + + it('should set enabled', function () { + // Given + //var button = new InfinniUI.Button(); + button.setText('button'); + var $el = button.render(); + + assert.equal(button.getEnabled(), true); + // When + button.setEnabled(false); + + // Then + assert.equal(button.getEnabled(), false); + }); + + it('should set text', function () { + // Given + //var button = new InfinniUI.Button(); + button.setText('button'); + var $el = button.render(); + + // When + button.setText('other button'); + + // Then + assert.equal($el.find('.btntext').text(), 'other button'); + }); + + + it('should execute action on click', function () { + // Given + var + //button = new InfinniUI.Button(), + onLastActionExecute = 0, + onNewActionExecute = 0; + + button.setAction(new function(){ + this.execute = function () { + onLastActionExecute++; + }; + }); + + button.setAction(new function(){ + this.execute = function () { + onNewActionExecute++; + }; + }); + + assert.equal(onLastActionExecute, 0); + assert.equal(onNewActionExecute, 0); + + // When + button.render(); + button.click(); + + // Then + assert.equal(onLastActionExecute, 0); + assert.equal(onNewActionExecute, 1); + }); + + it('event onClick', function () { + // Given + var + //button = new InfinniUI.Button(), + onClickFlag = 0; + + button.onClick(function(){ + onClickFlag++; + }); + + assert.equal(onClickFlag, 0); + + // When + button.render(); + button.click(); + + // Then + assert.equal(onClickFlag, 1); + }); + + it('should be true if scriptsHandlers call', function () { + //Given + var view = new InfinniUI.View(); + var scripts = view.getScripts(); + scripts.add({ + name: 'OnClick', + func: function (context, args) { + window.Test.button = 5; + } + }); + + scripts.add({ + name: 'OnLoaded', + func: function (context, args) { + window.Test.buttonLoaded = true; + } + }); + + var buttonBuilder = new InfinniUI.ButtonBuilder(); + var metadata = { + OnClick:{ + Name: 'OnClick' + }, + OnLoaded:{ + Name: 'OnLoaded' + } + }; + window.Test = {button:1, buttonLoaded: false}; + + //When + var button = buttonBuilder.build(null, {builder: builder, parent: view, parentView: view, metadata: metadata}); + button.render(); + //var $button = $(button.render()); + //$button.find('button').click(); + button.click(); + + // Then + assert.equal(window.Test.button, 5); + assert.isTrue(window.Test.buttonLoaded); + }); + }); +}); + +describe('ButtonBuilder', function () { + describe('build', function () { + it('successful build', function () { + // Given + + var metadata = { + Text: "Click me", + Visible: false, + HorizontalAlignment: 'Right', + Action: { + OpenAction: { + LinkView: { + AutoView: {} + } + } + } + }; + + // When + var builder = new InfinniUI.ButtonBuilder(); + var button = builder.build(null, {builder: new InfinniUI.ApplicationBuilder(), metadata: metadata, parentView: new InfinniUI.View()}); + + // Then + assert.isNotNull(button); + assert.equal(button.getText(), 'Click me'); + assert.isFalse(button.getVisible()); + assert.equal(button.getHorizontalAlignment(), 'Right'); + }); + + }); +}); + +describe('ComboBox', function () { + describe('render', function () { + + it('Setting the properties: value, name, enabled, visible, horizontalAlignment', function () { + // Given + var comboBox = new InfinniUI.ComboBox(), $el, $control; + + $el = comboBox.render(); + + assert.isUndefined($el.attr('data-pl-name')); + assert.isFalse($el.hasClass('hidden'), 'hidden'); + assert.isFalse($el.hasClass('pull-left'), 'pull-left'); + + // When + comboBox.setName('newName'); + comboBox.setEnabled(false); + comboBox.setVisible(false); + + // Then + + assert.equal($el.attr('data-pl-name'), 'newName'); + + assert.isTrue($el.hasClass('hidden')); + assert.isFalse($el.hasClass('pull-left')); + }); + + it('Events onLoad, onValueChanged', function () { + // Given + var comboBox = new InfinniUI.ComboBox(), + onLoadFlag = 0, + onValueChanged = 0; + + comboBox.onLoaded(function(){ + onLoadFlag++; + }); + comboBox.onValueChanged(function(){ + onValueChanged++; + }); + + assert.equal(onLoadFlag, 0); + assert.equal(onValueChanged, 0); + + // When + comboBox.render(); + comboBox.setValue('new'); + + // Then + assert.equal(onLoadFlag, 1); + assert.equal(onValueChanged, 1); + }); + + it('ValueSelector', function () { + // Given + var metadata = { + "Text": 'Пациенты', + "Scripts": [ + { + "Name": "ValueSelector1", + "Body": "return {Id: args.value.Id, DisplayName: args.value.Display};" + } + ], + "DataSources": [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + {"Id": 1, "Display": "LTE", "State": "New"}, + {"Id": 2, "Display": "2G", "State": "Deprecated"}, + {"Id": 3, "Display": "3G", "State": "Deprecated"} + ] + } + }, { + ObjectDataSource: { + "Name": "ObjectDataSource2", + "Items": [ + {"Value": {"Id": 2, "DisplayName": "2G"}} + ] + } + } + ], + "Items": [{ + + ComboBox: { + "LabelText": "Combobox Label", + "ItemTemplate": { + "Label": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "Items": { + "Source": "ObjectDataSource1", + "Property": "" + }, + "ValueSelector": "ValueSelector1", + "ValueFormat": "{Id} - {DisplayName}", + "MultiSelect": false, + "Value": { + "Source": "ObjectDataSource2", + "Property": "Value" + } + } + }] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout) { + $layout.detach(); + var $label = $layout.find('.pl-combobox > .pl-control-label'), + $value = $layout.find('.pl-combobox__value'); + + + assert.equal($label.text(), 'Combobox Label'); + assert.equal($value.length, 1); + assert.equal($value.find('.pl-label').text(), '2 - 2G'); + } + }); + + it('ValueSelector multiselect', function () { + // Given + var metadata = { + "Text": 'Пациенты', + "Scripts": [ + { + "Name": "ValueSelector1", + "Body": "return {Id: args.value.Id, DisplayName: args.value.Display};" + } + ], + "DataSources": [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + {"Id": 1, "Display": "LTE", "State": "New"}, + {"Id": 2, "Display": "2G", "State": "Deprecated"}, + {"Id": 3, "Display": "3G", "State": "Deprecated"} + ] + } + }, { + ObjectDataSource: { + "Name": "ObjectDataSource2", + "Items": [ + {"Value": [ + {"Id": 2, "DisplayName": "2G"}, + {"Id": 3, "DisplayName": "3G"} + ]} + ] + } + } + ], + "Items": [{ + + ComboBox: { + "LabelText": "Combobox Label", + "ItemTemplate": { + "Label": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "Items": { + "Source": "ObjectDataSource1", + "Property": "" + }, + "ValueSelector": "ValueSelector1", + "ValueFormat": "{Id} - {DisplayName}", + "MultiSelect": true, + "Value": { + "Source": "ObjectDataSource2", + "Property": "Value" + } + } + }] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout) { + $layout.detach(); + var $label = $layout.find('.pl-combobox > .pl-control-label'), + $value = $layout.find('.pl-combobox__value'); + + assert.equal($label.text(), 'Combobox Label'); + assert.equal($value.find('.pl-label').text(), '2 - 2G3 - 3G'); + } + }); + + it('ValueTemplate', function () { + // Given + var metadata = { + "Text": 'Пациенты', + "DataSources": [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + {"Id": 1, "Display": "LTE", "State": "New"}, + {"Id": 2, "Display": "2G", "State": "Deprecated"}, + {"Id": 3, "Display": "3G", "State": "Deprecated"} + ] + } + }, { + ObjectDataSource: { + "Name": "ObjectDataSource2", + "Items": [ + {"Value": {"Id": 2, "Display": "2G","State": "Deprecated"}} + ] + } + } + ], + "Items": [{ + + ComboBox: { + "LabelText": "Combobox Label", + "ItemTemplate": { + "Label": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "Items": { + "Source": "ObjectDataSource1", + "Property": "" + }, + "ValueTemplate": { + "StackPanel": { + "Orientation": "Horizontal", + "Items": [ + { + "Label": { + "HorizontalAlignment": "Left", + "Value": { + "Source": "ObjectDataSource2", + "Property": "$.Value.Display" + } + } + }, + { + "Label": { + "HorizontalAlignment": "Left", + "Value": { + "Source": "ObjectDataSource2", + "Property": "$.Value.Id" + } + } + } + ] + } + + }, + "MultiSelect": false, + "Value": { + "Source": "ObjectDataSource2", + "Property": "$.Value" + } + } + }] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout) { + $layout.detach(); + var $label = $layout.find('.pl-combobox > .pl-control-label'), + $value = $layout.find('.pl-combobox__value'); + + assert.equal($label.text(), 'Combobox Label'); + assert.equal($value.find('.pl-label').text(), '2G2'); + } + }); + + it('ValueTemplate multiselect', function () { + // Given + var metadata = { + "Text": 'Пациенты', + "DataSources": [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + {"Id": 1, "Display": "LTE", "State": "New"}, + {"Id": 2, "Display": "2G", "State": "Deprecated"}, + {"Id": 3, "Display": "3G", "State": "Deprecated"} + ] + } + }, { + ObjectDataSource: { + "Name": "ObjectDataSource2", + "Items": [ + {"Value": [ + {"Id": 2, "Display": "2G","State": "Deprecated"}, + {"Id": 3, "Display": "3G", "State": "Deprecated"} + ]} + ] + } + } + ], + "Items": [{ + + ComboBox: { + "LabelText": "Combobox Label", + "ItemTemplate": { + "Label": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "Items": { + "Source": "ObjectDataSource1", + "Property": "" + }, + "ValueTemplate": { + "StackPanel": { + "Orientation": "Horizontal", + "Items": [ + { + "Label": { + "HorizontalAlignment": "Left", + "Value": { + "Source": "ObjectDataSource2", + "Property": "Value.#.Display" + } + } + }, + { + "Label": { + "HorizontalAlignment": "Left", + "Value": { + "Source": "ObjectDataSource2", + "Property": "Value.#.Id" + } + } + } + ] + } + + }, + "MultiSelect": true, + "Value": { + "Source": "ObjectDataSource2", + "Property": "$.Value" + } + } + }] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout) { + $layout.detach(); + var $label = $layout.find('.pl-combobox > .pl-control-label'), + $value = $layout.find('.pl-combobox__value'); + + assert.equal($label.text(), 'Combobox Label'); + assert.equal($value.find('.pl-label').text(), '2G23G3'); + } + }); + + }); + + describe('api', function () { + it('should update DisabledItemCondition', function (done) { + // Given + var metadata = { + "Text": 'Пациенты', + "Scripts": [ + { + "Name": "ValueSelector1", + "Body": "return {Id: args.value.Id, DisplayName: args.value.Display};" + } + ], + "DataSources": [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + {"Id": 1, "Display": "LTE", "Type": 1}, + {"Id": 2, "Display": "2G", "Type": 2}, + {"Id": 3, "Display": "3G", "Type": 2} + ] + } + }, { + ObjectDataSource: { + "Name": "ObjectDataSource2", + "Items": [ + {"Value": {"Id": 2, "DisplayName": "2G"}} + ] + } + } + ], + "Items": [{ + + ComboBox: { + "Name": "ComboBox1", + "LabelText": "Combobox Label", + "ItemTemplate": { + "Label": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "ValueProperty": "Display", + "Items": { + "Source": "ObjectDataSource1", + "Property": "" + }, + "GroupItemTemplate": { + "Label": { + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Type" + }, + "TextHorizontalAlignment": "Center" + } + }, + "GroupValueProperty": "Type", + "DisabledItemCondition": "{ return (args.value.Id == 2); }", + "Value": { + "Source": "ObjectDataSource2", + "Property": "Value" + } + } + }] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout) { + var combobox = view.context.controls['ComboBox1']; + var $value = $layout.find('.pl-combobox__value'); + + $value.click(); + + var items = $('.pl-combobox-group__items .pl-label'); + assert.isFalse(items.eq(0).hasClass('pl-disabled'), 'bad render for enabled item'); + assert.isTrue(items.eq(1).hasClass('pl-disabled'), 'bad render for disabled item'); + + // When + combobox.setDisabledItemCondition(function (context, args) { + return args.value.Id == 1; + }); + $value.click(); + + // Then + items = $('.pl-combobox-group__items .pl-label'); + assert.isTrue(items.eq(0).hasClass('pl-disabled'), 'items not updated'); + assert.isFalse(items.eq(1).hasClass('pl-disabled'), 'items not updated'); + + done(); + view.close(); + + $('body').find('.pl-dropdown-container').detach(); + } + }); + }); + + +}); + +describe('DataGrid', function () { + + var metadata = { + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "LTE" }, + { "Id": 2, "Display": "3G" }, + { "Id": 3, "Display": "2G" } + ] + } + } + ], + Items: [{ + + "DataGrid": { + "Name": "DataGrid1", + "Items": { + "Source": "ObjectDataSource1", + "Property": "" + }, + "DisabledItemCondition": "{ return (args.value.Id == 2); }", + "Columns": [ + { + "Header": "Id", + "CellProperty": "Id" + }, + { + "Header": "Display", + "CellProperty": "Display" + } + ] + } + }] + }; + + describe('render', function () { + it('should render DataGrid', function (done) { + // Given When + testHelper.applyViewMetadata(metadata, onDataGridReady); + + // Then + function onDataGridReady(view, $grid){ + setTimeout(function() { + assert.isObject($grid); + + var headers = $grid.find(".pl-datagrid-row_header .pl-label"); + assert.equal(headers.first().text(), "Id"); + assert.equal(headers.last().text(), "Display"); + + var $body = $grid.find(".pl-datagrid-row_data"); + assert.equal($body.length, 3); + + done(); + view.close(); + }, 0); + } + }); + }); + + describe('API', function () { + it('should update DisabledItemCondition', function (done) { + // Given + testHelper.applyViewMetadata(metadata, function (view, $grid) { + setTimeout(function() { + var grid = view.context.controls['DataGrid1']; + //var $grid = grid.control.controlView.$el; + + var $rows = $grid.find("tbody .pl-datagrid-row"); + + assert.isFalse($rows.eq(0).hasClass('pl-disabled'), 'bad render for enabled item'); + assert.isTrue($rows.eq(1).hasClass('pl-disabled'), 'bad render for disabled item'); + + // When + grid.setDisabledItemCondition( function (context, args) { + return args.value.Id == 1; + }); + + // Then + assert.isTrue($rows.eq(0).hasClass('pl-disabled'), 'items not updated'); + assert.isFalse($rows.eq(1).hasClass('pl-disabled'), 'items not updated'); + + done(); + view.close(); + }, 0); + }); + + + }); + }); +}); + +describe('DataNavigation', function () { + it('should pass test default property', function () { + // Given + var metadata = { + DataSources : [ + { + ObjectDataSource: { + "Name": "PatientDataSource", + "Items": [ + {"Id": 1, "Display": "LTE", "State": "New"}, + {"Id": 2, "Display": "2G", "State": "Deprecated"}, + {"Id": 3, "Display": "3G", "State": "Deprecated"} + ] + } + } + ], + Items: [{ + + DataNavigation: { + Enabled: true, + Name: "DataNavigation1", + AvailablePageSizes: [ 20, 50, 100 ], + DataSource: "PatientDataSource" + } + }] + }; + + // When + testHelper.applyViewMetadata(metadata, onDataNavigationReady); + + // Then + function onDataNavigationReady(view, $view){ + var dataNavigation = view.context.controls['DataNavigation1']; + + assert.isDefined(dataNavigation); + assert.isTrue(dataNavigation.getEnabled()); + assert.isTrue(dataNavigation.getVisible()); + assert.equal(dataNavigation.getHorizontalAlignment(), 'Stretch'); + assert.equal(dataNavigation.getDataSource().name, "PatientDataSource"); + + view.close(); + } + }); + + it('should call onPageNumberChanged', function (done) { + // Given + var dataNavigation = new InfinniUI.DataNavigation(); + + dataNavigation.onPageNumberChanged(function(){ + // Then + done(); + }); + + // When + dataNavigation.setPageNumber(1); + }); + + it('should call onPageSizeChanged', function (done) { + // Given + var dataNavigation = new InfinniUI.DataNavigation(); + + dataNavigation.onPageSizeChanged(function(){ + // Then + done(); + }); + + // When + dataNavigation.setPageSize(1); + }); +}); + +describe('DateTimePicker', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + describe('API', function () { + var element = builder.buildType('DateTimePicker', {}); + + describe('Implementing DateTimePicker Methods', function () { + ['getMinValue', 'setMinValue', 'getMaxValue', 'setMaxValue', 'getMode', 'setMode'] + .forEach(function (methodName) { + it(methodName, function() { + assert.isFunction(element[methodName], methodName); + }); + + }); + }); + + describe('Implementing TextEditorBase Methods', function () { + testHelper.checkTextEditorBaseMethods(element); + }); + + describe('Implementing EditorBase Methods', function () { + testHelper.checkEditorBaseMethods(element); + }); + + describe('Implementing Element Methods', function () { + testHelper.checkElementMethods(element); + }); + + //@TODO Add Checking Events + }); + + describe('Metadata', function () { + + it('Using default value', function () { + var metadata = { + "DateTimePicker": {} + }; + + var element = builder.build(metadata, {}); + + assert.equal(element.getMode(), 'Date', 'Mode'); + assert.equal(element.getFocusable(), true, 'Focusable'); + assert.equal(element.getEnabled(), true, 'Enabled'); + assert.equal(element.getVisible(), true, 'Visible'); + assert.equal(element.getLabelFloating(), false, 'LabelFloating'); + assert.equal(element.getVerticalAlignment(), 'Top', 'VerticalAlignment'); + assert.equal(element.getHorizontalAlignment(), 'Stretch', 'HorizontalAlignment'); + assert.equal(element.getTextHorizontalAlignment(), 'Left', 'TextHorizontalAlignment'); + }); + + it('Apply metadata', function () { + var metadata = { + "DateTimePicker": { + "Name": "DatePicker1", + "MinValue": "2015-09-01T15:26:42.0060+05:00", + "MaxValue": "2015-09-18T15:26:42.0060+05:00", + "Mode": "DateTime", + + "LabelText": "Datepicker's label", + "LabelFloating": true, + "DisplayFormat": "{:d}", + "EditMask": { + "DateTimeEditMask": { + "Mask": "d" + } + }, + "HintText": "Hint", + "ErrorText": "Error", + "WarningText": "Warning", + "Enabled": false, + "Visible": false, + "VerticalAlignment": "Bottom", + "HorizontalAlignment": "Right", + "TextStyle": "Display4", + "Foreground": "Primary1", + "Background": "Accent1" + + } + }; + + var element = builder.build(metadata, {}); + assert.equal(String(element.getMinValue()), String(new Date("2015-09-01T15:26:42.0060+05:00")), 'MinValue'); + assert.equal(String(element.getMaxValue()), String(new Date("2015-09-18T15:26:42.0060+05:00")), 'MaxValue'); + assert.equal(element.getMode(), 'DateTime', 'DateTime'); + + assert.equal(element.getLabelText(), "Datepicker's label", 'LabelText'); + assert.equal(element.getLabelFloating(), true, 'LabelFloating'); + assert.isFunction(element.getDisplayFormat(), 'DateTimeFormat'); + assert.instanceOf(element.getEditMask(), InfinniUI.DateTimeEditMask, 'EditMask'); + + assert.equal(element.getHintText(), "Hint", 'HintText'); + assert.equal(element.getErrorText(), "Error", 'ErrorText'); + assert.equal(element.getWarningText(), "Warning", 'WarningText'); + + assert.equal(element.getName(), "DatePicker1", 'Name'); + assert.equal(element.getEnabled(), false, 'Enabled'); + assert.equal(element.getVisible(), false, 'Visible'); + assert.equal(element.getVerticalAlignment(), 'Bottom', 'VerticalAlignment'); + assert.equal(element.getTextStyle(), 'Display4', 'TextStyle'); + assert.equal(element.getForeground(), 'Primary1', 'Foreground'); + assert.equal(element.getBackground(), 'Accent1', 'Background'); + + }); + + it('correct convert from string to date and from date to string', function () { + // Given + var dateTimePicker = new InfinniUI.DateTimePicker(); + + dateTimePicker.render(); + + // When + dateTimePicker.setValue('2014-07-29'); + + // Then + assert.equal(dateTimePicker.getValue().substr(0, 10), '2014-07-29'); + }); + + it('event OnValueChanged', function () { + // Given + var dateTimePicker = new InfinniUI.DateTimePicker(), + onValueChangedFlag = 0; + + dateTimePicker.render(); + + dateTimePicker.onValueChanged(function () { + onValueChangedFlag++; + }); + + assert.equal(onValueChangedFlag, 0); + + // When + dateTimePicker.setValue('2014-07-29'); + dateTimePicker.setValue('2014-07-30'); + + // Then + assert.equal(onValueChangedFlag, 2); + }); + + }); +}); + + +describe('DateTimePickerBuilder', function () { + describe('build', function () { + it('successful build DateTimePicker', function () { + // Given + + var dateTimePickerMetadata = {}; + + // When + var builder = new InfinniUI.DateTimePickerBuilder(); + var dateTimePicker = builder.build(null, {builder: new InfinniUI.ApplicationBuilder(), view: new InfinniUI.View(), metadata: dateTimePickerMetadata}); + + // Then + assert.isNotNull(dateTimePicker); + assert.isObject(dateTimePicker); + + }); + }); +}); + +describe('EditorBase', function () { + describe('Textbox as exemplar of EditorBase', function () { + + it('Base functional', function () { + // Given + var textBox = new InfinniUI.TextBox(); + + assert.isNull(textBox.getValue(), 'default value is null'); + assert.isNull(textBox.getHintText(), 'default hint text is null'); + assert.isNull(textBox.getErrorText(), 'default error text is null'); + assert.isNull(textBox.getWarningText(), 'default warning text is null'); + + + // When + textBox.setValue('value'); + textBox.setHintText('hint text'); + textBox.setErrorText('error text'); + textBox.setWarningText('warning text'); + + + // Then + assert.equal(textBox.getValue(), 'value', 'new value is right'); + assert.equal(textBox.getHintText(), 'hint text', 'new hint text is right'); + assert.equal(textBox.getErrorText(), 'error text', 'new error text is right'); + assert.equal(textBox.getWarningText(), 'warning text', 'new warning text is right'); + }); + + it('Base events functional', function () { + // Given + var textBox = new InfinniUI.TextBox(), + handling = 0; + + textBox.onValueChanging(onValueChangingHandler); + textBox.onValueChanged(onValueChangedHandler); + + // When + textBox.setValue('new'); + + // Then + function onValueChangingHandler(context, args){ + assert.equal(handling, 0, 'right order: changing handler is first'); + assert.isNull(args.oldValue, 'old value is null'); + assert.equal(args.newValue, 'new', 'new value is "new"'); + assert.equal(args.source, textBox, 'right source'); + + handling++; + } + + function onValueChangedHandler(context, args){ + assert.equal(handling, 1, 'right order: changing handler is second'); + assert.isNull(args.oldValue, 'old value is null'); + assert.equal(args.newValue, 'new', 'new value is "new"'); + assert.equal(args.source, textBox, 'right source'); + } + }); + + it('cancelling changing event', function () { + // Given + var textBox = new InfinniUI.TextBox(), + handling = 0; + + textBox.onValueChanging(onValueChangingHandler1); + textBox.onValueChanging(onValueChangingHandler2); + + // When + textBox.setValue('new'); + + // Then + function onValueChangingHandler1(context, args){ + assert.equal(handling, 0, 'right order: changing handler is first'); + assert.equal(args.newValue, 'new', 'new value is "new"'); + + handling++; + + return false + } + + function onValueChangingHandler2(context, args){ + assert.equal(handling, 1, 'right order: this changing handler is second'); + assert.equal(args.newValue, 'new', 'new value is "new"'); + + handling++; + } + + assert.equal(handling, 2, 'right order'); + assert.isNull(textBox.getValue(), 'value should not be changed'); + }); + }); + +}); + +describe('Element', function () { + describe('Element as path of TextBox', function () { + + it('Setting and getting the properties', function () { + // Given + var textBox = new InfinniUI.TextBox(), + textBox2 = new InfinniUI.TextBox(); + + // When + textBox.setValue('test'); + textBox2.setProperty('value', 'test2'); + + // Then + assert.equal(textBox.getProperty('value'), 'test'); + assert.equal(textBox2.getValue(), 'test2'); + }); + + it('Handling change properties', function (done) { + // Given + var textBox = new InfinniUI.TextBox(), + step = 1; + textBox.onPropertyChanged('value', onValueChanged); + textBox.onPropertyChanged('visible', onVisibleChanged); + + // When + textBox.setValue('test'); + textBox.setProperty('visible', false); + + // Then + function onValueChanged() { + assert.equal(textBox.getProperty('value'), 'test'); + assert.equal(step, 1); + step++; + } + + function onVisibleChanged() { + assert.equal(textBox.getProperty('visible'), false); + assert.equal(step, 2); + done(); + } + + }); + + it('Handling DOM event', function (done) { + // Given + var textBox = new InfinniUI.TextBox(); + textBox.onDoubleClick(onMouseDoubleClickHandler); + + // When + var $el = textBox.render(); + $el.trigger('dblclick'); + + // Then + function onMouseDoubleClickHandler(eventData) { + assert.equal(eventData.source, textBox, 'eventData has right source'); + done(); + } + + }); + + it('Click event', function (done) { + // Given + var textBox = new InfinniUI.TextBox(); + textBox.onClick(onMouseClickHandler); + + // When + var $el = textBox.render(); + $el.trigger('click'); + + //Then + function onMouseClickHandler(eventData) { + assert.equal(eventData.source, textBox, 'eventData has right source'); + done(); + } + }); + }); +}); + +describe('Extension Panel (build)', function () { + it('successful build', function () { + // Given + var builder = new InfinniUI.ExtensionPanelBuilder(); + var metadata = {}; + + // When + var extensionPanel = builder.build(null, {builder: new InfinniUI.ApplicationBuilder(), metadata: metadata, parentView: new InfinniUI.View()}); + + // Then + assert.isNotNull(extensionPanel); + }); + + it('should find extensionPanel in global namespace', function (done) { + // Given + var builder = new InfinniUI.ExtensionPanelBuilder(); + var metadata = { + "ExtensionName": "myExtensionPanel", + "Parameters": [ + { + "Name": "param1", + "Value": "hello" + } + ] + }; + var extensionPanel = builder.build(null, {builder: new InfinniUI.ApplicationBuilder(), metadata: metadata, parentView: new InfinniUI.View()}); + + window.myExtensionPanel = function(context, args){ + // Then + assert.isDefined(args.$el); + assert.isDefined(args.parameters); + + this.render = done; + }; + + // When + extensionPanel.render(); + }); +}); + +describe('UploadFileBox', function () { + + describe('debug', function () { + + it('render', function () { + var builder = new InfinniUI.ApplicationBuilder(); + var view = new InfinniUI.View(); + var metadata = { + MaxSize: 0, + AcceptTypes: [ + 'image/png' + ] + }; + + var element = builder.buildType("FileBox", metadata, {parent: view, parentView: view, builder: builder}); + + var $el = element.render(); + $('body').append($el); + $el.detach(); + }); + + + }); + + //describe('UploadFileBox', function () { + // + // var element; + // + // beforeEach (function () { + // element = new UploadFileBox(); + // }); + // + // it('Default property value', function () { + // // Given + // + // //$('body').append(element.render()); + // assert.strictEqual(element.getReadOnly(), false); + // assert.strictEqual(element.getMaxSize(), 0); + // + // }); + // + // it('Setting properties', function () { + // + // // Given + // element.setReadOnly(true); + // element.setAcceptTypes(['video/*']); + // element.setMaxSize(50000); + // element.setValue({Info: {}}); + // + // assert.equal(element.getReadOnly(), true); + // assert.deepEqual(element.getAcceptTypes(), ['video/*']); + // assert.deepEqual(element.getValue(), {Info: {}}); + // assert.equal(element.getMaxSize(), 50000); + // }); + // + //}); + + +// describe('UploadFileBox data binding', function () { +// it('should set UploadFileBox.value from property binding', function () { +// +// //это говнокод +// $('#page-content').empty(); +// +// window.providerRegister.register('UploadDocumentDataSource', function (metadataValue) { +// return new DataProviderUpload(new QueryConstructorUpload('http://127.0.0.1:8888', metadataValue)); +// }); +// +// window.providerRegister.register('DocumentDataSource', function () { +// return new FakeDataProvider(); +// }); +// +// $('body').append($('
').attr('id', 'page-content')); +// +// var metadata = { +// Text: 'Пациенты', +// DataSources: [ +// { +// DocumentDataSource: { +// Name : "PatientDataSource", +// ConfigId: 'Demography', +// DocumentId: 'Patient', +// IdProperty: 'Id', +// CreateAction: 'CreateDocument', +// GetAction: 'GetDocument', +// UpdateAction: 'SetDocument', +// DeleteAction: 'DeleteDocument', +// FillCreatedItem: true +// } +// } +// ], +// LayoutPanel: { +// StackPanel: { +// Name: 'MainViewPanel', +// Items: [ +// { +// UploadFileBox: { +// Name: 'UploadFileBox1', +// AcceptTypes: ['image/*', 'video/*'], +// MaxSize: 100000, +// Value : { +// FileBinding : { +// DataSource : 'PatientDataSource', +// Property : '$.file' +// } +// } +// } +// } +// ] +// } +// } +// }; +// +// var linkView = new InfinniUI.LinkView(null, function (resultCallback) { +// var builder = new InfinniUI.ApplicationBuilder(); +// var view = builder.buildType(fakeView(), 'View', metadata); +// resultCallback(view); +// }); +// linkView.setOpenMode('Application'); +// +// linkView.createView(function(view){ +// view.open(); +// +// var itemToSelect = null; +// view.getDataSource('PatientDataSource').getItems(function(data){ +// itemToSelect = data[1]; +// }); +// +// view.getDataSource('PatientDataSource').setSelectedItem(itemToSelect); +// +// +// //window.maindatasource = view.getDataSource('PatientDataSource'); +// +// //check text +// // assert.equal($('#page-content').find('input:text').val(), itemToSelect.LastName); +// // $('#page-content').remove(); +// }); +// }); +// }); + + +}); + +describe('Frame', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + describe('API', function () { + var element = builder.buildType('Frame', {}); + + describe('Implementing EditorBase Methods', function () { + testHelper.checkEditorBaseMethods(element); + }); + + describe('Implementing Element Methods', function () { + testHelper.checkElementMethods(element); + }); + }); + +}); + +describe('FrameBuilder', function () { + describe('build', function () { + it('successful build Frame', function () { + // Given + + var metadata = {}; + + // When + var builder = new InfinniUI.FrameBuilder(); + var element = builder.build(null, {builder: new InfinniUI.ApplicationBuilder(), view: new InfinniUI.View(), metadata: metadata}); + + // Then + assert.isNotNull(element); + assert.isObject(element); + }); + }); +}); + +describe('ImageBox', function () { + + function delay(min, max) { + if (typeof min === 'undefined') { + min = 100; + } + if (typeof max === 'undefined') { + max = 200; + } + + return Math.ceil(Math.random() * (max - min) + min); + } + + describe('API', function () { + var builder = new InfinniUI.ApplicationBuilder(); + var element = builder.buildType('ImageBox', {}); + + describe('Implementing ImageBox Methods', function () { + ['getMaxSize', 'setMaxSize', 'getAcceptTypes'] + .forEach(function (methodName) { + it(methodName, function () { + testHelper.checkMethod(element, methodName); + }); + + }); + }); + + describe('Implementing EditorBase Methods', function () { + testHelper.checkEditorBaseMethods(element); + }); + + describe('Implementing Element Methods', function () { + testHelper.checkElementMethods(element); + }); + }); + + describe('debug', function () { + + it('render', function () { + var builder = new InfinniUI.ApplicationBuilder(); + var view = new InfinniUI.View(); + var metadata = { + MaxSize: 0, + AcceptTypes: [ + 'image/png' + ] + }; + + var element = builder.buildType("ImageBox", metadata, {parent: view, parentView: view, builder: builder}); + + var $el = element.render(); + //$('body').append($el); + }); + + + }); + + describe('Upload new file', function () { + + //beforeEach(function () { + // //register fake upload provider + // window.InfinniUI.providerRegister.register('DocumentFileProvider', function (metadata) { + // return { + // uploadFile: function () { + // var deferred = $.Deferred(); + // setTimeout(function () { + // deferred.resolve(); + // }, delay()); + // + // return deferred.promise(); + // }, + // getFileUrl: function (fieldName, instanceId) { + // return [fieldName, instanceId, 'fake.html'].join('.'); + // } + // }; + // }); + // + // //register fake DocumentDataSource provider + // window.InfinniUI.providerRegister.register('DocumentDataSource', function (metadataValue) { + // return { + // getItems: function (criteriaList, pageNumber, pageSize, sorting, resultCallback) { + // var items = [{ + // "Id": "1", + // photo: { + // Info: { + // ContentId: 'somePhotoId' + // } + // } + // }]; + // setTimeout(function () { + // resultCallback(items); + // }, delay()); + // }, + // createItem: function (resultCallback, idProperty) { + // var response = { + // 'DisplayName': 'display name' + // }; + // setTimeout(function () { + // resultCallback(response); + // }, delay()); + // }, + // + // saveItem: function (value, resultCallback, warnings, idProperty) { + // var response = [{ + // InstanceId: "42" + // }]; + // + // setTimeout(function () { + // resultCallback(response); + // }, delay()); + // }, + // setOrigin: function(){}, + // setPath: function(){}, + // setData : function(){}, + // setFilter: function(){}, + // setDocumentId: function(){}, + // getDocumentId: function () {}, + // createLocalItem: function (idProperty) { + // var result = {}; + // + // result[idProperty] = guid(); + // result['__Id'] = result[idProperty]; + // + // return result; + // } + // }; + // + // }); + //}); + + // + //it('Should set image url', function (done) { + // var builder = new InfinniUI.ApplicationBuilder(); + // + // //Build view + // var view = new InfinniUI.View(); + // + // //Build DataSource + // var dataSources = view.getDataSources(); + // var dsMetadata = { + // Name: 'MyDataSource', + // ConfigId: 'MyConfig', + // DocumentId: 'MyDocument' + // }; + // var ds = builder.buildType('DocumentDataSource', dsMetadata, {parentView: view}); + // dataSources.add(ds); + // + // var PROPERTY_NAME = 'photo'; + // + // //build ImageBox + // var imageBoxMetadata = { + // Value: { + // Source: 'MyDataSource', + // Property: PROPERTY_NAME + // } + // }; + // var imageBox = builder.buildType('ImageBox', imageBoxMetadata, {parent: view, parentView: view}); + // + // imageBox.render(); + // + // ds.onItemsUpdated(function () { + // var items = ds.getItems(); + // ds.setSelectedItem(items[0]); + // assert.equal(imageBox.getValue(), [PROPERTY_NAME, '1', 'fake.html'].join('.'), 'Image URL for existing item'); + // + // ds.createItem(function (context, args) { + // imageBox.onPropertyChanged('value', function (context, args) { + // var url = [PROPERTY_NAME, 'MyPhotoId', 'fake.html'].join('.'); + // assert.equal(imageBox.getValue(), url, 'image URL for new item'); + // done(); + // }); + // + // ds.setProperty(PROPERTY_NAME, {ContentId: 'MyPhotoId2'}); + // }); + // }); + // + //}); + + }); + + describe('Render', function () { + var element; + + beforeEach(function () { + element = new InfinniUI.ImageBox(); + }); + + it('Setting properties', function () { + + // Given + element.setEnabled(true); + element.setAcceptTypes(['video/*']); + element.setMaxSize(50000); + //element.setValue({Info: {}}); + + assert.equal(element.getEnabled(), true); + assert.deepEqual(element.getAcceptTypes().toArray(), ['video/*']); + //assert.deepEqual(element.getValue(), {Info: {}}); + assert.equal(element.getMaxSize(), 50000); + }); + + }); + + +// describe('ImageBox data binding', function () { +// it('should set ImageBox.value from property binding', function () { +// +// //это говнокод +// $('#page-content').empty(); +// +// window.providerRegister.register('UploadDocumentDataSource', function (metadataValue) { +// return new DataProviderUpload(new QueryConstructorUpload('http://127.0.0.1:8888', metadataValue)); +// }); +// +// window.providerRegister.register('DocumentDataSource', function () { +// return new FakeDataProvider(); +// }); +// +// $('body').append($('
').attr('id', 'page-content')); +// +// var metadata = { +// Text: 'Пациенты', +// DataSources: [ +// { +// DocumentDataSource: { +// Name : "PatientDataSource", +// ConfigId: 'Demography', +// DocumentId: 'Patient', +// IdProperty: 'Id', +// CreateAction: 'CreateDocument', +// GetAction: 'GetDocument', +// UpdateAction: 'SetDocument', +// DeleteAction: 'DeleteDocument', +// FillCreatedItem: true +// } +// } +// ], +// LayoutPanel: { +// StackPanel: { +// Name: 'MainViewPanel', +// Items: [ +// { +// ImageBox: { +// Name: 'ImageBox1', +// Value : { +// FileBinding : { +// DataSource : 'PatientDataSource', +// Property : '$.photo' +// } +// } +// } +// } +// ] +// } +// } +// }; +// +// var linkView = new InfinniUI.LinkView(null, function (resultCallback) { +// var builder = new InfinniUI.ApplicationBuilder(); +// var view = builder.buildType(fakeView(), 'View', metadata); +// resultCallback(view); +// }); +// linkView.setOpenMode('Application'); +// +// linkView.createView(function(view){ +// view.open(); +// +// var itemToSelect = null; +// view.getDataSource('PatientDataSource').getItems(function(data){ +// itemToSelect = data[1]; +// }); +// +// view.getDataSource('PatientDataSource').setSelectedItem(itemToSelect); +// +// +// window.maindatasource = view.getDataSource('PatientDataSource'); +// +// //check text +// // assert.equal($('#page-content').find('input:text').val(), itemToSelect.LastName); +// // $('#page-content').remove(); +// }); +// }); +// }); + + +}); + +describe('Label', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + describe('API', function () { + var element = builder.buildType('Label', {}); + + describe('Implementing Label Methods', function () { + ['getDisplayFormat', 'setDisplayFormat', 'getTextTrimming', 'setTextTrimming', + 'getTextWrapping', 'setTextWrapping'] + .forEach(function (methodName) { + it(methodName, function () { + testHelper.checkMethod(element, methodName); + }); + + }); + }); + + describe('Implementing EditorBase Methods', function () { + testHelper.checkEditorBaseMethods(element); + }); + + describe('Implementing Element Methods', function () { + testHelper.checkElementMethods(element); + }); + }); + + describe('Metadata', function () { + + it('Using default value', function () { + var metadata = { + "Label": {} + }; + + var element = builder.build(metadata, {}); + + //assert.equal(element.getTextTrimming(), true, 'TextTrimming'); + assert.equal(element.getTextWrapping(), true, 'TextWrapping'); + + assert.equal(element.getVisible(), true, 'Visible'); + assert.equal(element.getVerticalAlignment(), 'Top', 'VerticalAlignment'); + assert.equal(element.getHorizontalAlignment(), 'Stretch', 'HorizontalAlignment'); + var displayFormat = element.getDisplayFormat(); + var value = {}; + assert.isTrue(displayFormat(null, {value: value}) === value, 'DisplayFormat'); + }); + + it('Apply metadata', function () { + var metadata = { + "Label": { + "TextWrapping": false, + + "Text": "Label", + "LabelFloating": true, + "DisplayFormat": "d", + "HintText": "Hint", + "ErrorText": "Error", + "WarningText": "Warning", + + "Name": "Label1", + "Enabled": false, + "Visible": false, + "VerticalAlignment": "Bottom", + "HorizontalAlignment": "Right", + "TextStyle": "Display4", + "Foreground": "Primary1", + "Background": "Accent1" + } + }; + + var element = builder.build(metadata, {}); + + assert.equal(element.getTextWrapping(), false, 'TextWrapping'); + assert.isFunction(element.getDisplayFormat(), 'DisplayFormat'); + + assert.equal(element.getHintText(), "Hint", 'HintText'); + assert.equal(element.getErrorText(), "Error", 'ErrorText'); + assert.equal(element.getWarningText(), "Warning", 'WarningText'); + + assert.equal(element.getName(), "Label1", 'Name'); + assert.equal(element.getText(), "Label", 'LabelText'); + assert.equal(element.getEnabled(), false, 'Enabled'); + assert.equal(element.getVisible(), false, 'Visible'); + assert.equal(element.getVerticalAlignment(), 'Bottom', 'VerticalAlignment'); + assert.equal(element.getTextStyle(), 'Display4', 'TextStyle'); + assert.equal(element.getForeground(), 'Primary1', 'Foreground'); + assert.equal(element.getBackground(), 'Accent1', 'Background'); + + }); + + it('event OnValueChanged', function () { + // Given + var label = new InfinniUI.Label(), + onValueChangedFlag = 0; + + label.render(); + + label.onValueChanged(function () { + onValueChangedFlag++; + }); + + assert.equal(onValueChangedFlag, 0); + + // When + label.setValue('2014-07-29'); + label.setValue('2014-07-30'); + + // Then + assert.equal(onValueChangedFlag, 2); + }); + + }); +}); + +describe('LabelBuilder', function () { + describe('build', function () { + it('successful build Label', function () { + // Given + + var metadata = {}; + + // When + var builder = new InfinniUI.LabelBuilder(); + var element = builder.build(null, {builder: new InfinniUI.ApplicationBuilder(), view: new InfinniUI.View(), metadata: metadata}); + + // Then + assert.isNotNull(element); + assert.isObject(element); + }); + + it('dataBinding should update display value', function () { + // Given + + var metadata = { + "DataSources": [ + { + "ObjectDataSource": { + "Name": "ObjectDataSource", + "IsLazy": false, + "Items": [] + } + } + ], + "Items": [{ + Label: { + Name: "Label1", + DisplayFormat: "некоторый текст {property}", + Value: { + Source: "ObjectDataSource", + Property: "$" + } + } + }] + }; + + testHelper.applyViewMetadata(metadata, function(view){ + var label = view.context.controls["Label1"]; + var ds = view.context.dataSources["ObjectDataSource"]; + + ds.createItem(); + + var item = ds.getSelectedItem(); + item.property = "123"; + ds.setProperty("$", { property: "123" }); + + assert.equal(label.getDisplayValue(), "некоторый текст 123"); + assert.equal(label.control.controlView.$el.html(), "некоторый текст 123"); + + view.close(); + }); + }); + + it('dataBinding should update display value - 2', function () { + // Given + + var metadata = { + "DataSources": [ + { + "ObjectDataSource": { + "Name": "ObjectDataSource", + "IsLazy": false, + "Items": [{ + property: "old" + }] + } + } + ], + "Items": [{ + Label: { + Name: "Label1", + DisplayFormat: "некоторый текст {property}", + Value: { + Source: "ObjectDataSource", + Property: "$" + } + } + }] + }; + + testHelper.applyViewMetadata(metadata, function(view){ + var label = view.context.controls["Label1"]; + var ds = view.context.dataSources["ObjectDataSource"]; + + ds.setProperty("$", { property: "new" }); + + assert.equal(label.getDisplayValue(), "некоторый текст new"); + assert.equal(label.control.controlView.$el.html(), "некоторый текст new"); + + view.close(); + }); + }); + }); +}); + +describe('ListBox', function () { + + describe('render', function () { + + it('should render listBox with grouping', function () { + // Given + + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "LTE", "Type": 1 }, + { "Id": 2, "Display": "A", "Type": 2 }, + { "Id": 3, "Display": "3G", "Type": 1 }, + { "Id": 4, "Display": "01", "Type": 3 }, + { "Id": 5, "Display": "2G", "Type": 1 }, + { "Id": 6, "Display": "02", "Type": 3 }, + { "Id": 7, "Display": "03", "Type": 3 }, + { "Id": 8, "Display": "B", "Type": 2 } + ] + } + } + ], + Items: [{ + + ListBox: { + "ItemProperty": "Display", + "GroupItemProperty": "Type", + "GroupValueProperty": "Type", + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + } + } + }] + }; + + // When + testHelper.applyViewMetadata(metadata, onListboxReady); + + // Then + function onListboxReady(view, $view){ + var titles = $view.find('.pl-listbox-group-title .pl-label') + .map(function(i, item){return $(item).text()}) + .toArray(); + + assert.sameMembers(titles, ['1', '2', '3'], 'incorrect titles'); + + var firstGroup = $view.find('.pl-listbox-group-i:nth-child(1) .pl-listbox-group-body .pl-label') + .map(function(i, item){return $(item).text()}) + .toArray(); + + assert.sameMembers(firstGroup, ['LTE', '2G', '3G'], 'incorrect first group'); + + var secondGroup = $view.find('.pl-listbox-group-i:nth-child(2) .pl-listbox-group-body .pl-label') + .map(function(i, item){return $(item).text()}) + .toArray(); + + assert.sameMembers(secondGroup, ['A', 'B'], 'incorrect second group'); + + var thirdGroup = $view.find('.pl-listbox-group-i:nth-child(3) .pl-listbox-group-body .pl-label') + .map(function(i, item){return $(item).text()}) + .toArray(); + + assert.sameMembers(thirdGroup, ['01', '02', '03'], 'incorrect third group'); + + view.close(); + } + }); + + it('should render listBox without grouping', function () { + // Given + + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "LTE" }, + { "Id": 2, "Display": "3G" }, + { "Id": 3, "Display": "2G" } + ] + } + } + ], + Items: [{ + + ListBox: { + "ItemTemplate": { + "Label": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + } + } + }] + }; + + // When + + testHelper.applyViewMetadata(metadata, onListboxReady); + + // Then + function onListboxReady(view, $view){ + var items = $view.find('.pl-listbox-body .pl-label') + .map(function(i, item){return $(item).text()}) + .toArray(); + + assert.sameMembers(items, ['LTE', '3G', '2G']); + + view.close(); + } + }); + + }); + + describe('api', function () { + it('should update DisabledItemCondition', function () { + // Given + var metadata = { + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "LTE" }, + { "Id": 2, "Display": "3G" }, + { "Id": 3, "Display": "2G" } + ] + } + } + ], + Items: [{ + ListBox: { + "Name": "ListBox1", + "DisabledItemCondition": "{ return (args.value.Id == 2); }", + "ViewMode": "base", + "MultiSelect": true, + "ItemTemplate": { + "Label": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "#.Display" + } + } + }, + "Items" : { + "Source": "ObjectDataSource1", + "Property": "" + } + } + }] + }; + + + testHelper.applyViewMetadata(metadata, onViewReady); + + + function onViewReady(view, $view) { + var listbox = view.context.controls['ListBox1']; + var items = $view.find('.pl-listbox-i'); + + assert.isFalse(items.eq(0).hasClass('pl-disabled-list-item'), 'bad render for enabled item'); + assert.isTrue(items.eq(1).hasClass('pl-disabled-list-item'), 'bad render for disabled item'); + + // When + listbox.setDisabledItemCondition( function (context, args) { + return args.value.Id == 1; + }); + + // Then + assert.isTrue(items.eq(0).hasClass('pl-disabled-list-item'), 'items not updated'); + assert.isFalse(items.eq(1).hasClass('pl-disabled-list-item'), 'items not updated'); + view.close(); + } + }); + }); + +}); +describe('ListEditorBase', function () { + + describe('ListBox as exemplar of ListEditorBase', function (){ + + it('should apply value to control (single selecting mode)', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + {"Id": 1, "Display": "LTE"}, + {"Id": 2, "Display": "2G"}, + {"Id": 3, "Display": "2G"} + ] + } + },{ + ObjectDataSource: { + "Name": "ObjectDataSource2", + "Items": [ + { "Value": { "Id": 2, "Display": "2G" }} + ] + } + } + ], + Items: [{ + + ListBox: { + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "$.Display" + } + } + }, + "Items": { + "Source": "ObjectDataSource1", + "Property": "" + }, + "Value": { + "Source": "ObjectDataSource2", + "Property": "$.Value" + } + } + }] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + var $items = $layout.find('.pl-listbox-i'), + $chosen = $layout.find('.pl-listbox-i.pl-listbox-i-chosen'); + + assert.lengthOf($chosen, 1, 'length of chosen item is right'); + assert.equal($items.index($chosen), 1, 'index of chosen item is right'); + + view.close(); + } + }); + + + it('should apply value to control (multiply selecting mode)', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + {"Id": 1, "Display": "LTE"}, + {"Id": 2, "Display": "2G"}, + {"Id": 3, "Display": "2G"} + ] + } + },{ + ObjectDataSource: { + "Name": "ObjectDataSource2", + "Items": [ + { "Value": [ + { "Id": 2, "Display": "2G" }, + { "Id": 3, "Display": "2G" } + ]} + ] + } + } + ], + Items: [{ + + ListBox: { + "MultiSelect": true, + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "$.Display" + } + } + }, + "Items": { + "Source": "ObjectDataSource1", + "Property": "" + }, + "Value": { + "Source": "ObjectDataSource2", + "Property": "$.Value" + } + } + }] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + var $items = $layout.find('.pl-listbox-i'), + $chosen = $layout.find('.pl-listbox-i.pl-listbox-i-chosen'); + + assert.lengthOf($chosen, 2, 'length of chosen item is right'); + assert.equal($items.index($chosen.eq(0)), 1, 'index of first chosen item is right'); + assert.equal($items.index($chosen.eq(1)), 2, 'index of second chosen item is right'); + + view.close(); + } + }); + + it('should apply value from control (single selecting)', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + {"Id": 1, "Display": "LTE"}, + {"Id": 2, "Display": "2G"}, + {"Id": 3, "Display": "2G"} + ] + } + },{ + ObjectDataSource: { + "Name": "ObjectDataSource2", + "Items": [ + { "Value": null} + ] + } + } + ], + Items: [{ + + ListBox: { + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "$.Display" + } + } + }, + "Items": { + "Source": "ObjectDataSource1", + "Property": "" + }, + "Value": { + "Source": "ObjectDataSource2", + "Property": "$.Value" + } + } + }] + }; + + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + function onViewReady(view, $layout){ + $layout.detach(); + + + var $items = $layout.find('.pl-listbox-i'), + $chosen = $layout.find('.pl-listbox-i.pl-listbox-i-chosen'); + + // Then + assert.lengthOf($chosen, 0, 'length of chosen item is right'); + + // When + $items.first().find('.pl-listbox-input input').prop('checked', true).change(); + $chosen = $layout.find('.pl-listbox-i.pl-listbox-i-chosen'); + + // Then + assert.lengthOf($chosen, 1, 'length of chosen item is right'); + assert.equal($items.index($chosen.eq(0)), 0, 'index of first chosen item is right'); + + view.close(); + } + }); + + it('should apply value from control (multiply selecting)', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + {"Id": 1, "Display": "LTE"}, + {"Id": 2, "Display": "2G"}, + {"Id": 3, "Display": "2G"} + ] + } + },{ + ObjectDataSource: { + "Name": "ObjectDataSource2", + "Items": [ + { "Value": [{"Id": 2, "Display": "2G"}]} + ] + } + } + ], + Items: [{ + + ListBox: { + "MultiSelect": true, + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "$.Display" + } + } + }, + "Items": { + "Source": "ObjectDataSource1", + "Property": "" + }, + "Value": { + "Source": "ObjectDataSource2", + "Property": "$.Value" + } + } + }] + }; + + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + function onViewReady(view, $layout){ + $layout.detach(); + + var $items = $layout.find('.pl-listbox-i'), + $chosen = $layout.find('.pl-listbox-i.pl-listbox-i-chosen'), + value = view.getContext().dataSources['ObjectDataSource2'].getSelectedItem().Value; + + // Then + assert.lengthOf($chosen, 1, 'length of chosen item is right'); + assert.equal($items.index($chosen.eq(0)), 1, 'index of chosen item is right'); + assert.lengthOf(value, 1, 'length value in DS is right'); + assert.equal(value[0].Id, 2, 'value in DS is right'); + + // When + $items.first().find('.pl-listbox-input input').prop('checked', true).change(); + $chosen = $layout.find('.pl-listbox-i.pl-listbox-i-chosen'); + value = view.getContext().dataSources['ObjectDataSource2'].getSelectedItem().Value; + + assert.lengthOf($chosen, 2, 'length of chosen item is right'); + assert.equal($items.index($chosen.eq(0)), 0, 'index of first chosen item is right'); + assert.equal($items.index($chosen.eq(1)), 1, 'index of second chosen item is right'); + + assert.lengthOf(value, 2, 'length value in DS is right'); + assert.equal(value[0].Id, 1, 'first value in DS is right'); + assert.equal(value[1].Id, 2, 'second value in DS is right'); + + view.close(); + } + }); + + it('should bind selectedItem and value', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + {"Id": 1, "Display": "LTE"}, + {"Id": 2, "Display": "2G"}, + {"Id": 3, "Display": "2G"} + ] + } + },{ + ObjectDataSource: { + "Name": "ObjectDataSource2", + "Items": [ + { "Value": {"Id": 2, "Display": "2G"}} + ] + } + } + ], + Items: [{ + + ListBox: { + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "$.Display" + } + } + }, + "Items": { + "Source": "ObjectDataSource1", + "Property": "" + }, + "Value": { + "Source": "ObjectDataSource2", + "Property": "$.Value" + } + } + }] + }; + + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + function onViewReady(view, $layout){ + //$layout.detach(); + + var $items = $layout.find('.pl-listbox-i'), + $chosen = $layout.find('.pl-listbox-i.pl-listbox-i-chosen'), + $selected = $layout.find('.pl-listbox-i.pl-listbox-i-selected'), + ds = view.getContext().dataSources['ObjectDataSource1'], + ds2 = view.getContext().dataSources['ObjectDataSource2'], + selectedItem = ds.getSelectedItem(), + items = ds.getItems(); + + // Then + assert.lengthOf($chosen, 1, 'length of chosen item is right'); + assert.lengthOf($selected, 0, 'length of selected item is right'); + assert.isNull(selectedItem, 'value in DS is right'); + assert.equal(ds2.getProperty('Value.Id'), 2, 'selected item in DS is right'); + + // When + $items.last().find('.pl-listbox-input input').prop('checked', true).change(); + $chosen = $layout.find('.pl-listbox-i.pl-listbox-i-chosen'); + $selected = $layout.find('.pl-listbox-i.pl-listbox-i-selected'); + selectedItem = ds.getSelectedItem(); + + // Then + assert.lengthOf($chosen, 1, 'length of chosen item is right (after changing)'); + assert.lengthOf($selected, 0, 'length of selected item is right (after changing)'); + assert.equal(ds2.getProperty('Value.Id'), 3, 'selected item in DS is right (after changing)'); + + // When + ds.setSelectedItem(items[0]); + $chosen = $layout.find('.pl-listbox-i.pl-listbox-i-chosen'); + $selected = $layout.find('.pl-listbox-i.pl-listbox-i-selected'); + selectedItem = ds.getSelectedItem(); + + // Then + assert.lengthOf($chosen, 1, 'length of chosen item is right (after 2 changing)'); + assert.lengthOf($selected, 1, 'length of selected item is right (after 2 changing)'); + assert.equal(selectedItem.Id, 1, 'value in DS is right (after 2 changing)'); + assert.equal(ds2.getProperty('Value.Id'), 3, 'selected item in DS is right (after 2 changing)'); + + view.close(); + } + }); + + it('should set value by passed items', function () { + // Given + var metadata = { + Text: 'Пациенты', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + {"Id": 1, "Display": "LTE"}, + {"Id": 2, "Display": "2G"}, + {"Id": 3, "Display": "2G"} + ] + } + },{ + ObjectDataSource: { + "Name": "ObjectDataSource2", + "Items": [ + { "Value": 2 } + ] + } + } + ], + Items: [{ + + ListBox: { + "Name": "LB", + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "$.Display" + } + } + }, + "Items": { + "Source": "ObjectDataSource1", + "Property": "" + }, + "Value": { + "Source": "ObjectDataSource2", + "Property": "$.Value" + }, + "ValueProperty": "Id" + } + }] + }; + + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + function onViewReady(view, $layout){ + + var listBox = view.getContext().controls['LB']; + var firstItem = listBox.getItems().getByIndex(0); + var value = listBox.getValue(); + assert.equal(value, 2, 'first value in listbox is right'); + + // When + listBox.setValueItem(firstItem); + + // Then + var value = listBox.getValue(); + assert.equal(value, 1, 'setValueItem set value right'); + + view.close(); + } + }); + + it('should use items from parameter', function () { + // Given + var metadata = { + Text: 'Пациенты', + Parameters: [{ + "Name": "Parameter1" + }], + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + {"Id": 1, "Display": "LTE"}, + {"Id": 2, "Display": "2G"}, + {"Id": 3, "Display": "2G"} + ] + } + },{ + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Value": { "Id": 2, "Display": "2G" }} + ] + } + } + ], + "OnLoaded": '{context.parameters.Parameter1.setValue([{"Id": 1, "Display": "LTE"}, {"Id": 2, "Display": "2G"}, {"Id": 3, "Display": "2G"}]);}', + Items: [{ + + ListBox: { + "ItemTemplate": { + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "Parameter1", + "Property": "#.Display" + } + } + }, + "Items": { + "Source": "Parameter1", + "Property": "" + }, + "Value": { + "Source": "ObjectDataSource1", + "Property": "$.Value" + } + } + }] + }; + + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $view){ + assert.equal($view.find('.pl-listbox-i').length, 3); + + view.close(); + } + }); + }); + + +}); +describe('NumericBox', function () { + describe('render', function () { + it('Setting the properties: value, name, enabled, visible, horizontalAlignment', function () { + // Given + var numericBox = new InfinniUI.NumericBox(), + $el, $control; + + // When + $el = numericBox.render(); + $control = $el.find('input'); + + // Then + assert.equal($control.val(), 0); + assert.isUndefined($el.attr('data-pl-name')); + assert.isFalse($control.prop('disabled')); + assert.isFalse($el.hasClass('hidden')); + assert.isFalse($el.hasClass('pl-horizontal-Left')); + assert.isFalse($el.hasClass('center-block')); + }); + + it('Change the properties: value, name, enabled, visible, horizontalAlignment', function () { + // Given + var numericBox = new InfinniUI.NumericBox(), + $el, $control; + var numericBox1 = new InfinniUI.NumericBox(), + $el1, $control1; + var numericBox2 = new InfinniUI.NumericBox(), + $el2, $control2; + + // When + $el = numericBox.render(); + $control = $el.find('input'); + numericBox1.render(); + numericBox2.render(); + + numericBox.setValue(15); + numericBox.setMinValue(10); + numericBox.setMaxValue(50); + numericBox.setIncrement(5); + numericBox.setName('newName'); + numericBox.setEnabled(false); + numericBox.setVisible(false); + numericBox.setHorizontalAlignment('Center'); + + numericBox1.setMaxValue(20); + numericBox1.setValue(50); + numericBox2.setMinValue(20); + numericBox2.setValue(5); + + // Then + assert.equal(numericBox1.getValue(), 50); + assert.equal(numericBox2.getValue(), 5); + + assert.equal(numericBox.getValue(), 15); + assert.equal(numericBox.getMinValue(), 10); + assert.equal(numericBox.getMaxValue(), 50); + assert.equal(numericBox.getIncrement(), 5); + assert.equal($el.attr('data-pl-name'), 'newName'); + assert.isTrue($control.prop('disabled')); + assert.isTrue($el.hasClass('hidden')); + assert.isFalse($el.hasClass('pl-horizontal-Left')); + assert.isTrue($el.hasClass('pl-horizontal-Center')); + }); + + it('Events onLoad, onValueChanged', function () { + // Given + var numericBox = new InfinniUI.NumericBox(), + onLoadFlag = 0, + onValueChanged = 0; + + numericBox.onLoaded(function () { + onLoadFlag++; + }); + numericBox.onValueChanged(function () { + onValueChanged++; + }); + + assert.equal(onLoadFlag, 0); + assert.equal(onValueChanged, 0); + + // When + numericBox.render(); + numericBox.setValue(1); + + // Then + assert.equal(onLoadFlag, 1); + assert.equal(onValueChanged, 1); + }); + + it('should be triggered events: OnValueChanged, OnLoaded', function () { + //Given + var builder = new InfinniUI.ApplicationBuilder(); + var view = new InfinniUI.View(); + var metadata = { + "NumericBox": { + OnValueChanged:{ + Name: 'OnValueChanged' + }, + OnLoaded:{ + Name: 'OnLoaded' + } + } + }; + var scripts = view.getScripts(); + var events = { + OnValueChanged: 0, + OnLoaded: 0 + }; + + scripts.add({ + name: "OnValueChanged", + func: function () { + events.OnValueChanged++; + } + }); + + scripts.add({ + name: "OnLoaded", + func: function () { + events.OnLoaded++; + } + }); + + //When + var element = builder.build(metadata, {parentView: view, parent: view, builder: builder}); + element.setValue(true); + element.render(); + + // Then + assert.equal(events.OnValueChanged, 1, 'OnValueChanged'); + assert.equal(events.OnLoaded, 1, 'OnLoaded'); + }); + }); +}); + +describe('PanelElement', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + describe('API', function () { + var element = builder.buildType('Panel', {}); + + describe('Implementing Panel API', function () { + it('Implement methods', function () { + testHelper.checkMethod(element, 'getCollapsible'); + testHelper.checkMethod(element, 'setCollapsible'); + testHelper.checkMethod(element, 'getCollapsed'); + testHelper.checkMethod(element, 'setCollapsed'); + testHelper.checkMethod(element, 'getHeaderTemplate'); + testHelper.checkMethod(element, 'setHeaderTemplate'); + testHelper.checkMethod(element, 'getHeader'); + testHelper.checkMethod(element, 'setHeader'); + }); + + it('Implement events subscriber', function () { + testHelper.checkMethod(element, 'onExpanding'); + testHelper.checkMethod(element, 'onExpanded'); + testHelper.checkMethod(element, 'onCollapsing'); + testHelper.checkMethod(element, 'onCollapsed'); + }); + + }); + + describe('Implementing Container Methods', function () { + testHelper.checkContainerMethods(element) + }); + + describe('Implementing Element Methods', function () { + testHelper.checkElementMethods(element) + }); + + it('Default values', function () { + var element = builder.buildType('Panel', {}); + + assert.equal(element.getCollapsible(), false, 'Collapsible'); + assert.equal(element.getCollapsed(), false, 'Collapsed'); + assert.isFunction(element.getHeaderTemplate, 'HeaderTemplate by default'); + }); + + }); + + + describe('Panel events handler', function () { + + function bindEvents(element) { + var events = []; + element.onCollapsed(function () { + events.push('onCollapsed'); + }); + + element.onCollapsing(function () { + events.push('onCollapsing'); + }); + + element.onExpanded(function () { + events.push('onExpanded'); + }); + + element.onExpanding(function () { + events.push('onExpanding'); + }); + + return events; + } + + function createPanel() { + return builder.buildType('Panel', {}); + } + + it('Should fire onCollapsing on setCollapsed(true)', function () { + //Given + var element = createPanel(); + var events = bindEvents(element); + //When + element.setCollapsed(true); + + //Then + assert.lengthOf(events, 2); + assert.equal(events[0], 'onCollapsing', 'onCollapsing'); + assert.equal(events[1], 'onCollapsed', 'onCollapsed'); + assert.equal(element.getCollapsed(), true); + }); + + it('Should fire onExpanding on setCollapsed(false)', function () { + //Given + var element = createPanel(); + element.setCollapsed(true); + var events = bindEvents(element); + //When + element.setCollapsed(false); + + //Then + assert.lengthOf(events, 2); + assert.equal(events[0], 'onExpanding', 'onExpanding'); + assert.equal(events[1], 'onExpanded', 'onExpanded'); + assert.equal(element.getCollapsed(), false); + }); + + it('Should cancel setCollapsed(true) when one of onCollapsing returns false', function () { + //Given + var element = createPanel(); + var events = bindEvents(element); + element.onCollapsing(function () { + events.push('onCollapsing'); + return false; + }); + + //When + element.setCollapsed(true); + + //Then + assert.lengthOf(events, 2); + assert.equal(events[0], 'onCollapsing', 'onCollapsing'); + assert.equal(events[1], 'onCollapsing', 'onCollapsing'); + assert.equal(element.getCollapsed(), false); + }); + + it('Should cancel setCollapsed(false) when one of onExpanding returns false', function () { + //Given + var element = createPanel(); + element.setCollapsed(true); + var events = bindEvents(element); + + element.onExpanding(function () { + events.push('onExpanding'); + return false; + }); + + //When + element.setCollapsed(false); + + //Then + assert.lengthOf(events, 2); + assert.equal(events[0], 'onExpanding', 'onExpanding'); + assert.equal(events[1], 'onExpanding', 'onExpanding'); + assert.equal(element.getCollapsed(), true); + }); + + + }); + +}); + +describe('PanelBuilder', function () { + it('should build', function () { + + //Given + var metadata = { + Panel: { + Text: 'panel', + Items: [ + { + TextBox: { + Name: 'text' + } + } + ] + } + }; + + var builder = new InfinniUI.ApplicationBuilder(); + var panel = builder.build(metadata, {parentView: fakeView()}); + + //When + assert.equal(panel.getText(), 'panel'); + }); + +}); + +describe('PasswordBox', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + describe('API', function () { + var element = builder.buildType('PasswordBox', {}); + + describe('Implementing PasswordBox Methods', function () { + [ + 'getLabelText', + 'setLabelText', + 'getLabelFloating', + 'setLabelFloating' + ].forEach(function (methodName) { + it(methodName, function () { + testHelper.checkMethod(element, methodName); + }); + + }); + }); + + describe('Implementing EditorBase Methods', function () { + testHelper.checkEditorBaseMethods(element); + }); + + describe('Implementing Element Methods', function () { + testHelper.checkElementMethods(element); + }); + }); + + describe('Metadata', function () { + + it('Using default value', function () { + var metadata = { + "PasswordBox": {} + }; + + var element = builder.build(metadata, {}); + assert.equal(element.getLabelFloating(), false, 'LabelFloating'); + }); + + it('Apply metadata', function () { + var metadata = { + "PasswordBox": { + "LabelText": "Label", + "LabelFloating": true + } + }; + + var element = builder.build(metadata, {}); + + assert.equal(element.getLabelText(), "Label", 'LabelText'); + assert.equal(element.getLabelFloating(), true, 'LabelFloating'); + }); + + it('event OnValueChanged', function () { + // Given + var element = new InfinniUI.PasswordBox(), + onValueChangedFlag = 0; + + element.render(); + + element.onValueChanged(function () { + onValueChangedFlag++; + }); + + assert.equal(onValueChangedFlag, 0); + + // When + element.setValue('P@$$w0rd'); + element.setValue('password'); + + // Then + assert.equal(onValueChangedFlag, 2); + }); + + it('event OnGotFocus/OnLostFocus', function () { + // Given + var element = new InfinniUI.PasswordBox(), + onFocusedFlag = 0; + + element.render(); + + element.onGotFocus(function () { + onFocusedFlag++; + }); + + element.onLostFocus(function () { + onFocusedFlag--; + }); + + assert.equal(onFocusedFlag, 0); + + // When + element.control.set('focused', true); + // Then + assert.isTrue(element.getFocused()); + assert.equal(onFocusedFlag, 1); + element.control.set('focused', false); + assert.isFalse(element.getFocused()); + assert.equal(onFocusedFlag, 0); + }); + + }); +}); + +describe('PasswordBoxBuilder', function () { + describe('build', function () { + it('successful build PasswordBox', function () { + // Given + + var metadata = {}; + + // When + var builder = new InfinniUI.LabelBuilder(); + var element = builder.build(null, {builder: new InfinniUI.ApplicationBuilder(), view: new InfinniUI.View(), metadata: metadata}); + + // Then + assert.isNotNull(element); + assert.isObject(element); + }); + }); +}); + +describe('PopupButtonElement', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + describe('API', function () { + var element = builder.buildType('PopupButton', { + Items: [] + }); + + describe('Implementing Element Methods', function () { + testHelper.checkElementMethods(element); + }); + + describe('Implementing Container Methods', function () { + testHelper.checkContainerMethods(element); + }); + + + }); + + describe('Checking methods', function () { + var button; + + beforeEach(function () { + button = builder.buildType('PopupButton', { + Items: [] + }); + }); + + it('should create', function () { + // Given + + + // When + var $el = button.render(); + + // Then + assert.equal($el.find('.pl-popup-button__button').length, 1); + }); + + it('should set text', function () { + // Given + button.setText('button'); + var $el = button.render(); + + // When + button.setText('other button'); + + // Then + assert.equal($el.find('.pl-popup-button__button').text(), 'other button'); + //window. + }); + + + it('should execute action on click', function (done) { + // Given + var button = new InfinniUI.PopupButton(), + onLastActionExecute = 0, + onNewActionExecute = 0; + + button.setAction(new function(){ + this.execute = function () { + onLastActionExecute++; + }; + }); + + button.setAction(new function(){ + this.execute = function () { + onNewActionExecute++; + assert.equal(onLastActionExecute, 0); + assert.equal(onNewActionExecute, 1); + done(); + }; + }); + + assert.equal(onLastActionExecute, 0); + assert.equal(onNewActionExecute, 0); + + // When + button.render(); + button.click(); + + // Then + $('body').find('.pl-popup-button__dropdown').detach(); + }); + + it('event onClick', function () { + // Given + var button = new InfinniUI.PopupButton(), + onClickFlag = 0; + + button.onClick(function(){ + onClickFlag++; + }); + + assert.equal(onClickFlag, 0); + + // When + button.render(); + button.click(); + + // Then + assert.equal(onClickFlag, 1); + $('body').find('.pl-popup-button__dropdown').detach(); + }); + + it('should save click handler after set new action', function () { + // Given + var button = new InfinniUI.PopupButton(), + onClickFlag = 0; + + button.onClick(function(){ + onClickFlag++; + }); + + assert.equal(onClickFlag, 0); + + // When + button.render(); + button.click(); + + var action = new InfinniUI.BaseAction(); + var execActionFlag=0; + action.execute = function(){ + execActionFlag++; + }; + + button.setAction(action); + + button.click(); + // Then + assert.equal(execActionFlag, 1); + assert.equal(onClickFlag, 2); + $('body').find('.pl-popup-button__dropdown').detach(); + + }); + + it('should add items', function () { + // Given + //var button = new InfinniUI.PopupButton(); + + // When + var items = button.getItems(); + items.add(builder.buildType('Button', {})); + items.add(builder.buildType('Button', {})); + + // Then + assert.equal(2,button.getItems().length); + }); + + it('should remove item', function () { + // Given + var button = new InfinniUI.PopupButton(); + var b1 = builder.buildType('Button', {}); + var b2 = builder.buildType('Button', {}); + var items = button.getItems(); + items.add(b1); + items.add(b2); + + // When + items.remove(b1); + + // Then + assert.equal(1,button.getItems().length); + }); + }); +}); + +describe('PopupButtonBuilder', function () { + describe('build', function () { + it('successful build', function () { + // Given + + var metadata = { + Text: "Click me", + Action: { + OpenAction: { + LinkView: { + AutoView: {} + } + } + }, + OnClick:{ + Name:"A" + }, + Items: [ + { + Button: { + Text: "Click me", + Visible: true, + HorizontalAlignment: 'Left', + Action: { + + } + } + }, + { + Button: { + Text: "Административная информация", + Visible: true, + Action: { + + } + } + } + ] + + }; + + // When + var builder = new InfinniUI.PopupButtonBuilder(); + var button = builder.build(null, {builder: new InfinniUI.ApplicationBuilder(), metadata: metadata, parentView: new InfinniUI.View()}); + // Then + assert.isNotNull(button); + assert.equal(button.getText(), 'Click me'); + assert.equal(2,button.getItems().length); + + }); + }); +}); + +describe('ScrollPanelElement', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + describe('API', function () { + + it('implements API methods', function () { + var element = builder.buildType('ScrollPanel', {}); + + assert.isFunction(element.getHorizontalScroll, 'getHorizontalScroll'); + assert.isFunction(element.setHorizontalScroll, 'setHorizontalScroll'); + assert.isFunction(element.getVerticalScroll, 'getVerticalScroll'); + assert.isFunction(element.setVerticalScroll, 'setVerticalScroll'); + }); + + + it('Default values', function () { + var element = builder.buildType('ScrollPanel', {}); + + assert.equal(element.getHorizontalScroll(), InfinniUI.ScrollVisibility.auto, 'getHorizontalScroll'); + assert.equal(element.getVerticalScroll(), InfinniUI.ScrollVisibility.auto, 'getVerticalScroll'); + }); + + + }); + + +}); + +describe('ScrollPanelBuilder', function () { + it('should build', function () { + + //Given + var metadata = { + ScrollPanel: { + Items: [] + } + }; + + var applicationBuilder = new InfinniUI.ApplicationBuilder(); + + //When + var scrollPanel = applicationBuilder.build(metadata, {}); + + //Then + assert.isObject(scrollPanel, 'scrollPanel'); + }); + +}); + +describe('TabPanelElement', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + describe('API', function () { + + it('Default values', function () { + var element = builder.buildType('TabPanel', {}); + + assert.equal(element.getHeaderLocation(), InfinniUI.TabHeaderLocation.top, 'HeaderLocation'); + assert.equal(element.getHeaderOrientation(), InfinniUI.TabHeaderOrientation.horizontal, 'HeaderOrientation'); + }); + + + }); + + +}); + +describe('TabPanelBuilder', function () { + it('should build', function () { + + //Given + var metadata = { + TabPanel: { + Items: [] + } + }; + + var applicationBuilder = new InfinniUI.ApplicationBuilder(); + + //When + var element = applicationBuilder.build(metadata, {}); + + //Then + assert.isObject(element, 'TabPanel'); + }); + +}); + +describe('TextBox', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + describe('API', function () { + var element = builder.buildType('TextBox', {}); + + describe('Implementing TextBox Methods', function () { + ['getMultiline', 'setMultiline', 'getLineCount', 'setLineCount'] + .forEach(function (methodName) { + it(methodName, function() { + testHelper.checkMethod(element, methodName); + }); + + }); + }); + + describe('Implementing TextEditorBase Methods', function () { + testHelper.checkTextEditorBaseMethods(element); + }); + + describe('Implementing EditorBase Methods', function () { + testHelper.checkEditorBaseMethods(element); + }); + + describe('Implementing Element Methods', function () { + testHelper.checkElementMethods(element); + }); + + it('Events onLoad, onValueChanged', function () { + // Given + var textBox = new InfinniUI.TextBox(), + onLoadFlag = 0, + onValueChanged = 0; + + textBox.onLoaded(function(){ + onLoadFlag++; + }); + textBox.onValueChanged(function(){ + onValueChanged++; + }); + + assert.equal(onLoadFlag, 0); + assert.equal(onValueChanged, 0); + + // When + textBox.render(); + textBox.setValue('new'); + + // Then + assert.equal(onLoadFlag, 1); + assert.equal(onValueChanged, 1); + }); + + it('should be true if scriptsHandlers call', function () { + //Given + var builder = new InfinniUI.ApplicationBuilder(); + var view = new InfinniUI.View(); + var metadata = { + "TextBox": { + OnValueChanged:{ + Name: 'OnValueChanged' + }, + OnLoaded:{ + Name: 'OnLoaded' + } + } + }; + var events = { + OnValueChanged: 0, + OnLoaded: 0 + }; + var scripts = view.getScripts(); + scripts.add({ + name: 'OnValueChanged', + func: function () { + events.OnValueChanged++; + } + }); + scripts.add({ + name: 'OnLoaded', + func: function () { + events.OnLoaded++; + } + }); + + //When + var element = builder.build(metadata, {parentView: view, parent: view, builder: builder}); + element.setValue(true); + element.render(); + + // Then + assert.equal(events.OnLoaded, 1); + assert.equal(events.OnValueChanged, 1); + }); + //@TODO Add Checking Events + }); + + describe('render', function () { + + var element = builder.buildType('TextBox', {}); + + it('Setting the properties: value, name, enabled, visible, horizontalAlignment', function () { + // Given + + // When + var $el = element.render(); + + // Then + assert.equal($el.length, 1) + }); + + }); +}); + +describe('TextBoxBuilder', function () { + describe('build', function () { + it('successful build TextBox', function () { + // Given + + var metadata = {}; + + // When + var builder = new InfinniUI.TextBoxBuilder(); + var element = builder.build(null, {builder: new InfinniUI.ApplicationBuilder(), view: new InfinniUI.View(), metadata: metadata}); + + // Then + assert.isNotNull(element); + assert.isObject(element); + }); + }); +}); + +describe('TextEditorBase (Element)', function () { + describe('Textbox as exemplar of TextEditorBase', function () { + var metadata_1 = { + Text: '��������', + DataSources : [ + { + ObjectDataSource: { + "Name": "ObjectDataSource1", + "Items": [ + { "Id": 1, "Display": "2.2222" }, + { "Id": 2, "Display": "3.2222" }, + { "Id": 3, "Display": "4.2222" } + ] + } + } + ], + Items: [{ + + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "ObjectDataSource1", + "Property": "$.Display" + }, + "DisplayFormat": "{:n2}", + + "EditMask": { + "NumberEditMask": { + "Mask": "n3" + } + } + } + }] + }; + + it('Base functional', function () { + // Given + var textBox = new InfinniUI.TextBox(); + var format = function (context, args) { + var format = new InfinniUI.ObjectFormat(); + return format.format(args.value); + }; + var mask = new InfinniUI.DateTimeEditMask(); + + assert.isNull(textBox.getLabelText(), 'default label text is null'); + assert.isFalse(textBox.getLabelFloating(), 'default label floating is false'); + assert.isNull(textBox.getDisplayFormat(), 'default display format is null'); + assert.isNull(textBox.getEditMask(), 'default edit mask is null'); + + + // When + textBox.setLabelText('label'); + textBox.setLabelFloating(true); + textBox.setDisplayFormat(format); + textBox.setEditMask(mask); + + + // Then + assert.equal(textBox.getLabelText(), 'label', 'new label text is right'); + assert.isTrue(textBox.getLabelFloating(), 'new label floating is true'); + assert.equal(textBox.getDisplayFormat(), format, 'new display format is right'); + assert.equal(textBox.getEditMask(), mask, 'new edit mask is right'); + }); + + + it('Building TextEditorBase (Textbox) by Metadata', function () { + // Given + var metadata = metadata_1; + + // When + testHelper.applyViewMetadata(metadata, onViewReady); + + // Then + function onViewReady(view, $layout){ + $layout.detach(); + + var textbox = view.getContext().controls['TextBox1']; + var formatter = textbox.getDisplayFormat(); + var mask = textbox.getEditMask(); + + assert.equal(formatter(null, {value: 2.22222}), '2,22', 'applied format is right (n2)'); + assert.equal(mask.mask, 'n3', 'applied mask is right (n3)'); + } + }); + + }); + +}); + +describe('ToggleButton', function () { + describe('render', function () { + it('Setting the properties: value, name, enabled, visible, horizontalAlignment', function () { + // Given + var toggleButton = new InfinniUI.ToggleButton(), + $el; + + // When + $el = toggleButton.render(); + + // Then + assert.isTrue($el.hasClass('toggle-off')); + assert.isUndefined($el.attr('data-pl-name'), 'data-pl-name'); + assert.isFalse($el.hasClass('pl-disabled')); + assert.isFalse($el.hasClass('hidden'), 'hidden'); + assert.isTrue($el.hasClass('pl-horizontal-Left'), 'pl-horizontal-Left'); + assert.isFalse($el.hasClass('pl-horizontal-Center'), 'pl-horizontal-Center'); + }); + + it('Change the properties: value, name, enabled, visible, horizontalAlignment', function () { + // Given + var toggleButton = new InfinniUI.ToggleButton(), + $el; + + // When + $el = toggleButton.render(); + toggleButton.setValue(false); + toggleButton.setTextOn('on'); + toggleButton.setTextOff('off'); + + toggleButton.setName('newName'); + toggleButton.setEnabled(false); + toggleButton.setVisible(false); + toggleButton.setHorizontalAlignment('Center'); + + // Then + assert.isTrue($el.hasClass('toggle-off')); + assert.equal($el.attr('data-pl-name'), 'newName'); + assert.isTrue($el.hasClass('pl-disabled')); + assert.isTrue($el.hasClass('hidden')); + assert.isFalse($el.hasClass('pl-horizontal-Left')); + assert.isTrue($el.hasClass('pl-horizontal-Center')); + }); + + it('Events onLoad, onValueChanged', function () { + // Given + var toggleButton = new InfinniUI.ToggleButton(), + onLoadFlag = 0, + onValueChanged = 0; + + toggleButton.onLoaded(function(){ + onLoadFlag++; + }); + toggleButton.onValueChanged(function(){ + onValueChanged++; + }); + + assert.equal(onLoadFlag, 0); + assert.equal(onValueChanged, 0); + + // When + toggleButton.render(); + toggleButton.setValue('true'); + + // Then + assert.equal(onLoadFlag, 1); + assert.equal(onValueChanged, 1); + }); + + it('should be true if scriptsHandlers call', function () { + //Given + var toggleButton = new InfinniUI.ToggleButtonBuilder(); + var view = new InfinniUI.View(); + var metadata = { + OnValueChanged:{ + Name: 'OnValueChanged' + }, + OnLoaded:{ + Name: 'OnLoaded' + } + }; + + var events = { + OnValueChanged: 0, + OnLoaded: 0 + }; + var scripts = view.getScripts(); + scripts.add({ + name: 'OnValueChanged', + func: function () { + events.OnValueChanged++; + } + }); + scripts.add({ + name: 'OnLoaded', + func: function () { + events.OnLoaded++; + } + }); + + + //When + var element = toggleButton.build(null, {builder: toggleButton, parentView: view, parent: view, metadata: metadata}); + element.setValue(true); + element.render(); + + // Then + assert.equal(events.OnLoaded, 1, 'OnLoaded'); + assert.equal(events.OnValueChanged, 1, 'OnValueChanged'); + }); + }); +}); + +describe('ToolBarElement', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + describe('API', function () { + var element = builder.buildType('ToolBar', {Items: []}); + + + describe('Implementing Container Methods', function () { + testHelper.checkContainerMethods(element); + }); + + }); + + describe('render', function () { + + var element = builder.buildType('ToolBar', { + Items: [ + { + Button: { + Text: "Button 1" + } + }, + { + Button: { + Text: "Button 2" + } + + } + ] + }); + + it('render element', function () { + // Given + + // When + var $el = element.render(); + + // Then + assert.equal($el.length, 1) + }); + + it('contains items', function () { + var items = element.getItems(); + + assert.equal(items.length, 2); + }) + + }); +}); + +describe('ToolBarBuilder', function () { + var builder = new InfinniUI.ApplicationBuilder(); + + + it('Build ToolBar instance', function () { + var element = builder.buildType('ToolBar', {Items: []}); + + assert.isTrue(typeof element !== 'undefined' && element !== null); + assert.isTrue(element instanceof InfinniUI.ToolBar); + }); + +}); + +describe('View', function () { + + it('should get scripts', function () { + //Given + var view = new InfinniUI.View(); + + //When + var scripts = view.getScripts(); + + //Then + assert.isDefined(scripts); + assert.instanceOf(scripts, InfinniUI.Collection); + + //When + scripts.add('script'); + + //Then + assert.equal(view.getScripts().length, 1, 'getScripts should not override scripts'); + }); + + it('should get parameters', function () { + //Given + var view = new InfinniUI.View(); + + //When + var parameters = view.getParameters(); + + //Then + assert.isDefined(parameters); + assert.instanceOf(parameters, InfinniUI.Collection); + + //When + parameters.add('parameter'); + + //Then + assert.equal(view.getParameters().length, 1, 'getParameters should not override parameters'); + }); + + it('should get dataSources', function () { + //Given + var view = new InfinniUI.View(), + dataSource = new InfinniUI.DocumentDataSource({view: view}); + + //When + var dataSources = view.getDataSources(); + + //Then + assert.isDefined(dataSources); + assert.instanceOf(dataSources, InfinniUI.Collection); + + //When + dataSources.add(dataSource); + + //Then + assert.equal(view.getDataSources().length, 1, 'getDataSources should not override dataSource'); + }); + + it('should set dialogResult', function () { + //Given + var view = new InfinniUI.View(); + + assert.equal(view.getDialogResult(),InfinniUI.DialogResult.none); + + //When + view.setDialogResult(InfinniUI.DialogResult.accepted); + + //Then + assert.equal(view.getDialogResult(),InfinniUI.DialogResult.accepted); + }); + + describe('Context', function () { + it('should get context', function () { + //Given + var view = new InfinniUI.View(); + + //When + var context = view.getContext(); + + //Then + assert.isNotNull(context); + assert.isDefined(context); + }); + + it('should refresh context on registerElement', function () { + //Given + var view = new InfinniUI.View(); + + //When + view.registerElement({name: 'element'}); + var context = view.getContext(); + + //Then + assert.isDefined(context.controls['element']); + }); + + + it('should refresh context on add script', function () { + //Given + var view = new InfinniUI.View(); + var scripts = view.getScripts(); + + //When + scripts.add({ name: 'script', func: {} }); + var context = view.getContext(); + + //Then + assert.isDefined(context.scripts['script']); + }); + + it('should refresh context on replace script', function () { + //Given + var view = new InfinniUI.View(); + var scripts = view.getScripts(); + var oldScript = { name: 'oldScript', func: {} }; + var newScript = { name: 'newScript', func: {} }; + + scripts.add(oldScript); + + //When + scripts.replace(oldScript, newScript); + var context = view.getContext(); + + //Then + assert.isUndefined(context.scripts['oldScript']); + assert.isDefined(context.scripts['newScript']); + }); + + it('should refresh context on remove script', function () { + //Given + var view = new InfinniUI.View(); + var scripts = view.getScripts(); + var removedScript = { name: 'removedScript', func: {} }; + + scripts.add(removedScript); + assert.isDefined(view.getContext().scripts['removedScript']); + + //When + scripts.remove(removedScript); + var context = view.getContext(); + + //Then + assert.isUndefined(context.scripts['removedScript']); + }); + + it('should refresh context on reset script', function () { + //Given + var view = new InfinniUI.View(); + var scripts = view.getScripts(); + var oldScript = { name: 'oldScript', func: {} }; + var newScript = { name: 'newScript', func: {} }; + + scripts.add(oldScript); + + //When + scripts.reset([newScript]); + var context = view.getContext(); + + //Then + assert.isUndefined(context.scripts['oldScript']); + assert.isDefined(context.scripts['newScript']); + }); + + + it('should refresh context on add parameter', function () { + //Given + var view = new InfinniUI.View(); + var parameters = view.getParameters(); + + //When + parameters.add({name: 'param'}); + var context = view.getContext(); + + //Then + assert.isDefined(context.parameters['param']); + }); + + it('should refresh context on replace parameter', function () { + //Given + var view = new InfinniUI.View(); + var parameters = view.getParameters(); + var oldParameter = { name: 'oldParameter' }; + var newParameter = { name: 'newParameter' }; + + parameters.add(oldParameter); + + //When + parameters.replace(oldParameter, newParameter); + var context = view.getContext(); + + //Then + assert.isUndefined(context.parameters['oldParameter']); + assert.isDefined(context.parameters['newParameter']); + }); + + it('should refresh context on remove parameter', function () { + //Given + var view = new InfinniUI.View(); + var parameters = view.getParameters(); + var removedParameter = { name: 'removedParameter' }; + + parameters.add(removedParameter); + assert.isDefined(view.getContext().parameters['removedParameter']); + + //When + parameters.remove(removedParameter); + var context = view.getContext(); + + //Then + assert.isUndefined(context.parameters['removedParameter']); + }); + + it('should refresh context on reset parameter', function () { + //Given + var view = new InfinniUI.View(); + var parameters = view.getParameters(); + var oldParameter = { name: 'oldParameter' }; + var newParameter = { name: 'newParameter' }; + + parameters.add(oldParameter); + + //When + parameters.reset([newParameter]); + var context = view.getContext(); + + //Then + assert.isUndefined(context.parameters['oldParameter']); + assert.isDefined(context.parameters['newParameter']); + }); + + + it('should refresh context on add dataSource', function () { + //Given + var view = new InfinniUI.View(); + var dataSource = new InfinniUI.DocumentDataSource({view: view, name: 'dataSource'}); + var dataSources = view.getDataSources(); + + //When + dataSources.add(dataSource); + var context = view.getContext(); + + //Then + assert.isDefined(context.dataSources['dataSource']); + }); + + it('should refresh context on replace dataSource', function () { + //Given + var view = new InfinniUI.View(); + var dataSources = view.getDataSources(); + var oldDataSource = new InfinniUI.DocumentDataSource({view: view, name: 'oldDataSource'}); + var newDataSource = new InfinniUI.DocumentDataSource({view: view, name: 'newDataSource'}); + + dataSources.add(oldDataSource); + + //When + dataSources.replace(oldDataSource, newDataSource); + var context = view.getContext(); + + //Then + assert.isUndefined(context.dataSources['oldDataSource']); + assert.isDefined(context.dataSources['newDataSource']); + }); + + it('should refresh context on remove dataSource', function () { + //Given + var view = new InfinniUI.View(); + var dataSources = view.getDataSources(); + var removedDataSource = new InfinniUI.DocumentDataSource({view: view, name: 'removedDataSource'}); + + dataSources.add(removedDataSource); + assert.isDefined(view.getContext().dataSources['removedDataSource']); + + //When + dataSources.remove(removedDataSource); + var context = view.getContext(); + + //Then + assert.isUndefined(context.dataSources['removedDataSource']); + }); + + it('should refresh context on reset dataSource', function () { + //Given + var view = new InfinniUI.View(); + var dataSources = view.getDataSources(); + var oldDataSource = new InfinniUI.DocumentDataSource({view: view}); + var newDataSource = new InfinniUI.DocumentDataSource({view: view}); + oldDataSource.setName('oldDataSource'); + newDataSource.setName('newDataSource'); + + dataSources.add(oldDataSource); + + //When + dataSources.reset([newDataSource]); + var context = view.getContext(); + + //Then + assert.isUndefined(context.dataSources['oldDataSource']); + assert.isDefined(context.dataSources['newDataSource']); + }); + }); + + describe('Open', function () { + it('should call event onOpening', function () { + //Given + var view = new InfinniUI.View(); + window.EventOnOpeningWasCall = false; + + view.onOpening(function () { + window.EventOnOpeningWasCall = true; + }); + + //When + view.open(); + + //Then + assert.isTrue(window.EventOnOpeningWasCall, 'onOpening was not call'); + }); + + it('should call event onOpened when onOpening passed', function () { + //Given + var view = new InfinniUI.View(); + window.EventOnOpenedWasCall = false; + + view.onOpened(function () { + window.EventOnOpenedWasCall = true; + }); + + //When + view.open(); + + //Then + assert.isTrue(window.EventOnOpenedWasCall, 'onOpened was not call'); + }); + + it('should not call event onOpened when onOpening failed', function () { + //Given + var view = new InfinniUI.View(); + window.EventOnOpenedWasCall = false; + + view.onOpening( + function () { + return false; // onOpening failed + }); + + view.onOpened(function () { + window.EventOnOpenedWasCall = true; + }); + + //When + view.open(); + + //Then + assert.isFalse(window.EventOnOpenedWasCall); + }); + + it('should select correct callback when onOpening passed', function () { + //Given + var view = new InfinniUI.View(); + window.SuccessWasCall = false; + window.ErrorWasCall = false; + + //When + view.open( + function () { + window.SuccessWasCall = true; + }, + function () { + window.ErrorWasCall = true; + } + ); + + //Then + assert.isTrue(window.SuccessWasCall, 'success was not call'); + assert.isFalse(window.ErrorWasCall, 'error was call'); + }); + + it('should select correct callback when onOpening failed', function () { + //Given + var view = new InfinniUI.View(); + window.SuccessWasCall = false; + window.ErrorWasCall = false; + + view.onOpening( + function () { + return false; // onOpening failed + }); + + //When + view.open( + function () { + window.SuccessWasCall = true; + }, + function () { + window.ErrorWasCall = true; + } + ); + + //Then + assert.isFalse(window.SuccessWasCall, 'success was call'); + assert.isTrue(window.ErrorWasCall, 'error was not call'); + }); + }); + + describe('Close', function () { + it('should call event onClosing', function () { + //Given + var view = new InfinniUI.View(); + window.EventOnClosingWasCall = false; + + view.onClosing(function () { + window.EventOnClosingWasCall = true; + }); + + //When + view.close(); + + //Then + assert.isTrue(window.EventOnClosingWasCall, 'OnClosing was not call'); + }); + + it('should call event onClosed when onClosing passed', function () { + //Given + var view = new InfinniUI.View(); + window.EventOnClosedWasCall = false; + + view.onClosed(function () { + window.EventOnClosedWasCall = true; + }); + + //When + view.close(); + + //Then + assert.isTrue(window.EventOnClosedWasCall, 'OnClosed was not call'); + }); + + it('should not call event onClosed when onClosing failed', function () { + //Given + var view = new InfinniUI.View(); + window.EventOnClosedWasCall = false; + + view.onClosing( + function () { + return false; // onClosing failed + }); + + view.onClosed(function () { + window.EventOnClosedWasCall = true; + }); + + //When + view.close(); + + //Then + assert.isFalse(window.EventOnClosedWasCall); + }); + + it('should select correct callback when onClosing passed', function () { + //Given + var view = new InfinniUI.View(); + window.SuccessWasCall = false; + window.ErrorWasCall = false; + + //When + view.close( + function () { + window.SuccessWasCall = true; + }, + function () { + window.ErrorWasCall = true; + } + ); + + //Then + assert.isTrue(window.SuccessWasCall, 'success was not call'); + assert.isFalse(window.ErrorWasCall, 'error was call'); + }); + + it('should select correct callback when onClosing failed', function () { + //Given + var view = new InfinniUI.View(); + window.SuccessWasCall = false; + window.ErrorWasCall = false; + + view.onClosing( + function () { + return false; // onClosing failed + }); + + //When + view.close( + function () { + window.SuccessWasCall = true; + }, + function () { + window.ErrorWasCall = true; + } + ); + + //Then + assert.isFalse(window.SuccessWasCall, 'success was call'); + assert.isTrue(window.ErrorWasCall, 'error was not call'); + }); + }); + +}); + +describe('ViewBuilder', function () { + var viewMetadata = { + Text: 'TestView', + DataSources: [ + { + DocumentDataSource: { + Name: 'documentDataSource1', + ConfigId: 'configuration', + DocumentId: 'document' + } + }, + { + ObjectDataSource: { + Name: 'objectDataSource1', + Items: [ + { Id: 1, Display: 'first' }, + { Id: 2, Display: 'second' } + ] + } + } + ], + + Items: [{ + "TextBox": { + "Name": "TextBox1", + "Value": { + "Source": "objectDataSource1", + "Property": "$.Display" + } + } + }], + + Parameters: [ + { + Name: 'param1', + OnPropertyChanged: 'OnParameterChanged' + } + ], + + Scripts: [ + { + Name: 'script1', + Body: '' + }, + { + Name: 'script2', + Body: '' + } + ] + }; + + it('should build Container and Element metadata', function () { + // Given + var viewBuilder = new InfinniUI.ViewBuilder(); + var metadata = { + Name: 'my_view', + Items: [ + { + StackPanel: { + GridPanel: { + Rows: [] + } + } + } + ] + }; + + // When + var view = viewBuilder.build(null, {metadata: metadata}); + + // Then + assert.equal(view.getName(), 'my_view'); + assert.instanceOf(view.getItems(), InfinniUI.Collection); + }); + + it('should build Scripts', function () { + // Given + var viewBuilder = new InfinniUI.ViewBuilder(); + var metadata = viewMetadata; + + // When + var view = viewBuilder.build(null, {builder: new InfinniUI.ApplicationBuilder(), metadata: metadata}); + + // Then + assert.equal(view.getScripts().length, 2); + + var script = view.getScripts().pop(); + assert.property(script, 'name'); + assert.property(script, 'func'); + assert.instanceOf(script.func, Function); + }); + + it('should build Parameters', function () { + // Given + var viewBuilder = new InfinniUI.ViewBuilder(); + var metadata = viewMetadata; + var param = new InfinniUI.Parameter({name: 'param1'}); + + // When + var view = viewBuilder.build(null, {builder: new InfinniUI.ApplicationBuilder(), metadata: metadata, params: {param1: param}}); + + // Then + assert.equal(view.getParameters().length, 1); + assert.instanceOf(view.getParameters().pop(), InfinniUI.Parameter); + }); + + it('should build DataSources', function () { + // Given + window.InfinniUI.providerRegister.register('DocumentDataSource', FakeRestDataProvider); + window.InfinniUI.providerRegister.register('ObjectDataSource', InfinniUI.Providers.ObjectDataProvider); + + var viewBuilder = new InfinniUI.ViewBuilder(); + var metadata = viewMetadata; + + // When + var view = viewBuilder.build(null, {builder: new InfinniUI.ApplicationBuilder(), metadata: metadata}); + var dataSources = view.getDataSources(); + + // Then + assert.equal(dataSources.length, 2); + assert.instanceOf(dataSources.find(function(item){ return item.getName() == 'documentDataSource1'; }), InfinniUI.DocumentDataSource, 'wrong build for DocumentDataSource'); + assert.instanceOf(dataSources.find(function(item){ return item.getName() == 'objectDataSource1'; }), InfinniUI.ObjectDataSource, 'wrong build for ObjectDataSource'); + }); + + it('should sort DataSources by priority', function (done) { + // Given + window.InfinniUI.providerRegister.register('DocumentDataSource', FakeRestDataProvider); + + var viewBuilder = new InfinniUI.ViewBuilder(); + var metadata = { + DataSources: [ + { + DocumentDataSource: { + Name: 'ds1', + ConfigId: 'configuration', + DocumentId: 'document' + } + }, + { + DocumentDataSource: { + Name: 'ds2', + ConfigId: 'configuration', + DocumentId: 'document', + ResolvePriority: 1 + } + }, + { + DocumentDataSource: { + Name: 'ds3', + ConfigId: 'configuration', + DocumentId: 'document', + ResolvePriority: 2 + } + }, + { + DocumentDataSource: { + Name: 'ds4', + ConfigId: 'configuration', + DocumentId: 'document', + ResolvePriority: -11 + } + }, + { + DocumentDataSource: { + Name: 'ds5', + ConfigId: 'configuration', + DocumentId: 'document', + ResolvePriority: 1 + } + } + ] + }; + + // When + var view = viewBuilder.build(null, {builder: new InfinniUI.ApplicationBuilder(), metadata: metadata}); + + var dataSources = view.getDataSources()._items.map(function(obj){return obj.__value;}), + ds4 = dataSources.find(function(item){ return item.name == 'ds4'; }), + updatedDataSources = []; + + dataSources.forEach(function(ds){ + ds.onItemsUpdated(function(context, args){ updatedDataSources.push(args.source.name); }); + }); + + ds4.onItemsUpdated(onDataSourcesReady); + + dataSources.forEach(function(ds){ + ds.updateItems(); + }); + + // Then + function onDataSourcesReady(){ + assert.deepEqual(updatedDataSources, ['ds3', 'ds2', 'ds5', 'ds1', 'ds4'], 'priority ds must be resolved before nonpriority'); + done(); + } + }); + + + it('should build OnOpening', function () { + // Given + var viewBuilder = new InfinniUI.ViewBuilder(); + var metadata = _.extend({}, viewMetadata, { + Scripts: [ + { + Name: 'onOpening', + Body: 'window.EventOnOpeningWasCall = true;' + } + ], + OnOpening: 'onOpening' + }); + + window.EventOnOpeningWasCall = false; + + // When + var view = viewBuilder.build(null, {builder: new InfinniUI.ApplicationBuilder(), metadata: metadata}); + view.open(); + + // Then + assert.isTrue(window.EventOnOpeningWasCall); + + // cleaning + view.close(); + }); + + it('should build OnOpened', function () { + // Given + var viewBuilder = new InfinniUI.ViewBuilder(); + var metadata = _.extend({}, viewMetadata, { + Scripts: [ + { + Name: 'onOpened', + Body: 'window.EventOnOpenedWasCall = true;' + } + ], + OnOpened: 'onOpened' + }); + + window.EventOnOpenedWasCall = false; + + // When + var view = viewBuilder.build(null, {builder: new InfinniUI.ApplicationBuilder(), metadata: metadata}); + view.open(); + + // Then + assert.isTrue(window.EventOnOpenedWasCall); + + // cleaning + view.close(); + }); + + it('should build OnClosing', function () { + // Given + var viewBuilder = new InfinniUI.ViewBuilder(); + var metadata = _.extend({}, viewMetadata, { + Scripts: [ + { + Name: 'onClosing', + Body: 'window.EventOnClosingWasCall = true;' + } + ], + OnClosing: 'onClosing' + }); + + window.EventOnClosingWasCall = false; + + // When + var view = viewBuilder.build(null, {builder: new InfinniUI.ApplicationBuilder(), metadata: metadata}); + view.close(); + + // Then + assert.isTrue(window.EventOnClosingWasCall); + }); + + it('should build OnClosed', function () { + // Given + var viewBuilder = new InfinniUI.ViewBuilder(); + var metadata = _.extend({}, viewMetadata, { + Scripts: [ + { + Name: 'onClosed', + Body: 'window.EventOnClosedWasCall = true;' + } + ], + OnClosed: 'onClosed' + }); + + window.EventOnClosedWasCall = false; + + // When + var view = viewBuilder.build(null, {builder: new InfinniUI.ApplicationBuilder(), metadata: metadata}); + view.close(); + + // Then + assert.isTrue(window.EventOnClosedWasCall); + }); + + it('should build CloseButtonVisibility', function () { + // Given + var viewBuilder = new InfinniUI.ViewBuilder(); + var builder = new InfinniUI.ApplicationBuilder(); + var metadata = _.extend({}, viewMetadata, { + CloseButtonVisibility: false + }); + + // When + var view = viewBuilder.build(null, {metadata: metadata, builder: builder}); + + // Then + assert.isFalse(view.getCloseButtonVisibility()); + }); + + it('should build HeaderTemplate', function () { + // Given + var viewBuilder = new InfinniUI.ViewBuilder(); + var metadata = _.extend({}, viewMetadata, { + HeaderTemplate: { + Icon: { + } + } + }); + + // When + var view = viewBuilder.build(null, {builder: new InfinniUI.ApplicationBuilder(), metadata: metadata}); + + // Then + var headerTemplate = view.getHeaderTemplate(); + var header = headerTemplate(); + + assert.instanceOf(header, InfinniUI.Icon); + }); + + it('should build default value', function () { + // Given + var viewBuilder = new InfinniUI.ViewBuilder(); + var builder = new InfinniUI.ApplicationBuilder(); + var metadata = viewMetadata; + + // When + var view = viewBuilder.build(null, {metadata: metadata, builder: builder}); + + // Then + var headerTemplate = view.getHeaderTemplate(); + var header = headerTemplate(); + + // Header + assert.instanceOf(header, InfinniUI.Label); + assert.equal(header.getValue(), 'TestView'); + + // CloseButtonVisibility + assert.isTrue(view.getCloseButtonVisibility()); + }); +}); diff --git a/out/vendor.js b/out/vendor.js index 34d2f2b..cc64aad 100644 --- a/out/vendor.js +++ b/out/vendor.js @@ -12,500 +12,12 @@ padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){va //# sourceMappingURL=underscore-min.map !function(t,e){if("function"==typeof define&&define.amd)define(["underscore","jquery","exports"],function(i,n,s){t.Backbone=e(t,s,i,n)});else if("undefined"!=typeof exports){var i=require("underscore");e(t,exports,i)}else t.Backbone=e(t,{},t._,t.jQuery||t.Zepto||t.ender||t.$)}(this,function(t,e,i,n){var s=t.Backbone,r=[],a=(r.push,r.slice);r.splice;e.VERSION="1.1.2",e.$=n,e.noConflict=function(){return t.Backbone=s,this},e.emulateHTTP=!1,e.emulateJSON=!1;var o=e.Events={on:function(t,e,i){if(!c(this,"on",t,[e,i])||!e)return this;this._events||(this._events={});var n=this._events[t]||(this._events[t]=[]);return n.push({callback:e,context:i,ctx:i||this}),this},once:function(t,e,n){if(!c(this,"once",t,[e,n])||!e)return this;var s=this,r=i.once(function(){s.off(t,r),e.apply(this,arguments)});return r._callback=e,this.on(t,r,n)},off:function(t,e,n){var s,r,a,o,h,u,l,d;if(!this._events||!c(this,"off",t,[e,n]))return this;if(!t&&!e&&!n)return this._events=void 0,this;for(o=t?[t]:i.keys(this._events),h=0,u=o.length;h").attr(t);this.setElement(n,!1)}}}),e.sync=function(t,n,s){var r=E[t];i.defaults(s||(s={}),{emulateHTTP:e.emulateHTTP,emulateJSON:e.emulateJSON});var a={type:r,dataType:"json"};if(s.url||(a.url=i.result(n,"url")||j()),null!=s.data||!n||"create"!==t&&"update"!==t&&"patch"!==t||(a.contentType="application/json",a.data=JSON.stringify(s.attrs||n.toJSON(s))),s.emulateJSON&&(a.contentType="application/x-www-form-urlencoded",a.data=a.data?{model:a.data}:{}),s.emulateHTTP&&("PUT"===r||"DELETE"===r||"PATCH"===r)){a.type="POST",s.emulateJSON&&(a.data._method=r);var o=s.beforeSend;s.beforeSend=function(t){if(t.setRequestHeader("X-HTTP-Method-Override",r),o)return o.apply(this,arguments)}}"GET"===a.type||s.emulateJSON||(a.processData=!1),"PATCH"===a.type&&x&&(a.xhr=function(){return new ActiveXObject("Microsoft.XMLHTTP")});var h=s.xhr=e.ajax(i.extend(a,s));return n.trigger("request",n,h,s),h};var x=!("undefined"==typeof window||!window.ActiveXObject||window.XMLHttpRequest&&(new XMLHttpRequest).dispatchEvent),E={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};e.ajax=function(){return e.$.ajax.apply(e.$,arguments)};var k=e.Router=function(t){t||(t={}),t.routes&&(this.routes=t.routes),this._bindRoutes(),this.initialize.apply(this,arguments)},T=/\((.*?)\)/g,$=/(\(\?)?:\w+/g,S=/\*\w+/g,H=/[\-{}\[\]+?.,\\\^$|#\s]/g;i.extend(k.prototype,o,{initialize:function(){},route:function(t,n,s){i.isRegExp(t)||(t=this._routeToRegExp(t)),i.isFunction(n)&&(s=n,n=""),s||(s=this[n]);var r=this;return e.history.route(t,function(i){var a=r._extractParameters(t,i);r.execute(s,a),r.trigger.apply(r,["route:"+n].concat(a)),r.trigger("route",n,a),e.history.trigger("route",r,n,a)}),this},execute:function(t,e){t&&t.apply(this,e)},navigate:function(t,i){return e.history.navigate(t,i),this},_bindRoutes:function(){if(this.routes){this.routes=i.result(this,"routes");for(var t,e=i.keys(this.routes);null!=(t=e.pop());)this.route(t,this.routes[t])}},_routeToRegExp:function(t){return t=t.replace(H,"\\$&").replace(T,"(?:$1)?").replace($,function(t,e){return e?t:"([^/?]+)"}).replace(S,"([^?]*?)"),new RegExp("^"+t+"(?:\\?([\\s\\S]*))?$")},_extractParameters:function(t,e){var n=t.exec(e).slice(1);return i.map(n,function(t,e){return e===n.length-1?t||null:t?decodeURIComponent(t):null})}});var A=e.History=function(){this.handlers=[],i.bindAll(this,"checkUrl"),"undefined"!=typeof window&&(this.location=window.location,this.history=window.history)},I=/^[#\/]|\s+$/g,N=/^\/+|\/+$/g,R=/msie [\w.]+/,O=/\/$/,P=/#.*$/;A.started=!1,i.extend(A.prototype,o,{interval:50,atRoot:function(){return this.location.pathname.replace(/[^\/]$/,"$&/")===this.root},getHash:function(t){var e=(t||this).location.href.match(/#(.*)$/);return e?e[1]:""},getFragment:function(t,e){if(null==t)if(this._hasPushState||!this._wantsHashChange||e){t=decodeURI(this.location.pathname+this.location.search);var i=this.root.replace(O,"");t.indexOf(i)||(t=t.slice(i.length))}else t=this.getHash();return t.replace(I,"")},start:function(t){if(A.started)throw new Error("Backbone.history has already been started");A.started=!0,this.options=i.extend({root:"/"},this.options,t),this.root=this.options.root,this._wantsHashChange=this.options.hashChange!==!1,this._wantsPushState=!!this.options.pushState,this._hasPushState=!!(this.options.pushState&&this.history&&this.history.pushState);var n=this.getFragment(),s=document.documentMode,r=R.exec(navigator.userAgent.toLowerCase())&&(!s||s<=7);if(this.root=("/"+this.root+"/").replace(N,"/"),r&&this._wantsHashChange){var a=e.$('

5q!RY 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%0DyT{kunD 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⋙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 z - - + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/out/fonts/fontawesome-webfont.ttf b/out/fonts/fontawesome-webfont.ttf index f221e50a2ef60738ba30932d834530cdfe55cb3e..35acda2fa1196aad98c2adf4378a7611dd713aa3 100644 GIT binary patch delta 20319 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 SdSQM28?+M|D(2r_;{O0|uQ74} literal 90412 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%0Ded40&XED0GYFoIh+AV*?9!MR5pBW?X_8Bp zK%Pi2&3!RUu9|qRP>4Z35>46R3-HSVQAZLeK|VoiF$JlT%hYN$P{~XnOQBRrwNe$3 zDkDcHp>LA~P6d z5;fR}J~SHToEBnMNz2J6@w`HcLpUx~OvPyi9!FGCnG$S!Nu$wVjzF!}7&Oz=YOP5N zluDpAY5uI%+w?#pQ9`*)A?4JNnR$45&%afA$Ec1MfKwMKS$_D?H&7v0tL4cbzLBen zPQeDPlx3w_N%C3nIgoP-8K(mC6YFKN^$A)18?Vabue>3{1M~AAzEmi_{6Wd~e6Lb{ z-=lJU_M=wD{rH(ghD>k)+VUf((EkY5=@l&~=XksKuU9Qu4%g8d8OKWX$(xqn1@$U=vss>j z&UTv)_xlSZeOiTS27(|;QR&_oo@&VMd<8K5?=eOImlmT%QOJXL!Tyye(QT*$-F9*% z*#9f>W1tI6J=q&SNmHXo9uajhj*RR%G9Uu721J-Fd`gHhd>XKq%TqSWLrubCXE~Li zuEulHFZb%qoX$;LAPb7tM0^VbNg3I|m2gIJznp`D-#uc@4v1}tk?g+`dxJ6<5{&Qh zYvTi^EYtu<%y^QE33`A2h(BQ9Xi_#nE+b+69x^D4*yE019|CeB*x}d$R>_s<4@xkN z7@H+2h}_|_(i@#xH3X9Cf-9@uzwhR88kGgGaz-|3lv)OhVs&1NN~Lfafmx}S5nFg= z4B3lDg@=NT8WnyX0iHq$)?Kw5n%Ks$z1Rs?T9!2ys2OI9u)o%eqa1Y9p{vuBphS62 z&rrmo?HmP%+nijX33FEf_=9ds89K))0VB5sXXVN?5RU4+dVSlip`gZ?FM%}cTs!Cx zvRkeUj-}URwR1i?$S?v}mI=2=a!%Ba$>Q1tqZbt`EDit$_A~Jt4gYQ5hBp#GV%++X zFxgngVF8klmS}*7(B-s8AnZK2wdru=S6g{b{h@;ij)n{kSUPd=P(6CPeH!Ktaa;m# zSaJho0mEQsaa#LtXfZl5FF6l~QzId8ol)GaA`+8FVKkKAMxAXpQ!(P2pA`k07Dn>kT@+i0w=sV?xguZi1YNXzCXwX)?u?)Ig7tC16huq z*9bgy-7nOlPa9@2N*Z@6MxvP8h(4%$_QY>!g3sp8y`AHwjD+E2%nvfM#?A^hc^?3VDn)u zIO^gzZq!B%Mpid{x{fvKpS2stjL}E^kS{9YA#eCCGgF?_lsrvbK;A9v72mB%4z?Tw z`wki!jYa&nnf)`KLMHSH!WXuqPH%bqVHw1`!J26?rc3x_j#j8N@ET}RRi)0qsYUP={P;@WeTT2$$5#TmJpMzcE=^BL@D*utX*mw`JdXpI z*9lzM%f5r#i)iIyvPc3&hdgr3?U-zYW{UayJf-77K-7>1Zu7D4%$QRB$2;;{+Z@$% zrZ4RnV+VHI*wt%V?p?9tjyI1!`dleztu3q8yGlcm_@C~mgfG5iz8ZadyDhgs7g=)s zM}Pwh-*^}8MPI$taqpKyK=4@i52v~hZUBrjkUnepnD%MopZ;q~j?annnuL;LE=rF% zQY*m(;DOG^#sV_n>)mL^Je!X7Vah~jNI3%|yoks;{|$~ukD|w)f1VEG(0Az3CZNTO z*VosA=Hy+>>(8Udfhu_y9nR=^-I!zSc|9Y84&wk$0E^H2 z?2#`PPEa0NKDlWa2t0NeSndSpUb|=AwprRLWo=WesVR~(yt;bm@Ws`u@4jd4^;6X@ zzr3cgsI{RayQR8jXxpNyHAi4i-XGQ+`V`3jdDp_Hqk-(Dca+|8{C4!koe~TBdd-e$ zhN0@}+GwOMtFEoBF6;W0t9MM%dUKTVnsCV=F>U+Bwg)2aCb6iA2|hJ1G8pitb7q1{ z24eoASU{qs((y4P!0FSYf^S&Xj3;8wWPq>yQtcmhqb>KHXgkt&;`}!!9F7z1um-FX z6JANVdZnkIXm3B^kWiP=5>~g9O1LVia39)|d`?IJ{*T1U(i8WImlO7D(j}+azY-J( z(68L2CyM+O!6!(sBwPN0h>6ilPH+1s>PB6t`=8rRfYy`mqxVyOX=kGM-#-ajPr$^( zBy-z8LHyxAgQZ`)&g7!5Pd15eXg7TVI&#mrzDC=LJ~)r(wSVI_oQ8XRR38f!;?c+m ziX?*hIv_^wWK%OnOgEx}CJ-SUNv04`3pVkhse2xSxt_48&?zbLbIDHwc3C~V^^u=nYmeN)$BmCfd>Jj;r1?ffM!fB4#%vVHlBB781miYh7UFw z%ZFN+^sK^6wMxy&gSjn*b=d_D9?&14g%^&Yqn~eud)@(S@JNw{XRh40`|#jUKk5 z%v7;J)JtjcQPjJ{6=I}{P>Xa0YJedOBO1nBqykUReG}a_w=^xM`lk1E)ycn)Fxg9{ zPAzfrZ5~!yIv3scW^uLdy_>3Y)_kf~|I1Z-tfal5XhKmzd&#j{*T2;2Pu(@g%ElJt z%+DzpTXw7lWmOlG;(kxbT+qR2r<)9supLy&u17v26I zirx3Wk-QJhJnAkgcg$MQIo(lQ?Do5H#=Tji6%gMVuc740t{V8X@ZjY%^SJ>wv06<1 z4Wi~y060L$ze|Z`qt8I3#NiN~I-6n!$uFTObfyzQ4kZo)P*UmpEz&oOm9O|lh=Q^xg=CRdPP}| zKXY-gt}**`N3*@Ku&G_{8@vs|Z8SLN#M8aZBb!5C$CP^kt;JlN-c{_6qn8VY6o%>x z;q-wbu`@MQaj<*T$o8=BinO#PqeHVbw5~28Jc2` zfz5ela{*cvlC3tjeFT@c87!{+NQQv8PvG@&PS{9Xed!D-t#5H1gd^^{?f$)GwszOLU?6w!=+T37 z(e6QO7FIt|TQy|zbJumWO$ASUz%U;$aN^)umF=N4Dda2?qrXG)56OL+67{Gt70Iug zOG;Z?%1TYsXV0J~RJ8593cUV`Ql6c;;W4w+A8=)wjn3Q=CFo6S$-IWU%9+ej3mlB) z-r?6C%kOzEcO0BDDZ@QJdF!}Gejf;ycZ@9qlNl&^t}*J#T=yJAW6Pr1NuWbrUj8~ycl!HU7!#a-av`_Xr|#cPdbmh~FLB~uI;c;rg9N2Hr6e08up-22TjC-b>tq}QV~V;W7?d84U~8I1 zw5F6x7(vMv_cqZn4B1Z?U}A`G*%0n40gA&B_G}AOD z;FTG5Muiq&QmbsJVMI&{88-g!$kO3)jZ__%WL0V&r`htNpXaW#ITJdZpZOE);WFVRc_+GlJ64RR}1dMPurj>^Z z__6)O`#@1QynHgiL5B1PVQ>bxn3o`m5M()`y`dAk4%%~b z?ZNODg<=Z4zbHUb0!8RYSKwZB=1#N6Z7Zm>x5<)2&<8JorWYRuC8yw`ZOdbS*i%Oe z+zA}_-VPl1G4i%hI2Z_{$&Q>{yCXLTe06EU5#|YjiHtPBjiZ}J=T7k!#q#+y*kN7Eij!h>FY|J+Q_N>4@^ z{dfN>I%X8^{`=?EnE?acZ9J!DvwL3L1~>HlRDYbn;n;(Bw z6W2Qv2~fep$7L^eNGqD|OQx z5F~np#IyFs8H?7O+=u!!`8s-a*ZTEW?1ZmSL#;rEYxBTGmSmeyk4RYyB>2qxz|Knq zhb)CN2Npt4{z5ibiSKm+-)k$TCsW#I!Yqkr5F(}%zzB`B!R(|{+}*$u0o-l`br|%z zZNei=;NghIxsfNLJvW()_@Y1_ynG4ax{_TvkL2b&oMW+NGvtu7}cmm61ttBi7nksHzW9VWR1q`7Q49G7KrI$62g zysCuGrSt5ejDSTVXBVr&xHYn^ZPUhlEZw|Q=y zy1phpcI@g!AOt?NdfD2cX>lO2DkA3-RcF8jPtOqdVgJg_f{8!W%sia;7iMyL8VCmm_W_K?mxBf_tnKu3J}6*Xh#| zDw%$|Kao!KhhhBm>7FjKQ#t@d&JS=LQi((l{xKKjAZlPNRZNs`r+mv3Z3^N!1h*l< z*~2qAUPpbTbEe~TJUg+N6Jn!G_ts~gK|ekN(Y^`mad7MU31BuPaBn1t_CW|{PkF8*ZHTtMYDOSTF3r@UftO|bZy`ueV6thgGu(+j+mm03uxm`>!hW&*ZA4^>^ zc4Wmj5PnlJa_kjXJiH!$Q#k?$#*V1`2Cjb?TrrSTNLC~4g-v9Ckq|NArE_2`D)wDr{tTp4R|K)Ti0e`$!lD`AAVYz5{^1qfAJ7M!0rY>Q;LFpx*oACrV)wkhWzg1Nrj6$I@<^e(UrfTqcw!K2jwqb^p_ZkFNrVQC;v-fA{Yeiostv=Sl_(F6Eq_t z@as(wL<%7@=!11*`$DkWZ}Zy_o{-OS7Wgj$Z!1ReOn#4r>v@O39D#HK_S+j`x|29R zDJ&I`qUV^CaoF9HK&eFmFA|g)#7_4+Ef?ur;h7!87m0x*+CoeK;04OBuL5R31d<#% zOP*-(p+$ST?nGtB(4NP^+;#bPcI^Q-_~+vE&dyE zVIHpf8MwiR-@$r8Dfy@1bI(YX3f_nYq90twPo;c<>p zu+A=FY#weATV<~E4-OBlXn1M$`H}N#md|b;%>b#J1I(C~*~_cvj5xpAniZh6^rTwm z)7nYKKo;#7v2x{zktn0>8n=?!rToX7XwAD7AAm-B&h1Tq{?4E`G zadfdKJwLn{)B`95=)onS{B-Y)p7 zByg`1+=%J;7_q%K#()mEIU<7P>BLUx+PO1%el)0m2NTTA=;?RfK}!}e&8QhXN`6Tx zqV4DZ`OZ7cksbwV#^)=6TkOB%E&%ojo5WmTHlDGXsTpLJf~2Vh0!rk71>nwrL<1PX zp3#rvcp)NUEUZMpsJhnV_jOD5L%GRys|CUaGYKbDrAi1Pxb&WDZ}!9?3f!(0i(Mscce~#;8=w z8y>6Y6*9U1OiU9P3p1>t#>eYmQ<^?QmW_@_|6))Z<-piv3>mX^AW&oHOmO&2gKjJw z?XhQ1)W|*he6k=i|KL}>rS0mwd=J!hkyM9rYleoz4!A^NF%}RXL;IAi8 zcsc>zF>=w5(67P;PnC%$aMdhI#r;LVS#aTb zZ8)aMQlr*rh-F|#C1pVqBg%dP0GNP#<;ft9gay(YuPZ`2kEs_NPT_&|r!$7&t}EKE zm<<~@Y}zo4*6)=!fAPr|&GNm}1%>kJf9)G}--hX>P`5|E1*`%Iuxg8Z4^k)|LmN;r z+VGe{q1!8e1~SkFnP=pCRW};ab8^xR>q7W%k6tBj8auX0uF~%TTIrl=IhB<;d-O{A zmR-BH$dx!zBRg>L-~kya`1EV9JxvM{4LHGOM%cp~D3Pk7hEXG^Y1BMwEgqbg_=2PU z%QL}*6w&NL(Sd0LG48Yj^sfifw;(Z$=th87g%c7_^ss@k%O=vp8fQ1+|ERZquNfYT zk3!O`jYa1K={bv!k-1`R@*lh^oY1QSW0y@#CP2RgA6^i%x&=sTk=HU7*;nBm_@ykgx{=-5vsuM_>a411Pd7Sq22ZH^Kx$6fHzoP6kf^Gk~?bG#e z1W=%NOlkDL*xWQYI%7k@yv6jIk*iRh+s32A8k^f`EI!@&VX+UI19K+tt*?^MfG&G% z-o{Vcf)IcXY4S(8+r<7Z&2Qr~50N=MkXmQulpfFELBdg)Dc%ifKW6+S9HgT$J+CJz zGN7f2XB)q$f1n4)(hWe~foe8_U+i)cnkE6;5zRm9Qv5X6Ay4xMeqkgFa7tncvb z!*JiA*0uWq*j3;!4~(uinHv^uIsmUL%qh&Pk7_`7qT2N1gPylp%`J(>qMwECB*jOV z;oBjTr^{ojKp?7WnSdI`)vruL5N=Gahnuwa6_aKTF?)^9bhqM$46thY+&XK9(c}hJ z>8;V^(GF7sed4@uF;?iC+P=2o@HezkUaF94q2^PYsNK|^)G_MM)EVkKkOqkV0a3aU z^@StRJjRp3_Qs2Z4O1b9_QW_(fb;NSvyXIOPppsnF&7b;5^gflbr~lJON3c9kP#>% zEU=*aM&wiGFy|rr@R;Eg7(=qh5jGn*4*_`*l0=pe!IMaVKwa7_8^UkI5-c9~@vZB00k$C}OlA9~k`Rw4!{q3;=JMlk=xF?3bE& zyG$1xlVRb~OzARR_DJV^2bTtAEH9NxjeItg(x%vp+#=d$bvk5D`{Y=bC-YjB3^SI+ zn1Bq^YV&I{hshPRTa9+P!;~8tTx@%hQ89VI5HLH!`FMTDH=H*3< z#(bbSJ3^b&T)vpkWm>!Q{7sMFxFIK$vt$WAY`F39o6heP(pKe$^5)LX3+1jNX<*Am z9d&%V$yrV_tPB(14LBUi47##{51?~@{Nu|n1IeAm67LM9$(C*lWCNOIfI-gWD40T8 zCzW!1<`5u(`BI*fNezJ^Opz|%No!#~m#@q*te;~}Gnv#;>EzhptbjQHi)N}f4RRZG zz7lmT+nJ#%lU5Yfk6Wy_v}B~N&q;)<(-uDr%~sEztiW`14m!u13xbj6v{wim@WN&H z?3p!d&ppc)is-)!7u|f#&7~GoS5Vhb zw+LPU31X_?)Y>2fSYjxy>ve$6rsS-opT&A5vAy1H0z#(}wGLsG)ToC2n$+D80SQGpy z?6$pUcd3eIENPgC9`lFCfu?^2a}095T5GiD_+mj%rdB0Unhf@wV7wx;$yXgJsP#7) zX6%}gd=hGcV|Q)5uD}m}Pi{I_3PztkjgH8Q+lw1Y&|}wWoAZm%V_Tv3yt25txtRGL z9|_s2@B4NTQ?6>vuQ@Q?>c?DL3pJiPN&THV3s@inUQh+5QWPH!fLOp|BriaS>_)Oi2{EpZ7Zft^&uzq?oBTMzP6yY;Jl#n3C64HvId9;vdCOans9+M!Pi5-|A!sUsm%SK`9jygfi zDCy0U2z&OaJSU)az0HB=YMh$kS2F@OL`-O%$jWiKu)3lC&K)~I#k6OGBS&NccUIf* zZ1fp9f>+1o^q6WUl}y@Vy~1#Rixrmjkmoo;gZpEw=t6u*r#zW!Ff$wE&%Yyyhyms+)Q&hHIm zl~}bhAn~bZcuK7*C14dkCrLCg5?F)2ef8Dy@~zjDK|srOX}mx9XZ$s(Ec z1?EmXcwCO47E)WOgVckV8u??&V^eBB1$Su=Cpfvs6!E}x0hEKIB?Oa$=zIy1B$kf~ z$pb8$@fnw(gyI??II9-~=w>k^27dFE3}OvFQY4h;45G7p%s`3{X!-?>@M+kW<_Y;6 zK3a#FIvrH#O*RXd9QLMpN$RCe?R7(D3@UY$ z>lxJ`9-NS}O$u&q4yzl+N&~r|O@*V>1+c!U@}NPuNSl)RNL>p==hONuYucdbuSRE$b_Mh3O7o*u5&t3Favnkd^U( z_n7eQ%;3X|mSVCO(YF?Bs1P*-uf*dq{kn|0mbz73hw*|MAuze<V1%k4U%d@urUmSD>7{n!LOk`r(4m zq>e>ZvAHwKv?YVH4QBRdcriDzdXUc}JMA1j_0zIytIDLdxjWPSf%?*Fi`uMpS@nxE zeVM?s=qlq9>8$@5>2)eraG@8i*V5_EVw4F&F7y!i>j!H}ii-1-Ypr_~#ns^VN)XZWeksY4GA@CTi&tQ^l84~QOuf7-~zRJ+#PxOMU$G1+rxxIkt?tRhS@Q1?{iz-0v$X|WYhf^;HK8HV#U0yYH zei$WCTzv73&j9Tdw4b@Bz^^p)0_d8s~6AGj*4`VbioIDM>3phD?LC(>O^y&`L!GR!@1Ce@7a}dOX&6;`; zQR};)Anr&CRsTbn{`YbjgtFZ@+|xK>_3{z)Q^IZT_7xTR?$!^$`pprv0g1ex!17Qc z>StsTA4j_NbUlywm!S?$z6M2EXb>@QO*w;!drl+!?~Vk~xwQjJ}_E$7?It zP$0usGqKF8xkzT1jaTAz)OFN;5y3emU`&z?Oc)lzFf2sGbTQ0hRv{n)t8xOy)#W3E zjUlR7?!JE_J0q$aF_C`3+b<&=b(YF)^*fx|^_l5u-qyU_RUC8oe z2$5WmP$W06)thEA1xb-#)(~=WmCn{U@faZfi??>3r-l?qhVhOJ2k&o(|1pvvVh@Mi zVmF!WR+}TuYUQZ z)PGase~gG@U6ALng#LCLiFX9duH&DS`kBJh0HDq$KsSuz;JE}t^&}wfbII;LpCR4C z`lrP!Ace_(!5b2u&BDB!_{YHCozc@2%$SQlKJb<}&%E^v&90h%C`rAA=Nous@`L%S zdS{;`bpU-l7v4crcw)Qg*<8KPMwSXP!pJZS2qTLasF9^YcwUYQXjdn%!UN<})X@!x zk^p#fwN_^YkE!+IJDf&MMx9Wqw~$ySpilWB;wWYe)j=pog6GSK`m~Y&@jToI=pouq z;57@1s=~xMh=@Wh5x`D~6wu>@X3ifF2uM~bmphBRJ}~Ii?y@<}jiC}}p(4F(?5eho z2WS5Iz$3$p?ISg5U^BXK;}2Jl+4+Y#V{Vu=rnD@p)Yh?W_)>pW+nBKp#R~eNMa`oM zfYRh-HrgEKhQfL}F7c#g+Ew!L-|Twc7oFU?q2)@)@Hu0HiyrOh`f74jWM76C?7Izs zU2|U9JHcN$b^4V{cST>G(wbGC?lR|=&8gSw79L_~bC$xM%T6ma0%OfZYrq&mrcLzn z0!6*sRvr^3p#vgThe1Gu#S5NEQ0in!8<~yboFD6h^c4m;7rqRB`@YXS-k^+uh2E$R z82E_+xqDE!bsf}BnVuF5*};giDfQ-(z@V1Ih#61JrJ0EjE_iyPK~bKyWZcqyhh}#! z%aeLcnci4&W7fQVvoFH;Kl4D1T;+2>l>&P6H5%{Ws65TEw3X9#j7^hj9GNz@wEl+t z-7{AXDeQb|I+*{&;)Qn0g4Q7qE}wJHyp_hurQ=KL0`_a+#}^v|&?y0a7l=S2@A%=<(I0-uP5q6Je$1hEQ#=PIH|Ezy#(5eQ@Q9=JJ^nGwM1iC(_o zCymex>39lBC%(I40kV9OeuGm8uO_%|4dc-tNQDR(SvUmGp_hUl%kkQF2#P*6%olGF{Lu|z4B8=lx?OBVLj%axn>VLg!MZaztjIuhas6T zI2;C;Fo63>;Ut9*3F|D`Bft(u1N$SgIcA_3ARmQFkT9pEnNh--mj@RH9gd(QIX-z; zA~I}PBq1K*_|8S(rREjoW->A#SKo@HY};DIgQJ~$gJ4S6@~Hou47xcf&mZ`!jYcMFb#!h3!IyQdxZ zhTuQy!{Pey=+PrX9&hOSdmch>KhhhX_0Tt9izhT{)ZOTf_csIiJ0Y(S1BLHzMnAq2 zA~pw#3l#H1>f73J|6eX(ZPR8wkvR$W#CiDD2+ok1z|To&!ErOOniD+Q6U}MCk+ZId zSZa914GJd{3kldlB2+gXCq|s?4@f*Imt>f@Go=yrE^*mJGEyUF9#SNi&3RvzDDb@Q+*f z;qO$8{J3OSD6 zIu(tRvtaUjo}M4Php)4#EzRkzQ{z!|AhT-cp(FPKm|f7QFN`QyXGW2OXBf!yUWd(O z$-8=xYpGMIgz}S+Q%8pGAD-ckD`)GJ86S*`%~)q^a8|C-fRl4tXC$A|Nwgal?wm1X z>d^V9UQ;<~Vtfzkd2V4=2~hR>!6WORjfx8R=@bYLT+BSF)sHN6zWs9t3&!X;I5TQo2k{^g|lp5FA= zn92}Ij|2*1V1X-FqH(~{$pgvjN3m9&B-iQ8mFUfq9B>uj;nXp#MaSkjyMLyj_O{3W z_40|&AMA?PuU=j-q}F@wr3sBsyzz2{RH=tmRg6X@E&sz?Z~mb|s#de^^lC<}mX*Im zzj}^LTfOTF+kx99jVcqh0aL)?{sEp2g^@0J;#Gs*#lF|$VYD|wpB8*Bc6Fk!g#c#M z-@NL~R*=|w<|1s*wzEqJ&^I8hQ0D8-uJZ!mHH+Ett!Kc{o*Qs2y_y!8cdDzC z?iB4Km;v??m4b!~b*bhkD`Gfvy+F=5tvBm(F<+!lkwwT$;gDZK(YWlES1b+(KG>0| zIUWWv^;dVCf3xH2t2>y2 zj;rAlOUPBo0iBCf7Zp`U&Y4V~khD+w&MR(-R98pPOr!B=Ry91(U;FBTKK&qGnu(U3 z+Ya31pX?VlcQ>MUZ~PR*&~Y>b9S1S60nReiD$pH)F$fxVeZQVn>eojcV>6By6?l5ZCSD`$)|kCl5B%z zVa#D{z?jS2<~Fyv2_YbE5+LDDfIw&nxgZDmHur%^n}i%tl7^JrPMV}io22=sX$rPA z{AOk)TQ)T9x8Ls{Kd^RZXJ=<;W@p~KdGp@qZN=-qeau1T9!v`#U>;^3VV+=~XI^5? zGQVXmh&aG3wU%UKyPpmT`H6ImrN*eNh!9{XAyI}HZF2<3PlRSLP>fl8#1(S_d>MWoD2)dw0 z;&Sp9lMK2%I$rPri=hDGj>Eb=GU#UwP6H4s0rk|T0G5E1u^P{_$;Pv+BPm&nT685k zv{+}gWN>GV$?OGVa*FXaknuK`VX^AL4sAdSZr78$zq8nd=MBl79^P_C%Rk-R%-j9(O{^wvxNs^&~^@wl|5nf z=8?0jqk-%DO)M}=FY{7V3j&?3 z$MHX|qHsgj?;v|}{ZJmRH>GpvZkf!8Pmf8ZmJGeoXmlh=m0&oRZj{Nu3_jh6(||_6 zflLjUCzmEUO!%K8NuorDfWxd(qZhdJ&huazI;v$;IhmYCcR?1s1}3~Lg`oA^Ic>)% z312;Y4v?esVYDk11kgjA2B$wQ;lZjZ(C_|_Upy^k{Qv^3>NHR((CbG)`L~})(Ul>u zLuK1%x#$&i7Wgzf(H9@*fo&ZSH-!ne7+3{3RD_-dKYxn8>bwj7y(rZi?w8LtZaf2K zwO4I=>7`AXzXlHxoNr|G_7~~SMm+9rVdT{FHIc_~3`-ao%)juM{lyn}u?h5yOT6HT zmPvpKN(3`|Kl%;ISZO>Dnl3hg8IuN~o1?ERniOh*0d#yR)Pd<)YV;8bubj>P?(Cym z4=(^i-ZItqht567is5Tb& z8)Z2UY8T$M>9H7%kTTpqsE#b5=myaX4&5Qi1%?1-w*x*qk=(HHc$O@9F+(FdZxg8Z zBul^|%sjkt?YXm`@7wqJ*>jOK{NXkLzd3a18vxONufK3)&B<5V4jgEE<>Z<$74E}!KU7tLDY{{Cpm%n}D)EnHY4r$qhefuVqaaY#Oo!fDLSwA*9Z0F8loosHN zbN>7cb~|_H;i}G&zT#Q)c#)qzf#>K6T{a05|L1b(>#n;&NE1*=D2=fJ{v(@llF>#F z=nI>1CJEyM`sl`Ce%rVAcVyoG?bbBQS*?$4p|T;#K`TW)ZWLS&1q2I%YF-E3=c? z&Fsh2`UGJ0*FyAJOu`L* zt~jSffnsbhU?y959;ZO=Pe}`wI)nAYgV|Z8j2aE*$}?p)wbiUl3;G=rrhONB z6g2c>k9JN&AMjbPzmDEpx^!Q{-yInR4t0h%gZxwuZ$^gKQ83w?;U&LG1sPuM?aW^P z(5c}|d&Vpsp4lT${O5dngIHQ{OJ=r=2L@A-uQEq&&P(?e2tZ*pB}vSda-d-qtOUv} z`Ed;XrFi`9q?iafz1FffGGL3jStSg|lzZBa9&KaM(YAZ;X#;JQ`ByIIS61eO$MVAP z$8a8aEWZ+LBlnJyge{AYa;5Dr1iJlagL^z?C=73+^eA8Oo41@8KWp>)DYn@^GENn=RqU(@lDD@_yQX^DSsqH~|ijHRufEBb6q15{P451>FC1g|5G_s+%6 z2I_@?V(;UR5GQpZ5M<-B6&pvE;~a5dOQaXn$1M#+zY=w=MV0F}?a3YA0)bCr?;=S$ z8LQjuf~VgS#V6Wije-*ZciQS^d*(s{(L@DowiPi+E_St$mL%5}5l7K^#=+ z)6Fiy-HrWD>MiQ6j}&{GCa!KyJ%m|+xi|>^(>n8vyTq^;zjiNXHVuFw@X<_k?|)ot z!ye!wH_(TB3^?a&jDh5r@jtJ-=xajcp?ASIU{ZA8t#6@r)W$|}%!{2b!-wBO-@`>u03p|&%uFV}a5 zwNMQrdIuMAuuOC|JlNUEa?~e9=bzv~8UT@5h|w45IvJypV{`?2$PimcTuI?OJQvk4 zcQVKD1Wm;Af``I2|MDRy8j$|egDWwSjwRdXIv;VvX(Di$#E${1>rVZzUI|Pt-cP0( z!GJ$JhM`yI1j)>aU@$a>Ok1S;?!tK?M*o!+9#^cv(U zg;JrC8@!n+i(aQt@k&-fQ-OQ;+|+sCraiJW?+E|+_ssC+cXR_X?RmEOedpWq?3n{} z@4PIeyw^}UE=LPmBVl4n6pp}R4oVFW8l;fZ%UD6+98#;)C@48D*_n}?oZ(F7IHh33 zkq%A}SXt-sn{K=9rivxEE}UxpC>&NAvr5ZyLc4NYp^z(QS16~fG;750&m8NH-4WYA zh+#QMNZH%zD~)R`avcX!!M+n~kaBNEXd-D@Y^JtmyMth$BlIbjYq z=n!3qQ?Yv%2wW#?mqwM<8=jy2tM9bR;ll?tEp(+^V+M4I!|UpjZhn%QO+|)nnVy#h znWdvYvAKE9ofLH#2QD$B%p^DeYw5;acf4`s-KCFP(5p_PUbnX(Z_^7e@DU(=p{MK} z{51Q_wmL!a#j!=N4VqW~#fB75Ttc3bzYvqUl;SjVB;RJSrOsJmz^}EsPgSN^-;Z|e zUX*T6$16G_fPbO4*gfV0h>!4Xn8zJXW? zz?UQ$W>bb_PpKYyW}`b6Nu7p##roe$oOv1iGBj>BY74DjRG*nyzi54^4M9dCW4Y*q zdOaKu^(iKh9Gz*jT8-e#7AH8h`|!s)BjmGD1ANqIO);Uu!@EDal3Nqb%naA$ULiaj zyvA@5z7z8^J|Y!j1f4J5tGfhtUD&ibFM!lLE2qySdq()jMbP{2w{-)nh`|GYTd!1X z|7`QaAm`CeM(lB94~T937(I*oQbJNuoru#u3iOA!e6>eo*n|G87k72YQ;GYb#AdFi z&qV4i7-o1O-3YdT7+8!?EE}WcTdi*T0<>Z6gu|EqeChB6d|LkI-C!;1phC;p@uH!t zJpS59R9lju^>@FyTue^;X6 z-s9CE0BirEex!>87(xVGWPHaf#WBRLJpMJ--l%^2|F%J?1@<>reALKX+oIM-w9zodnPwGa#UC<+R!SkAW zNZsR;L9h$eH(>AC2>icp1pJZLmdun{<%Mz}o3n`C!9>VTZf>4CCU#?d*-^0P=zrKs zq#L|`)W1j$qS*gouzHf@e)LgC|LkM9UUahQv)LUZ5i~IUOj*VPXkJ*b)g+uK(MC1d4%}UgSmx zJm)W*JbB?f@O19QtV`?C*@q6zUP@K&GCV%*?-0pTq34gb^f}9xoddr%qRw9%j$ZX^9OeP(m3MO9;4(W(#gLCP;R@ zFkNJbB_Hj?HX!NI)9NbC>FCF&-$BRwFTc3AUMjoo^Q|jB97p?4V!A#VPwkYs4`a zPE0jqifk#4L&uEn=~}f1UF{Sw7bM1@vp5E~p(M7yF$A~aM5g%{ z+7S1de~U0tmmFeK(!NJoy`Wo5dS6$c)8Z}{>D7dG^p7V$eQx>o>&EQitG8H^f$F)o z=k`4MdTdlO5n@u0tFwIOp+hs5Kg*VhosVAj9H+SLevLX)GS&>!Tt8TK&w`A5p9h+> zj5Sl~X#7*G8-hio`;|QaS|2Fu?CN?b{6JX`9il!IWj%4u6uOipg`Tr#uv=sDpU$I~ zcF1I2OoVm}>p7neJ0-@Sy7bHQ>U%rnR-90_b9m4Bb=WB}{?w&^GS9+m9Gz#&sLw+) zV=_XHZtv;?L4Ws07DV79u^RDuc6SRHs}GF44?K^e_a5H-*>(k?EOZm}*hH}qZ{W4y z8)AJXiZ`xy*M?n_gr5EQ0rclR2F;$Ywj2ifN44T-J26pw=5>SNbupufC+LliNY8l) zujqsbw>DlEiWn}II)PkD7^2T7a$9DL&mZ3mb;JRi;@?JCU@)K$WGS+Ix%^r5L5#-# zlQIJLvvPSpPTUdht`b~;D~vu6Z#*kfK|BvV3Ua#IM~r+{d`std*UhW++YtGX$U}C4 zr7>hhfLY!yHh{2;v?TZiv5y}W5?Yrsh|#;LPWTKmQ^k5o^vz!H!~{0N5&LNZbRJ_y znXc|kw7nQ~wTqA3+TC062_(#!(BB=8PfP+4C%=w9f^Up*7BjJT z@r1tBk)1HIF5t}6F=vL`qm~fkDEv}=uv_dd>Vk7rXiCAq#ob#kTf6DhtFw;+?ZfVd z6{lubZ%LD9Ds1MQVwYN`$sI4)o9ip88^?!(lPil-R3AQm4*iszmTWUajc<6anLRoG z%#(Xp{AIZA4#A1B^Yn(*F191h)`8~sB&cSnC9hk3LZI& zqOavO6z0lO$FrJ-c?;rl>D9RHw&3+dh#-3~B7z6iJ*VsJpy;#9OtlgLtq{fI!4YgC z7OW67>*G*e1QX6cm5|uCtPk-}r(IZ3wt3pFy1{@Ql$0t-5)2xtw0HoYQC&JkDc7{D z`{uzJGamc~;nS+&KOV(o9a!F2wdxJ@&B5P1jHYaxzv>NG+$iJaj$DsFl)tBC-dO2` z{$^HXGHw%0HF7~(6ZRJhXm~6Wd|LPBiEoBB^Rq}M=mPrYja8Gkfc;PW{vgho`ap?c zbcwh+1}Y==;8wsZmY~D$(BWT~sZv5%--X9PeYembQT1iWPhu~vFDrF~Z?v_f?)&1~Zt~AuK4VJ%EL{cu zr)#P!iR(rS|Dg5rF=GL6L8q^VvPoFuo*cVPQbXJjDY;W^(sH_@2*jIMR(bOX!%HYP+yLlS6Qr95T|^ zJr2K*rK&FmJgc>~qVI#C2F*l=@&B2iCWyXoZ3PVI4_1Tzh?##`!k}<#q_wk^B`44t z#nr;oRk!bHCN|eN34P`Wea1Wu{Zy5r>*-9NKJI-J*PA1Jf5)#cX|?8#HnUcH>DL{Y zFZ+QyJi<9+TL1j!&d7#m_%}3JS(-QaXEv~r&Cj>DQvXKaB7s5b>61x(cdjUnxbgd8 z!uy$jS(eX5znHVY?oh$Yq*&3!i}+s6ZI}+NpuS2{DK?CbP7pDd z*F;ESw#XpyvF>q^xmpIqNH{tR1%*{(Jw4gySIeIM*tp?RP zr&3#gQn4NL~Q_T!zI)Mb}K?-nTI^P!z0wcg= zFdwW0Pk^)FGWZ%qp%Q;Sf+*&ucw%OrNV|!*Vvk!Aq+tqzA`#ON1%!YZ_%ehT2#qJU zomt|>OD!P;Z2*`t?`#%x0}i;LK?L|orm{IO||?1f@Bj!bnSK*T?ulAt&C z9A5PqZLEa=5xE75Mdal?nFNj~=nJvLy2~PpRDob3+Nik1B#|!!Z1fIA3UwNVfcQ=m zLAS#Nv;=^W97)Z{B1!Z#h?hwj9{Zow}xi}7wA|2%$)Q*`y=l29+uIK4!`1>h`!%pe{UeiMBy1=jPZrA~=Q z%?cTk3>*;S$a>$*1_%J3TMaDY*P(j5>{-i0)7!y zj(ADLS@8i8KGi6e5_}?c>y!NuG^F4aDQ0t-YHUXSkgbJT1?@{zW5l2r zz7DdTDH#EGNh;qmyuPKSZTjEVq%68+#R&ML)F6Nfkw9UiIXWWxTg%v@G0y|Y8>EtC zb&4QUq^8+amQ<%zZ&V2WMukkK83r@lsl3XoW}!S=uF+VkL1=NR-6Yixv6Qnc`i{;7yud*S*m6sa9?u)8i~0^qQtK2sGQer`RD7yC z0}fZqq{>FWTmVMB)tPEhJFF=RxinQ}L4TJu*tnEbqkWh&S=HaB;@MK4W{6FlqcEAZ zwyQ7M8e|SbYD!jGwJO=^()fa$>^XHGLuS6$n#{g0)v>Hfmz4*SP}|q{-~aXffw^;l zAWvJLF5`Igqm<>~yO5Je6aYs+xW5@&&|TW>GL4>P<@|t`S=T0Dx&IU}9d@v+u1aGq z^`-NiAcqo}pp_b+CBZ;Jo>Holm8XFbtghOVeN!Xv+z{}MQCYa( zyfW>?REY(q%anO?1AweyG&I7Q=+U}*skC4C;zak+p#397x%ti4RC1GwKWq z76M&arA+EosnRlWn?yIMwS!hDl>T`Ee?5eKKdLNUTv4)ZDkp=OvKuT4m11Q7jPoYb z-Xf=&WlgDlBcLEq<#vFfb-42+8TA~`Nne`WXGdV3U#VC*P^&J&Wv{3FLVp?HU!+`l zAL{SAhlT>M;WqUZ+c->-BtnSy;!~zq;D2h`Hg)Q@=+dd%nwqvn$Cu69dh2h_0}m*> zy#4ogPR(a?2F+hH^x2tdQzkVHbSsA+LZ=@@AAR)VhNacjj)GkB&{X>9RKBS1xLRM9 zMa|1C_JY#EBWBL;cVxV8*_2r$>ihcAwJg-yN_<25j0%p3>l?)UR;5$q%vxqP@pi)W z^yEWO4|~8E8;UU-f_Zj4$NMS#vBn~*vw{H3rz18b&zr6u&a&(v$k$1Ie!?k{Axo!!O6)e$}JN;~JFQaVq zy(mhXv~lAkF|_Bxh0fa{MGmA;wsD&>nTWe?p*$T~hxv5QUQOYroRq1zT2--Gh+K^b zcpau!U!jWd0=18?^-r$4(poina+MISn(VLT7{bR!TR}t==68yA@5fNYUwe!sV`<`J zwM?%vrF4}kCX47*1XD7&uBe!$=NU+Cgc3{9tBANb3~a6S_bNiPsb?91{r{poEMC_B z|5P4`xzYc#^1!b0Sn#N2{wF1o{&FeUf9w53j>K~}i`dJ6`qD7OT}o1qAMTiIbPKnD zy2se?y4;v_I=N7B2AwllmCCFvr7}eizO#9& zEkGOQBWa-=v7I;- z8zD|aqqqlO!|937T=6N60dYUF?L^>@BSfDFBot+64~jt2i^u~p+#FmnT&MId`H(N> z<6&&iTJ@}(&Ka*ENUWvPhM~Q0lLJ|fiEN$2kEr}$8?hwG9RmvX2_nL5`tXLu9K9AzqSxNYt_G3mdGpOZd7Z_onD{S_edFo6Ak4X~& zhOoQ*1QWZ2t`&(pC^xlc4pQ?qzv!8o`0La;t~YlQ?n$>uzc(?=dj}>QdU_Id4KnZ%Qyrxf!Mhk#rafu+E_S`h7;A>H8Ae3a)H!W+b z&ysMr2L|x0w7)l4#R3Ft*gy~LA-=1f2;PB}@iHOO1Js!R$i$V@1sLiX%u8Kc+Brat zxv7<^p2M{b!Rsui#?Rff2~OKIcP^N41pRo=%J+{*;!>S!gBO)ji5L?%~t zP*Ts~=>U(N_`PGt;*m`xSuC0x+MReZ2pu~XzY~eY#r&a43GF6&tbV3~8OyRYE}-@T9sj3sNqu zoz8BsDXUVAOmqhOi)q@LX(sR&x^-AtRZvh>!0noJ``%4^Z=W=9$&6-BU#I7qXDk`m z!Q3d83lr}I(J&jqS+@VZ8=8n$;Fr=+*`PsXG@vaY*>_H@Sytt6R4uDf?0EaB=LCmC zcp+#=$y5>cj%G-wSS~{?k8Mt)UP=m!{AXi-cijSZUv}o>JvUJ!y{`YHA6{=|Ozu~W^*QKYgJN?%UJ!QhA?0x>Tva`6i zJMlR9cZxom9W%Nt@bv7jWIvF3r!R9fI;oAIuw$xNxzx>*8ozoS(Wc!p7?_e%c>yJz->|fXHiTTb7RkSv9lTrtbt(Hkbx<@AEX_ zZ(PI>FfP(8PSFk|8N>k?0c{!FEdH2U;qTFXUN@dahcMHKpI@G=uS79R&>^aeccD!4F;yjj zm#~EY6d{brW(@5z0#EUINmK~1t~ew$Z;IiL1j*JUOYe$y{zA;ZLj~|rvq&Q7;klyI z$15$N8Xk4bJ#b*|;=Caf4$SrD!)15?ADBM|Ju>l*!^drzRbHzRG!#{WFbSbgQuVo7 zZDp}h51MS5Uq@FYnfYvC{(4|;bVlQL(`XBPZO{;P(BZ9;AClJ>Ut@4!lS*nexy;33 z*)esH)m@R+`m?Ik=fbsfYv;aNnLDeKF^pCW$b)zLYu7r8&}DCEp!ed%fqBvq{+z+O zon3v8t_L$IHXiOtpv%c!1#opSE94`1#4ym6;I2hkE`l#hfDKKK7;=)&K{YC3s{%5t zNx!x51erM|{90GBFcbD&(Nd2h^)2Z0=qL3p53L0Ez^d2u=#P&FBktJ~!ju+u{_UP~=m_zO za{7*zdi%=9*k(x4MO+ zDsRdwRDdPo;St`hAG3_oEL=TATQ{-cLU)C1_qzLJ6>v&)$mnXs7ndEFlU$ThXb#G67FJDEZyq;tgK_pq z5ti|)nTDJANOhrF9o+>!cNbO{DD*0H8U4il@hfXhN&j55*_v$!yKT!- z!6!2&Csb<7gQCxqxZvy-Gx^pKCs5!5}LD5p|ELl1;{v)Cfz066y!ALV+y#ac1nEDm$a>qB9Tm|h+H?Ob`_!{Zl^zCE)WBFL$ zdosA5_!(l}n8=UF@9xa5Dj6aYzzb$4KQXDazEqqhh6M10F(fc=zga$gNI}WsK`CjI zH>6I~HdjT9MPj&r&Y(UA{%i+!^2g&j0Wm1@Mxd^Q62cS{Xla`Ees*V*BEkL`%BSca-=T0Yd&OOi`vqKYq3H#zM>gjbVvw?af zNvxt@$Hr8c(t(JzN&tP$LWV>`!3b#wv}CB+7=ooZeU!NIRBJF1{rF&f3K6?Ch_yIN z(O*2`+B!fNR~kT;U%a$$!A{F))Aq*bjJXH?syi^Zeq*W*6RQ-{faT9Qg6biIg2nZi zK2<$tcA2bF)h2nB7e^nHg**C5uguD=d=*os+VDAbRhGY&OU)ag7;V_88=T`GAc z_6{g1BQsy-HuRRiwhIqN_%+8c$&`mQ-B@#{*vuQu0*&=32)BD(?)pE7oAn&YHDdajOtV3fB25>U^gioADxY8jKml#6x<9?^|Mz!IyAhjsRZyb+bj1T*ZlQNko_l8{Xk zPT$ut>gIc^2A7(!zjv^x?SJ#BQ2BphTs<`9WH7&2TO|6a1|nx@wt5}b6fS*^&I=(P%t(->21 zE<@e4rXj8YTCGB(mHJg0R-5N<$lv$dmsurFD$ked{zcNgue|KJzA>ZsUB7_@3Yzu$ z1{DWYET>d!l){Xmb<ZoNu_50RVuFN2F(skH~5BR9EGp7 z39Y=H>Xa}t&LVhZASh!!L5mCs_&;nTgf7|yk3HBl7}-JFS@bD929HIX@HJ>d_Ormz zgd(tw2s+6Pnv6uJlSHv(&eexwS#iXZ)N zoZT6m9e%J8T)jc3B=YKyWDK8)%V}UzW1c7nFe7mfjr8;i5Z_tlW9nrA>S&kxN};I; z)z6HDe4?7Y8c-lMKp?t`ZO~K_f^kh=gF{W#(}_fosC3}vIfXBVeyTR(pbo;}_MqDn z40_x_ZbNWbFgUE!v-sFz{Ku_dTt9rt;$xiyjxSwy{JyV_a~qB?TY4N{bbgBd`^+ux zu37W$Eoa!12)%>OqUG-%oG^C(1vmozh&B+H3Scb<*5!p{3lE_yhc|y+U(lc!ZLj}k z^I>%5&_Y=#4=mUZ?*6l(uyqIA(f^o1#CBR-gn-O4$@28h>g!4gw`$1Bj7a(R$w9eG(%56Q-1T1pg) zY=G^HwxOSa9IOIzbl{nd8=u(-@>HBEE8ny9Tn$jzY|8X8>HW{4zo(DE!E~S){N@r* zeilw5&nyf(cw^Pzma+-=yWEa&VJ2J-M+zT{-9UTsUj5fhjI6QbIx@tu1w zkO*p+;Vz&dqIqN?T0%xl_wbC0FYz%@QUD3>3bk&#L~FKRCqlkw(xyq1HUXbJvroF* zy=KFTl$7*7nR0Vh|B-k2ZZ9&MW#$U=nI%K&Z#Je zcm~&7FZy>Q3mvKnjmbgG!FLddTsx*3U96}it>5@*J&w+PwQXV;o-J^KeXapT zc>Vt(deP}E8juP0JNU?ie$lIsqt>ssZv6^`ABRGCV#j3%0a`2?;6QJHfMY2o|FrZ#TBn<1FcC2qgNq=ptVVY}zxMU+{Yp4+u!7v zZ(mrMR6PZRFYPsimN+h{z7)W->Op<1;4J{QhoV0^X2Yk8qSrP90M4?;H;R{z;oZ_= zm|E`a)46L#1vs4J0blqBz+zAUz21R;t$uHRum}p75&()|s2B}&M3IiY>Ml|POjYu@ zogLxY1Uzjylf*2+T7{Z7SEe4l?mfK7dJbKFZ{520Ko%GXvflgj1``b2 zXmyj~I7Y$&(gkZaOpruh5EkCNaYEnMABK93N}kbj#NHogS*@7^T{cdYmc`b7wn@V( z$!iDqzwih!Yn2j%QrU9IhSTv?ss*JoRk-$(4N6F=pc?!q`to&&1%m7U86O2=bE}!j zAm})N?5?@o_;Up^Wx&h@SvQ_Zv@WwAVv6Ac0qDsj_#~LHu($m1`>$6;t;f($KJ;w_ zER22(Mhph#Ltnj%?te}4+j4fsg*(1NKY{&?ikYai{q*Vf(-H=*-txUi_P`$S;60C^ z`O!Id>`Oxxj;mnZM?eugfX<+gqa!z~;i8S8a)snHd5DZFNctE5I^9vQGafgzf*>0r zVu~OcLoC(#go4E*u@OTcg0-RM@I2_T0b&;9B>@XAJI5HzPz^YCEBX=*m|w0Rc-L%& zVu>o}yJdlmLUOHdv{a)=<}Kq(HQV(jUwyW3a*eB^Ooo?F=4@-}*Q|H?)%3Jd_blhB{ktZu{-nE$)JQq1@PeuPu76v|)h zpF6ZPMUeSCkSouGf?g$Mr;Jck37vl^P5l`9?H5}}-*}3B5EOy?4sB~*aqEghuf2L`<<^z+w%*C7F5I(j zQv1%Fo$Zs>?O8Z~6_D=x9#o%xiu5F~vhzwSI=QxTR4JJD#UH`6vXT96L8oHt6D|I3 zKQOtBpQ&U9QhzrNan*|17E)?lNTP2M)Vn0Cp24dV0%S&DaLgcAm#>@n8ZbWdw@UCVNVaL1YfprmM;F%495{E> z{5?0lIly=I)v05a-nsf|?=)})Ugj^~vFi_TY-!=1S0;_R=cmmhmjPkvvAz$1=AVb7 z@9=~(1uVA)r&TR`_$l!C$Y}!$9$K`uW6hXJBL{!78_IO>_~BN0rNc+baW0 zGrejyNpIkw&sH`C{ZLq4&3z3@@Tu^LceN-N8gqsQZ?3cFRAe|!a=meM-~6FvKBo@6 zTg^wpqf1w8o_A!*ID_o_2`8JY3;87SVEfmF)$f4mGxLWGEK*vlQmS7%e*D}pcXn8% zR9Fg%>@yzg@?FE~vIQ+5bi%AzlZxb)^8j`eD>@ymPYxP)c{#ZvE0=cu+!)4+k5ft zJ>`K^jTW!=T*~HMg9kOw8x&r+sp*L=H9L2_c5a712}s zoEcu?K9@Q#ws5Y1i=fS54h?s9%iMAfkiZEOyeHr}#o$Mj-T z##o7|Z%JQ0`XF!o+S9XU+&i^jauomVt6TP-)_A2bUx77~SW@()67p+r!EhtjKxa}@Rbz(Y5 zw6x|W*o4N>mAh?oyF#uQrlmiIamn|(7IjR2!CF0LtVLZ}#~f&5LP&_Ec)FJ8fGHu& zMcN}Qa~&Xys13o?m2~T{G!gRK6g!Hx=%Q9(LbzQ|Ob=nWcTP0eqkS~g+kua2v6&L* zgkm$%x%<~xp#P#laa(bCQizJGBg8ipUKJ8aba&O+ME_Kg8@3vb0mtHL^wD=XruDiy zi{W86Zm7DReZqq|7uqLW-4JJPN|n2O55?@zEoS5YSv!m+R^~6fAljI}_@Zca9>0F! z1zD&4KWmyhZ=7A%HER3cwU-gEqq3M%f)y(hL6c&w6tmXw%(MkWJxu|aTdG}~zTf6y49i|0*?(GftW=J+W=Issa(ZkVLA#E)+4RjMm5 zVcgcv&EOHW+ls_fhZv8KqFj+9`73d2Q~UK`mz>-jM?Y}Ut&%R8Q2;VkA!_$ou^T)H z^3c1e5xol;Qk^{)^r`xXK&vLYn7jnuq2a>feUJwptiv}i>>=q^K7`-x!r%ErI!C#v z9u5^jb&FfNKNdl1iWjS!n#O<|2pegVye*gSOwDSi_NFi_TBR~sshuwX(L|M{IBD&z zS*bf|N{HK*`vd;!J5vcDBt-&qTf?axA5lGjE88jpgyG~QO>3(tZnZ*LFS-xCe^UQQshkCBg~rS~)GljbVSmr~=pBy&&&iWax4*Qma(gMFYcKnt z_?hgT;Ng-^@Z2yzPWbZ7fYuF+T@@m7YQH<+Caxv;AoWc}oWt0_4QuudYDP!izGK7K zlqBz6H|LfOsCWxZfBS7Pf>d~5?W?H0s2{IM;#eNYp%My(rtBn};>eTTq7L}v_4STy z|Mu3FH-{8AO&C!*-z|}D{}$-KMcW_6jUj!kzgmjv45#HZm@Sn0Ev4SUS>u4@z=rQm z&767aJNg}E9K-(u_dp3FXH+l~)2J}qKcoF^&=?@RMaljKjjV`k*qo+X@ca((T zaP&TjrEQyhUZ-N0Fsprj-N95=w^j}}zJ}s|t z@M!&lp-B&V?;bs6nI+F0?B|<3Q>t2B7G4ELcChW=qN!*E5RQQ=AgP;Xx-;uGscijr z^x2rJzxvha?N)HBLdx{O!C}c>2DJcS4G!FaB}_ZRRebz$bj!ydg9#`8dV(I}Xq(3?-5^m_j)8&@J1o40GCBNs)k(B=d_iXh z(G3Ve;HP?eew_m^ulTJ%iF8vez?$ zco-#mhIBK=9@~J4!Lz#zAz?s%cAQV?#qwmh8@o<>*iJC5@;_VN=NEIaygba=AQRky|X26<;AQ z8@q<~=K)R}aB2*Z%3v z{bPRr>hsrLSaiI>Ztd?wTZ2PjpawMk_D3*kTHlS6hpru3YSjS158rTSysuK-dJ%~} zg<)_vi?I`=GZG_`E=I{GV8d-Mr~{44ZBH<`Th9;emJOJ~tPo{o+Jvd`A< zxG$E;fxR2=xcDP|`g@uYZAUw~avWy)cO>Uafc|RBq*L8jZ`^4KW!v8?`dT+sPN4=GIxwYvE z^TbkxYPsMuzQ(+4{Os>KhoIS~>+)A@5}|bPF-_c=z=YIP9I(M2&)~C3C!S$M+oZ*R zkcpq8k(OgEQ4-zt5QL@FJcW}2t7<9u{luZtUR*TN5_ZfPse$@P))d9KWmJyY8h z&s?u=GNuIFb)Ia0Sxv^M`3K%TFn?4=O_@L2Q|At(7|RCXuQI4in`sYay5^Nf^hQNb zy#WD_atGyCsA3GGB{o7n8tSF+vUYfBG+GMa(;Lz7Uq?5o9+xP`He1Ma;1Rd~sdikqXAjYjoDEn+ z7xCmVt;bEpSDD(bC?b-g9D-y)wO`N**-1)edaB&A`kkA%d>)uzZ_W!_YUhy8!I_6I zI{5nS9e;l4hjaTwAoQERfC-jm2ivDwvXcx}rGC&Ly|ScIKNT=rEZG)=Ri&RlU$3%S zLwfL3pDCvNf}~VdUS=CK_~y4)@3|>;m?fNNuHFCc{zb!XKlj&%4t`;N<_q+jKP5kZ z(__0FDqW?u8Ng<1C{tyyM1a}C*Zkbe5m|>7Z)wp%*#*JUM?u_QK6+^WqRE8w9f&toeEF;`|Ji5FEec*2%+mZJb(G(lB?9&s&q5 zCYS5ofw2Lt0f5jjSCTtW*e5NyED#P34Al4%?es+Z_Um>QT)nOnopi%iz4{tml>&SO zJ+C6Y{c$%zI+D8uMzJus*30WQmw-)Up%NWpZQo@r&)7pi>&1(Epf$S^{i!9&A!66C zpr_3{I0~}b_v~p$m+=vNPs-5RT_}3sdl$Up(LL>5PYvr)^n`E^-j;YhysjmCxHk_c z<^WoMsjaSSAGTNf{L|J6CfaiTtJYZ9U7!C!6ZF=daxoPQ<1$c#X9~RzFmq3}yhSDX zu5+=O2#!Q=d9;nhaKLVseC%WmhP11ZG=qV4N+ylDI%*7?nG6`Zpdtq*ITLMkm$)&F z#zz9x6+y41noTBiDkx(IbzWtKBuAoGPRFmVF`{1zLZRZ}dp`RtW`{>kCW>Cvhp8cU zcrk7&t`8jZj)CVc59-7mq&l6k&p>r+iOy_p z+yeli&$N`9rP9IP4#qoJx>Q51!Az?Y+F^DHIl7X;G2#@X#0?^`bCVr9OS17jrS(hz5bX^GZp$6!(7z?w6m^ z_1SRZJZnD&MbKFU zR>taBqDKhu_@~yGc#u*APPS&>{{8zlf{W+^C`N_XCV?<&oy1&&zY8yV`0USTA6^uW z2f!cq?PquF-`6=6Tm;4V|HbGL=Gr852A#nVfEGMfUweH`QPG;$K^Y#eWnx$yn_1Tw z_HtLb7+27v3wjJhia?Yq@d=K41pl*x8PPA%ALfH)Xvchz4O14MIt3PWaY@sNuNdMI#*hs_5g|{3VnAF%$UqSZTbkLV&b#$$VJ5f$ z_o1hvKfH>HUzHZ~g);@UzVmK2iC#+CP^S#8Q01CHNvBLQA$m8QVTo==Z<%sc(c9R6 z;44dlEUpcI39=(oM0}_Eoq*bydk7j9MW5u2WH~RYR%VEbm7+@!GFjlc^w=?WK=byk zSDQfNm3`|`7R5e@Odp4$&#b;sZm2VqUs(MNijJH912_V{0!My;t!>eFCuTx0rM9Vl zDgd{%wLX7h*198~%xMIman2`4*3CNc{M+JW5XW|i%T~m7mVwE_{D5c^ZgTn!)JvJ8 z`$x9{fJdN4EwL#MugrM-*Gs1lvYnls?2qUq7)?}mqfM+wDYc_5@4SPy*riIPl)Eg& zOSWgxT)6#XeE57!s3R*hW=x2?92x@`MU zd?1PL*3$$eagMH9z2ZB0{=I+HQ0EyN(K5i zqd%FqH=o-79K873hBuZObXi(kdhX0klSk>Kqi%b6!*Y9-gw4n_mE)1Ww(o``cYX9K zDBd=><@AGJKK#d(qefZKvmgy7siA!glc4ujKzFyO7kb7E1kUbqtLZ+o8e;lNl@l-p z4f=?xxvw}FBCz<-LwNkyh~#>$MVNn~oX^it=37w*`Wkgu^OY&qmlwbkYpP6cPL`?j zw9sD{|BNn4k%U5$l#+ajS9$c4af3|Bg>o+2xP8^C?Z#|QUYKkeH13n5 zO0VQN6}2wz^(GRUzxo3DqSp&i;f++(aIde%^!xc(8xO`YW@;)!S3d>{dGCp7cjETM z-Cp7aR9}~%H{!|71x1BwBPb5iRRys$5muY*t{~dN1x#PF*d2wIIo@Lwno`*jVEQr3J zQwrGrdEgQ0;&qqrzIEo7-4`a_wj>4Qjs2C4uWC%YWD)e}OH)Dr;;)V1p=Odz`%4wu zm+fia_rkvIjSF_4zs?WvFzP3+mmgq)A|R-txDigHLu`=ZUQm}tRMW*PDxg5S8ftCO z9)g(VOyqCbmY5r3;2AO7W$q`SZq>lzP&9GOa>7U(N}u|G56c?@{M> zCuhw%`5oZs8SL)O6xYXd)Pv89>&tB>y)jio_xP%veKMU|RdQx}PM;KGrBc!$Smmw% z1^VOc60=25_hO}Sdw8y~{5ZNk3}LRNiP+G_r8&3-+{Ew>kF9iIV5uGlT@9xY%^y1E z@FI~lh7+xD?%{C~tRL!ZkEnY9Gf^AzgGVD1|6glY0v|<{=Id2;RrOhY zRCo1}zS389=jcw-S2}0sAO>@xW_Ta8}V>cUg4> zbrya*6iq{AO6V)hSS&tD z74g;t6@bFm5ZhdYLS>|u3-1wff>6oc$<(DYnRH#&Tju4=;AJ(96LQVn!fqjXsK7?q zteUDkJw6redHi#WkJSL2P#Y~;9O|RDc!Jq)Ni_j9PhNkbJUQLnl*g&vtWE)D2)`(m zlQ^jgDW3ypfegnLaxpg=ft^-hGCSn7DyTh|VlCJ_Y%P*-1R2Z42LW~jc|x=a0umG( z(g3cI5s>Bx+KWUY@hlLA_(Z~Sx5%3Vu+N%qrfs{=L0AOt8fx=LYLyx}-+iQMkw+^?zoa(k@kFvhoqTYn4Z(0?&TVXn$|-K_q?;{Ju1yga!h z({o2<<~#)CWc0uY@yV4t1lL!+Bst*L8`wM@g&} z%3_4IH3Q1yrC2|t{JXIGum`arF%Dncaq;C!JXc=b{L|T(xy`6c6gHAAz7?B@EyPx1o1rR@8@0qRiYB1JaCDU| zAXP$yTtib&j06(b8%29>cxajbRwDeGX8Jh;MyQB(MIj1`k z@&;<^LqjLgs?4I)tVtz&I5sOOA*`VPDF+(ysd$O#34&5UqH^oeqxT`zj$;qp1Rn(d zfsN}$Rqy;xScOl|`REdtF?lxUgE1d_QPk&i5%r?Bn?M=5B4XrC4tNnsA4Uudr^_UF zSu~<$qSro@cLCln!2luzO*UajCY&g2iB9D3^5B`6P2Vpj?jtD4(;cmXCx?G4@m$go zYeW}>q-W%VXs)>u=gcHx$})MSRbS(exA>Hv5`T@}ir+ANR+;-mn5=L0)-*>;2o2FQ z7}V$a3?`Gom!}U7_E0*z@cGw_HmKjDVz~dn zeKunMNDrI0*kP6W$mG7{mAwpq=TU&M121|Op2p)Iz9n9sFL&{t`0cq87h8eBYty^* zU~ZSMMXylkTYOz}aXfD&?FDIbsiq&Ob^`reD_zrWs~j^?51$SHPi3*P%+Rt%ID~o# z-|Q5=p38Y%QV&q#8|mTunR}0lM`p1`sKfT4{czE7D&QV*p@Pb(h+84n#F+?9yWBjb z#Lxg~o)Tz}1ZwfaF?k4!hY0Y<4Nm4p6GZs!QCO@yxNZTOLWtl+*b^Tg^!TFY9g7eR z51rHo94@afX3p%)zHuu1y4s_DO0A~S@a?San)=%^$21=NP>$TU=ExtMMo>MdBF&TJ ztXP;YnKUc4NLLZhl8*3@V>+x6hfc8y7sxeF&sFIb9t9~k%OHY<>EOiOWr$>HQ^%NUn8Wt~4| z!q%xKiX{ovioTK#K#+=qqXPG`c@1Sp%2Wiv=cK!z3o!XYidjv{+i>nw-C0V1|3A&x zx|_m1U9s5_OT=x3lauBgjT1cGix+L}%QqxOQ|1AJkI)P=`8BUdF6YPsPN1 zcF>~15oik>AQZu4kdRq<=@W4j39n}aLfwc62n`L9gv3@LxqFESn^Cvkh|^N)ASb}j z$TSW!&o5l8_l=3j>}sPD*QIqVenBgzxX!d|-$5;fN^?KCrOC4$OR6b09xhJAK8>0tHThZ%!>f^~OD{LU?Gl zu-8YVYBcn}KpFy2{;ef1V%69LsK;OkQ57vCAS)Q&IY&q+rwhtFQVb;C21vhnf)eYP z%cS5rWFXPz2u=(;xw}w4JBkA=S_IYt6d5n_X_}C>6cs=!*<784BZxXBl90%1-Fcr^ zmu?NJnyH98`)6T~f=?v^KqjO^DIBlj!E4!XLuC||@+-kf;n6?|MJ2ox0}g!xWWcO7 zzUF1Dd8XHnlfLtS02YX%0+hn{ zCX?UWV*K+4t;yqW*Z=E0xzhsFczK8~CuSJ72UE|4tAsi3LRq=HJm^o5?y3+U18FiH z@)lS1Dr^0|Vtl3_gf+LA$L9y$y~U3Q00l_kYPXtI_HFRIcrn-~{B`WOPb=+-n#eQN z1>4PjP@X>?YTa&O4>;`YWDORN&;!PM+x4t1Ak2D8OB!`2LRBCo@jxeyk+b2iH67Xm zP=)bJzy^>WDJTljTB{g`0!b4?y1f*>Et>DR2nS#TQk92N55aeNQRFTmf*G(zzuCv) zeldjuhA5uPaZ>oR`FS(wz-5!4NSS0ZCCyL<{2)*-(ch>xDA)AN1xj#io6(rL{2**n zvC1`Rp^>f#5q~?c&{U=fp`0(YfHf*+qioTMA`kASUnF9sK)?T&!r6xAUSWydIC+&l zXg_eP5lm3fzr<57_BeTkQD;|^$zOduCREk7b+=^}0_xt@wlz)aCOPhB^%oDxZnH{x30;SmHB&+(=J?}UaG zT69BhM-ux*j8p<$lG(Ox|MJY%Z5u9Zn>pD{*SGCEeG*JK;jT}Gel;}2IP$yJHWzD& zWOD5K?!IhS+wo==FL?7hug4Z%TG^X7&f>lvJpa+qqmK@KwC&riu9~#{uTMR5?%Xp| z+cdt}Er*1oa{=kT=c!-6kQw9IvlsvHROMyi)s~fO{cP|3)1(LRc8e(}`ks57E7h%B2!O7#bpivO7VDU|2L)2@-lFEqIQMi5>?c03!Ov zIaTZ`VIi~GLq*&pXLjzoAzmyqSJgdo>==k0JAf-)Wm8fnlk(Gmth1sA+!hUWjp?+E zTknwF(-^CWwwv@|?3Ka+eBD0Aswhj}^w?uJ-S9M9SY-M{c=!DeK-LneU3vcvvpC{z zpu4fJ^A&zq=-TGVW_CET2{*g=={{9`JUtMf?4&jo9j$#{gViCmw znp>`U6)rmbpaQ}6NuqP~cJF1b;aUgHM|i(c9aPEWq~3Suq{FRxQl?Y~ zl_oFzgihbdZN%kTojS^R(?!>W3Y!blUM8y1F>-t(09UVut>Z{-cbcWNoZ7*$RvkWr z?eMlwdBWSl&cL-6qsgJ>v=qC^L2_Y^EMOH*uM@uH#vsXoi&w9M0Za?W;d(d@XcQ6> zMwsNtBw`YZ3A)TV=rCOJYs$qsNy8)!n?&l!g94Y5P(;gez~)5fogbv~6bxgiH#ict zEwyU@9UbV+SmKkwXL-=hqm5m zU=(@jkI4aW_v(t9BU|V^pWR)=@^-C#!iIdcigGmNtIGWvlJtgxd3nK*mn60R3RQlS zgHoy8o5sVAys^-g=eN=KmaMASxaukznDPHg16OA^ATfy!!jKMBLA6K+>nFe6W}uX4 zam@%750MTw;c`Z&iE6xc5*^feH8G7=D+ikZHfl0JB4E1fkVkcn2x?>PK8<|^OdP=1 zC&hj77B5bV71xEL#ihmF-QAtyUVQQ5#l0-cvK05leG4tn0%a+-`1POM_uVCzyIdxD z^JbEnWahm|e)ID3e#)3pU2nOX+Eo?GtVu`}NJu%^n6+EtFyGZS6%xGtYZMzSycn0I`d(ki7 zRu}joD5aMQpwL`E*rS`{P1ftR zRcTC@`fwERcpd|-memlwK2q-J6$9-ypG#41u-aDaqt}hWk1^+H2_HTYg9|r7xYUnR z13Ct26`Urixq9gzCkAvGK)8zgBI!`3g`H;e1-0S4g9%@+d$Nb^vzt+J?x*jM73+gH zOZ4>WWx~*o^oCLyL!)4XdKB2N`B$zw`Co z$uJ!MqQ38m5S=4To93P79X=i1nb5au80&6hhCGwjKDJ&T6@d}3;7I@V8Mq@?ES4F@ zmXXjl><$^s-zTny?(tYkjEHc*kOLxyo|JVCG}{IN0EPN^szu)p!6qa_89hikFx2kJ z>(jhZvSfRYC#_*Jf#pfSX_T1)*)hewS#bQADGdo6LBfwloQg6^@={{rj%t}b1j!Hz zaemC^xvPvU|Mv(84qha*y)7+OW*$(J{)Jga5HX%xJYb95|FxgHI~@-ow+Q7Do8Gns zce;2@+q|mO5qs#1U}d+s?YBsi5wBU0IHeMp1BZ-P9jD+Jw%v@`N3VwdKwUqt=iqUp zwaN3|u=CDRNtQkP#lC?O91nlAV?_v(vT*aP;&g9J|{InT1#P=RzTUB)>xGI%V zV16t3Dq~U;mu*YSK&cetb)J$Wo>APORFl$Ot*+=$wU=gSqq5(nQz z?-R!|zlXBw9QUhBrX;Y9^qf~HGJAiqjeOqQJT{K2lfaTpoY&zuUn`$trf#I-^B#kL z{==WMPdg0t_#f$J=6nY0wa0$p0vV(2mOP&=lEUdub?6S{<htOIf;zd&YORK z2&xk}o3%T^I#%PMxXT;oT6W(#Gx~rRUiPK3l6!rg36y{HW4C&u9DSTAKSC<5sX ztwZXC1;S~vVWERQWk0)3>F$;y*Q zLknEDv9z_cw6r?5<;SB+Jm|iefKJb#q32arTv}c{Jv~v2QLnuPNs}rHtygjoVB0C3U|wE22JAHTeja){kim1M>DM(~Yi_ zKL+T#LKn7oOy4!mRMLR6W7g4d7y=IYOYZla`ewZ)ebDZRBSYEcH9T2 zK>Q^V1M+ndO8oVafoa_q5ZU~hv2}MXyzbTOeA&0aAp4E~M_aN;>V)Wl?50Qk%fD}y zY*S2B_nm7VSbqG-A@6Ku>g5|TQ=K_r&Zke>s9&E|3I7OrS+xE@yP*%0%r~12;^_F% zUTvH^=*#vq)vt3m>C#FdzzR_oGLno^Jdr3Mmz>r+s6i>EAv-bcYX=u_Jx$Q}M0a!+ zz&#xik~Ja5m&y4W+eeO%_9%1s8X2A14Bq$(zZR4h)J@vLN9Pswka9qNgzwE~;4v|& zSQ55O$uxeAvAnna+IlNAaeb=+BBx*7CG~DZiUQ~_hW0i(Gqk{+(hynEq_x30!}Qpk*P>7d*2-+t^LB**(WSQiExFho?Mn@m}v& z_27et9|?BDitalyaCp2{BDd^giGrR|vp^O)@!>>iw5dr0I!8*)b&!kxlUS|aXIXcu z;BGsR&Z^`(SL>exSpB`x_XZt0UoD}CsqsA;!W*el(FIyCVPqs&t8%Fa9`5l)ckw(%G)dRlok~Z7>NJeeDU-q?GAYH zV0f02{WQPbGzF>LVJU(DOxoU=-WClouJjHJz+FP;{`q%*Zir!ez>AU7(@9(=3Z~eu zPBTN?@zJ#PK2)hbzPFP;-u?V~ zyv(qEBB)ckOt+1rDfo---e=ux4;+X~X0!fR-J*PnC@8ylwX$Z@OTBtp?xpijphTZ= z&Lyo+Gz!r|bxfD0Vjc>nHew>0S%un@e({Toq_)b_*s9YHtfHaj9}l>`XGzj+0hF5+ zRhs)^OpPxxjL8luAK{UKQ^*{A*xG_!THto8G4X&RCR zCUjdBbL3yb;!57tQrDvUq&C7guf5= z;veh)8E?PQ0m&|g(Ccr_9P3ya|9EE>3ATbOeJnz6$rb=+w}b7Bfe>zaN!Pp?pcNIU4YQ^sa#Z?a|F*YTPNh zSeWcROwNh)F}an8i9M}kw9V)EY z!yaQFjgCk7eWgcu>1>)te;r}oXlb8QY-;h>Sj^oB`2bT-2>U^7vqt-+sa6OEC ziLRq5Ccu`v=ObQS(Sto(mKr+=eG)y}Id!SO5GzXM>U&F;8NzS`0*7y!p-Lm}mFkop+Alx&kwMLQ3`V4ltAiCiRjTcK)OjSKMsD{o@U#O~Qs4{#`8D645sk(osc#4M9<)-BjJvAtEt3cVhp!o58Qq7lnp zQ0TrE9MjmR=Zie;Tg2_cL4o7bV&<7K!{m{Gs#zxFizJ?uuS4I(r8Mm^!_s0S#QIYz zt{m@25zl2KY{o^?9@#C6#%|(&faD(26K?XwHH*2<@xn_5DxIV%zd!Fcw#PP}hDujz z+q2VI&skAH+ULDQ!e+%^3W_S)Gn}5c4rfI?qmzzEQz%eG8pek42jyz>&B(HsgyKmV zv1KdosLgv*pQ}}r{zMujS_s@_fLMlrw)(9c4f#0N8Ae0kW%%S*&H@Tw<5}J?wNxVH z*4u3&EWQ@fVu<{L#$jI~wYxoI7u1ex$K;n4?PYH%;dS=f%(eS|NBm>2hdRyI>Q_jA3*Tb_g3XyGGn56bl1Ci7L0zu0uA=fi0V>qPr|S? z8%f#OnuMR>{5A6@gzF_$?jrnatKLXSt@P&zuV<;eZK8SKBe3Y3qfLFs?ASM{_h}vu z%7=({-7EB@yG)Mf-Nd%52P8dvhCDhVB?9V#@~%VfrT2$J&znh0wyrAadHT3an&>(dK*6$Tc2@R}FB%g0si<6OV!mNNccs81>lCn}hPL3>mbbRFT+ybS34WoJ zl#GD!wIIQg0D8i>f~md(_k)r$p{1YuD%Ul?pf^_ zX6~E0z^wjK8m;exNay1r@Y&~9MxT-P5kW)#k2L73LJ*;F*|`*#`=o?|<$ncUgDTHx ztEVM#A_7}1w{2*7I_BTu9MqPn{-pBH7^QTr09LT8PMIVyMRP8bGHX`M%zFFz4YxbF z884Yx+a(=q*k||Tni3GLb3ftpj%PTy;m0ep#E0p-G0F0cuJUUB;}1;|O&h))^5M?z z)BRk}^TiADzVA0&y5yBSb`hPKm7d9`xJhd}wV8U`k*%EHugHjMa-AfbO4>?lndxUZ z`PWJMg-8CTT*Wp+f#F7l9TQwhss{{`FoF8eO*Or^_UR(RbK05N^ouxK_!HL=b5z^=U(y%ulZXC>UjDU(MekWzK+;TQJYH;bzk6`YJk#TkxDg@R(mv z@ce{daERf2%RGmbBRk;KZ2NOVU)9c%*;7Cc2)6k25TEXY@k*W4@^{o?e_hD?>ly}C zAR(sH*jp;^jCgd4a?B5Jhy+_+`&s%L=-Qy5L+of8rok0xgrsc0B&w~D?3^Ya95 zqKU#ZJOww=yJ2pglAF&0U}m18n;6%yFi#mNGyqH<`9=yo9cF_R3Y3t-D8ZYJb{O(O z^dhAKrNLNNHH*>IdOBO0jvSBgro`N0TY`8JR(J5MTlu6RUj9bXq)&n zG62?x*g`S{@__-{0LDlFEFLk0Bt>zC5=s-7Mry%o5DQ3Z6n7}GG{7Q~4@Qn;LkWap zLGUeNnukOYMMxf$NGJ}3U?=8u2!M!3vY`0yF~jj?VoHbj5P3*0l<+-vIDr=I6mgBj zL9yK9JrYJl4ZwB~r$_*btZl|iNjs{ zi@8xWc~hvODa>v&dS%xy5V##Fx~mZ=xElP@v9Tl)^7AU$MbG;iDC?g#S*p)}U zk&aH^wLuAmN=RdrCeFef_I!}ND5+3s2%1F#AME*_8nOx{1|hUaYla%^HXxT!G@(2Y zVvBSSsOWAHavDVy$^{|XNjrrG?DiqIPz<4b5Wr44BNVV3j~qgg-gAZ%%A}P-wRUTe z3n=P)?r>t6bPFioE;)+rULYK6Ajx8=c~2BsgyOju3C9^o-WfXG10du78HfK7Ga^Z5 zsC17HnTO)K7kgtMP8$D?pYr3o>C$P2X=RmrzpTZ$0Na0>eFCN!Uqf{(yCYT zMiV+E_`09TH0Fh-=Uy9YxH$gHD3F9}b_kxx^}*dcBu`{R;N~5oC-Qgj@D3UJw>WTF z-#7Gf@o+0&F?!i|a2;PEdii$UYJ9yqr6j`o1v=qFLy5Gs8uCL0iA2rnAZNIQu@Sk?h<al^~c9=iAP1gF~IQ+3rl_ZARw z*hy7LE^q=TCf6-EEOqcDN7y7_j@ljw^rrH4Pu@#0UKV3C;vgLRb=d}4Vk{Ez1BJ6A z)gv+(#8`?CmV75WVtg%Aeb;@a{^+h4(QRyI{<^o#ATr~pcG>jLRc&(P?Uu-0X%)Wn z?WF!8wRPShGd8JTf#p^ssDAC*Zt-KtcPmP8IoxZobtu#QEL>H^fQ}+7{Lo%BgubT1 z$4#(}BL6|?>3YF!lzP94x?uawUhuNmnEzDf)s*inHO~F!ANxjVN2BJeIW<|Avc|`k zoJtRh4YY(w_g`e(*S}f01`l8Q>6X z|4wbum_Xk^Qhen%W_e9}6GH%ZpP0Z_?y+8oQ9BobcWhAUR~Ibm2+LrJ1!~8%3=)wO zoOQR(=^4-Yi?0j7Y{LBmMnms()tsU3rmIIt6K*vhTNzvqqk;O9XBquYcXKEOZ$h zRi(M5O*L+)UNkar%8Ie@C#T|=?BEmV%j7HT^{x?lDhIj=5bZ67^s>+n z!-?0rQU@!QrqS5y=$f=u#vdtrbUqZO)8iX0ueL`(OEUPrmvZ; zSu4a)p>Bpco0)DQI#i%Wm#I1S_$cHa#lyF~p}e{G_x z%WkZ84xy(~FTLFPnYHMjzxSTmA;`y>`J}eOGYw$a9JRk$=-?JI)jv+1>0>^htI=Ud zbs}|uwcp$9P(jkoPU-rZVMKLW<&|6NSGEysjL`$c5tz|9>P_x*oy1Ysc!Hc|Q!Bce ziTAH6y_w%R#^+9R93D^~t8Tr@XSs4ula!EzZHLdy_VhRg}2h*bwb8A72kDc*srba5Y0t~p4vRq-Z=g~ z^)lLlyt8-UO!f5U<$R^!j3b{WpK14!1=G*T;83-(B0(JvRh}>V?j<%;OOqW7e}}ab zM7}kzHFWLwu|D$>NK97rjaZ%*ey7>qs0bvG?4_@vFjbJ)ut)qQ zVDgeDLQ&SZ-Ov4f2fXpOYbQzA?f9)x$&ZH_*E{co2|v)^%5iYx4Lq4}PxJFCD(Hfm zwCeIuwWI#0DnIXyjv~TkcE$L$33rB@s@1QF4L^AKyN52d@*Osp<9YUg0&t6lyhrA` z>^tdfKdYl+Gy0$9UARN^`EHQRM(3(l|07rEuMT?b^_`oDnjeM>*}ph(n%CSZepc&u z8fPnM@c0N5ZH&ui$p$An@p5ZO1G^wBgHwJ+-1j=uuZjmQ*vFFxS_3z)r*yhTcRJ+L zr+919y!)jVx}yC#%e5R4>W(2*s|p_)T;u888s0B(jgDWLnF zRw|*+A!%Mh!Q^#k$@?Lzsfc^IegX30eqnL&)RKQvw@_WLzp2lUO#TJGXi9*sySsCg z%gkgN@s{G2{!s3i-fsYo)kSrFj1NNSU_=4O{BV ziD*uO3ed6Jma8?E0ja5?C*`0X=6@;QKIlp5Vd+pR=#ebhh8$&Mt>lr@_A|{n?|S#E ze#ta60<*g;esj?PFMo6434S?ejK1|UEk{hh?F(7P|7ux{G|_J`t#Dx^v6-%ZHW%t| zm5TSal1uPvc>%xC>k0nT?N;-;|NaQx%q;1tBe2#a@rfoeTU2;1Jg=zXt3&=jRX0r% zB3U6!rixl&%=y}?kemc1Dy-`YoM;jqPAV)>JEzxh-Ksj3%Ky3{mi97nH*W*ha$6p@ zENy1I|0VROI4Hf|lg1{uQW*kHCru5xp{ zOVwHfVOdUD+*8#+16Uu~b`G*BHh>Mx_1z5bf14tdeGyFp&tbxqCs7Y>hT*zn4u1C0 zB9Z$_2G=tq@sq{-uBXD%i)y#I4b7?Y{stqQw#79K_RcEh3{>%zpQ zt2MO)?&U{q57wJ9ff_QGFc$>kl(=KR+g*VAf2sQ)pU?~Oo1D?mo*4+$ IH>08b4`|GD*#H0l diff --git a/out/fonts/fontawesome-webfont.woff2 b/out/fonts/fontawesome-webfont.woff2 index 7eb74fd127ee5eddf3b95fee6a20dc1684b0963b..4d13fc60404b91e398a37200c4a77b645cfd9586 100644 GIT binary patch literal 77160 zcmV(81_!itTT%&fM`8Do zgetlXfhX-f>pHa>CezJ5a+CKJB5E?t-D3Q@I zv;Az_{%F*wqQWVk+*x^)@=9sx>ldws&U_`?fwx|)6i0%hGq@6No|Wjj+Lhc2#LbXI zik@&>S#lthOy5xS4viawbfqcF5t#22r#4c;ULsQqOn&iMQrAORQWXh`G=YxhM*4YN zTfgWxZlU6?d>wP(yNq!jqfNVxB}>Ww7cSen4lE1$g!lMN&~*PN_7ITCO&u%|6=U~^ zD`NV@*N5j%{d4(V*d&F9*Lp4o^=-wV4E$&&XJX#);dbqZ^8pUYCyEa?qdKs=!}D|N zZKGn0G1#bWFe1l-8nC}AR*a~P9;0KUBrGsNR8Um3F%kp&^sGD!?K|!B(qItgwkPpO z4nOg8&Z#<)4^Bj%sQjrANfD$Zj098^i(7$$Vl;{o&HR7r?C&hE&b-&}y`y4mHj%mu zNlfW!ecOyC;56fuZ7e6t7R&P^z1O9)e^Pe=qGENxwk%7Q3&sYU;&zJz+X!u6Ex^F$ zTu6(Z`;JIR{;Knn>IcTcKbV%&ZSxB`P>8MADLLm#sD>oQy@;IWvGh3j=*Qa5&VIQ& z#BvplZofSw5gN50lul%1ZW|#duBPzgJG1nxIGMaB*-obI9wC1%7zRoi%C^%k;Mn?+ z?pUuq3@j1^4v?E3B49cgqW>EY2?-#3jqje^;JgycOCcwp0HG~LNR*rji6bO_n_6Fl zxt$OawF6EyR#iAg$gdotjwKXO)cf75+S~gE2n>cpa0mh<1W_5Hw7c36opP+~qRPFS z?z(HcYuX#9GugKj(K=EQB_0sAfiipahu*36k{xIzyD2!y5%vK1@c|DQ3Q0^$kT!Po zBklXM?*0ZWJJ6;!hoDZHGR|mrw+{{o{_lUy{_6}+Pm!l|BNl}Q;&@bv@2Wy(0-c_O zab6Z9oUWgiKYRW)Vv0%P;3X|rT9E6xVx&Q%6AWJDG0oX-H5vJ?>5A8;PEnm%C;H~y z%@URb{E<@x+!!CGA#@@j24G?{>Gvg*2lVeVHM;^7(Pnl#tDV)(Y|gCiIh;CbXJ$WV za+~#V|9GDufDe2U{2(L>iu$ z&FbBmZ9gV+TlVF2nNyNeYL2HloUh~eKdpS)>J9Pm#Xd(4%myqFVno%qUa9n|Ua803 z8#-)?GmgDZL7HHzH4B_FHnRat`EXP62|?edFIDRb!q%9yytA|?Ib5`-)rNGqg%GbH z-}d(Uw;KH$fouQgEh;fvK+gfZPMGsl{cktu>gD1?zL z`z7_05U{qkjReFC1qI#x+jpODe!iG=?eIufIBbyAS`i6yq~pK;J!P{R?B6jf<_85Y z$&N8sKi05v?h+0-IZ#Z-(g8koZ#f{v7%?Dp!%F^s91LTw|BvSLb7Oj@878i9HK*kSp)6{%ZXlv-PQ)RD zE`x4f_xM$H9{@mn{1`uWwLbR;xgELO9FcMuRbkvnQXmT&j}ZE~*Z9?u0F(1c4Md6G z%ZpLJy?$`%3V_^=J3F{;`T31Z7#Ad=bomK731~(`S)uLTR8OErP908ueHZaDB4D$q z{GZri&j-sW%|A#W5to*SAH-ai&E<86{%v3LDwPh%=3Mm7wrS#iOV1$&8oKgshx_jMlowl4ED4$f#L1!t6C1g9p~=ODPt z5-F*yQZ*RmNQ`~4r~k{Ouxs3@+Z>Q5N}1kIzW_;y+Y`2(U+=Sj1(9)2Vkg!}$DaT~ zSw&5w0~|KUc7%a7st`^}4doR9Pl!$j8b%9FcqlQFIssg|->XC5YmQ@}VmJj+^a&GW z;TT&?6ewkE94j()E$+}^)|h0Xjx{@?P9)U!BBDsDj}WU31 zAtcV{=d|bI-bs8=m>_-=CKKcXWW_GX0~^$^=>jcb2lM)283`*Z!V{7?x-M-}_~|s` zV|lNhxg(2J)xt(s?g(|g4crMAX)o}cuastffHd9kY=i3#SX1;l!-O06F-4v5y)!_N z{n~32h};!G7bhd5ytZSkz1eQ+sUW)X74K7DJFF%9?n#Q!!7ID?F7r$p*h2z%vFq+0 z9=`hOhOu`E+Rawmf`Ea#sNtl*!}&#cW`0Ouz3DI?ydh+i=s;0>PiQfT7Zu*A>rw!Z2oWMZdTlLANQLT4}czIhYZic*axDrD;QpTldic#?)QnYZQ#V&@GPdWKu$ce zkR96D(D?F+uOEL7E{&8{@#anN+7VOiE7M#=o-3l-Qlfm(Hnj`lCvjX<;N1eImGc}P zIfq1q23S0QB<*mCfZhipyXl3dlKdo_(zgrVEctLByL0)aRMXBH-Ttp)yZ_WqYe|tF zU*@4;)#eID=!hTcSCgMs|CA-!(RT=~eyOCyMAVSk!pq$%^Rswq@*cQ(TXI^ehX9#d zQzf)Vo7@<4U`9OSg`E*=es@n8G*SbT@I9!qVekl|qYka=BE@A6$s=C?(x-c+DlyNW} z6eaQe@Drh#XmE?Ex(!VKoZcdgD?X0w=CviN3tmmjikMECbJNHMagMY-l@hQIzV7AZ zriQRf5j1k=Eh_KlCFt5{BiAK6a8T){lxWsNJ@?M~+S(158s#PwDXC&%gvLuu_&~q; zp5%18A)_>(Gy@` zHu}fy7?5gdqUqRaZ9G+VYFVjT`f3hBTtJLx%QHo4W^k7Hn4dbj+U@EPSKG&~pSs!K zvyPmU&Tyr~vom3Dulo^!F^FVgi})a%1Gn9)rTvJRN`lw2KOkz(aW}5MO~dBSW@edL zwPwp4)N=wJup1;S7@U)OkZj2gQGo~o4#o=@iYEeNjFZoLvW2r$?(LKzQYnI52$jlzP&K3-Fs?@ z8TYz{a*Ip6o|)y)qHif|*~IjRGj3tOR55>Cr^87ZMJVZQz4x-c--DZz!bJ3J`mBFt zv$MzMB*TT@cUYc?%vG%XC_t5juJ=v#VIpp<4lLvW$%%|VH?JfU3&D=q@FkudiARUh(d2N+ zWLd~2X5t4S?fb`JHk6Khs0b;)4m))>Bf>MuG>~md#IxJ@3UBxJiBI@&t;m6*b~tLF z>Y4m_C`-#PTHIv21B#D$$;E^HZ8uiYUtFhV*G%O%3~-xR^LiE@?1e}-zAdW`mbEM> zF-u5dt!0p?EOIRw9HXESaG^}g@5b$*Gd<>1m;%N!sdSMt*}PbmYdWd4wf_iOfHlC+ za|MYGa1MylQ*%_SxCI*3>pCu7wYNkflt8fcEw)9s%#j8m5R?-^jqs5&y2-XJ@J1PZ zvCEQxGD63Ll8sRsnbjBI1u1mJ!>4@OBQ%73++6qLsDSXuV7F#t5G=NzBh&|HiRm#q z*)7%le!&>OD#^0421Im4)tJOE2i~}o^A-DsEaeX+t0KZ z{sQInfSneVRDtp{f^<>g*rTZi2sAuCI!Z9Zh$ZFSky>G5VCcOA>UPbn{DxunR4-Zq z0{Rr3Vcwm`(344N37c0jkQV&${exerkPtp8!}^!LNFtPq`QzzulIshDd^c?rMzvmA z&&_^jixC$vO7ZGm0Le*_7u+*exgqHorQCbdJY~!;JgCi-!q5HtGLD2^A9dP#_`PVfh~Qf+*{6POoKUi6l2P%*Hl&QKAyfLqkaIKd`D8JY1@={Zhq*1zZjQU5-VVG9EdQhh(N}S^W*!YLJe?QZ~`l?e_yw z5+Rt%0P61dAXbLEnF=K$2o+w?V3$raPx6eS5Bi3KtXuINb~@n7ggV*iUfP^;*T3fx zK(YWg|IErMMW^{br`nI~*hvLG+;Qa(JTE9Xz2mD|`K zWkMsBLSxbz*}wwmYD`=a5~IW|zFKINTi5zYJdLXS5AlQ;aj16QewJ%pn@7XW)l@{k zKU1m8+14)_#x2y>CEb#Vl-cMv42b@BrfGab7RyPY#BuR=W2k^v0h<(f44SbZ&kQd& z1c7+0f=Eva?9UId@{fgyyLhy>XLZ>Hs_gVQ>JLK39^$?US5+# zF8FwgP0>wLKjyriCrA1t{C?ppovgaV>1c~smv@h!4uR$(`2`$DeE7c~B> zpO)wsEU7ZQ#)-uJ6()96NKJ8Y@H7-Z0#aPGy|SvlSYbSo*fbFCmK;D$X{<=pL|?w> z37bU`XR6OqiFvV2n$yv2RQ}kYO5LsvtCo2WW6I7VnMg|XEFd+Y{o1b`B?Ku6B<2+= z&U7;n*3GsPjMqSY02HvKv_gCJS?}VwnX)lP$9Q?8>7cln_TCYaRXg*#;^hb%1uH+IT+qbi5QUIEkAPwUL- zZcK{joDF?6iF-BK80ny(qch>Bj2#sVh;E9olq4i9E2BhC2h@ZuNbOcWnAb?Aj+ol{ zPjg%dw*~)|Ezvu`S2h4n_?1nG-8izHMroCi)H}Y7r8gOC^D?nEB?8ux%nux4T`W2w zjmomxy+te?pWb^_g#G~wZee%3vH68gXQ75Jt@23+IdVE`poA6wl8hR#JV_HpwK4Eu zBw$Qpa>tT{f!Cet&Rr4Zc;X#7JyIEVCMr=i=zs(;dVe1C%lLUbh~NS0gJ4a3_SBi0 zWKV|KrDg~RR0H=-#?#LMUi65trDJ==U20Be7 z%Xwpj z8rGRuVi>6*eIn2 z4sdTqnx|BWhY_zMYaCA7zUpjza))jPvt-vupa&k7+<6n*ist$5`NN|BwO~KBX%LYryjwYCD`L@BOz&Y#&6yLk zrl09#3<5$~a4xgYhziDTTr}+GvxUZ_irgNJWb6?^#5mb!Oz(fO^4&7G%H z5^GS_GXIRAC_Q6#bn~Jjo?A1S$rmQJt!U~*P6dbvJ-70Rj*C#qoAg1nM--Cz!Y317 z=u#u7#!Wgd*X$9WGk^)j?$&fleixkNGkSM;Ai$K^JD4}R=>kur91A#{$yq51$wX5{ z_^yQCFMy;I)XX=RX%FBGjUjh=$~M62v?QPtjW|Ux>QrIgjQe~*2*&>nXZq^b5AiNL zZOI)6wC_3KIl*(?NODXbHzum22a=JFGaEv41mKQ*TW=5nCK7LT+EZuu)vXw=D|?|q zMZe$WYg*z7q#{n@ie%~;HG`r$nwUvewW8XJl|HLR?P9D;g~!gQW+^ITmZnEFJoC&$ zpqK!kl`d!W6#u8;k_s8NrGXb9K``UKExyy)qZX#Ac7FthR3Nwo1`lL3ODL!o z#aVG+vZ|XXb=~EAEWJ7~DkOX|><)vPi!TI8y2~t+U`4!!=-3qTcu*UzvmX| zU;vxoFY7w$fXLF*)+alS*@;#LhY>_6%d`y63v$W)kPx*5f^bYS(x#$=iQiEsSbWTj#TRZs?$7t8|iN~L%c(PyNt zN>cc8olk|i&vOa$9mc_tq1qTUO?Q~7+#U@N=prKaG!!!T;ppICO~e}UM7l3dA&J#? zf-}{*xAKAEE{qjsE0aKYPnTB6aq63DUe`n4s;NtDuJ@l2EaI^^NCY{ITBxi%Cb)05 zg&!!x67sqr4))=f2=^B;|&U9nAtxK%O?JrH(qLN-KLYGA2ys`5Pbca_F5=9yX0 zI@KWOZ;?E|06C&Ni~*hajz+-M`jaFaJ2KXs*J`w}5c=M_?075|63ZIOft^DH#ZttH zbQl)6uo5JL99BwZ9>Hda#W}|*0Iy-0IZ%nKCgAwd#WqiGzSaX5Y^gk*)brv38S)wL zWOF?u0W-yO7LT=1Ezn{_pw#>#jSuWwImbE(F^wt}}lf1z<$?f+@!t&&enhvFSp|oAa+s9!U zHXe30?GjS`pv=ByF^BCWSWJbRy2A=eiD6-y5fj~pEXMQfgpkY{A~P+|N8}+K%cVH8 zxAHg&eBe|%Q{GUMi~=9Hw)OFF98FTLS>9sw=B0b@E4xqqW!sxF_VU+f1*fUgb*|_4 zRz3PvJ}t!oYhpH4pAwRi(5Y}*;!VBKPpDx3vfLzB=tRMJ8;%jV@j>6aqg%i<1&#b+ zk^D-3Kdxp(KRuW4k%?rmuP94I&g0b4>O%zd6?@oyO6liO1^U`$YEO(w~dfSW-)I*JFbc95RKnhH_Ueo)^V z5O<-H?_2BbD+u?V6s?hlkNW{&D{7-4R^P`fkDgL0;{mp{b)#&5Aruay{_1@GD<`i@ zS^hSgHnz=Q2J4n}WYT?K1Ba~KTmN}=+nAMVj->#wyKf}M<5@kRd1_Le5osxl7MTWO zkkpGzVMHjsSp8MXcS#7V+PhkS79{jH0@}OoIU2e8CV!dMG+M*m)+daUL`I+W-4I(& zUB!OpWEez0R`B*0QI%Jr&CRlbeRfkm!A=eXZTHE;D+5#BaqzefNU;B5|N6>RA@|Ob zujYmt7m3)_czpI-ihZS1NN z{mBusZ?O_Oo54A_*Q29z84jB*6Wst#IvTqXn1FOd0WHRQYg4!CYPDfB?VoaEw10XJ zM*G{lAl|>>gn0kjc8K>kTL8Snq(eBCBR95iHQy_>TsDaOw3GMV`td+(amo3Y-6~SVgFExhSbYQt48O)0=vGOBz@93V1J{b z%hnjMkz5Lb^ba^Q<`P+L@G)XOzkbHOO0N0Xg0Ihy$^3ajb3G!GhUm=0X6-0?ONj*> z_f3DrB8?gdNMPm0cL=p(y+ve&>N;XLt~MwFIj|UsJns<6WB+W8-IyLPg}oO15Nn;A zXX*?`q_n+^0gs7HP%P#UtYbBYu|?p@^*>8)y$gH5q(rM|2sDE3?Nr_ z6;wk|U!eBTYxBbDj4oegyx`H4PD;~E0DDx)A+w4$lWIO__?$4^47wxdhTYj)uj=EM znyJ8s%uB-ov3ip%{vp~EGl-_rGMMKEfwnp}WIi3G1!!q)Mb=!*J@7~jy3`z6D|(ulUfoM`T~yvcgH%qlR3L>cQz}3KH_#K=7el_UiNveh$%U8? z_LGuK4xOlJQHD;H94v&y2_rh?&Qj5;yNIP~_>vbFIhO?$;xT|Nf?1iDP{&TfzW|C{ zCb@Y`IIq*W&G(5WFw0|-!FC7~@WzQ;j=+kc@=CQq%FR2Z@=-e+m0g92{YkVJKEF#;crZ%nQcFJ%ER9s%lZuHyt zzJCQXZKOUpq-8^{@!U>*5UtJX?PJ5B=GmY497K(+_9#(mFzjTf_-f`njzVGrbu~ zIo%B~2+9wdNd~?$Ckbz>{gcoZ5?p1VB{W_&eWQl99s=eyg47Eg{UFjXJqPm>4W7YD z$9-*oALJ8xuo5PzsHx8)k^U}Y)`AIEyYYQx=Stt&>pC^1 z<1Ipzi|(09mqxhhS;O1DqBDH|#e6Brh?)T?##hqzUdF1q6jPRD!uP? zbWjmu@AiW4LERk~L~lO?LlBOkXS8(lwDr(C^0>rF%Uwqug_tr@MLb@WZA&whtoIbB zE8!EYJKqhOTZ^g|%QMT``HvY}F|fSBy?KOoxP^}j7bAZUs@!njJZjWwL(^eq=6+n~ z8%LxAL!~qu?!w+=bz*cNLZC~R!u8OxQEj~wJTO)h@b)gBEo@zQDyI4YXo5}-(Ea; zYM(shM=smh)qbs|w%6;$>GU<*xxL%3UDH z0vH0D^OBr9a`sG=$rh?)7@YIo7tGXb<&x^?G`z4x$kihn?Wt54!tl=`j5ks~^J>k@Dr0)P<4=`SHK z9HqZCbCIW(RVN`J;D75Pe20ytLgS&Ts0!l`bX*&cR3jPU^U~6tO^zfhGHzeRUZ*DYv5=CgnUBb27sKfkX_*_QW8g{ZJrxy%`UQ0*MHZ%`jL5C?){`F! z&C1heYOrD0xYm%Mlg`aWz|)=J6XL61(PaYmoZu*Oee#}dZ#fyd`&CdjdPpQ^urvhm z*}68VQ1kadK;l>pC^5~>n9Trx;doyON_o9|l{4Dr69cU$EWU&B<4x-^ZkyN@g+6xh zPwMoB)w72E_{3`d-x8SCuyV~Y<7PBtbGlz8b|q|+<4fOKPHB=WR`~8S-zT@E#MIz^ z=alPCn@!+HKuGW89YXG6E7SeT?x%L$Rz`6^7@OU(bxT^EXsU2P?CnJ`_xORo0LS5ZqJMxCVbRWeo-#hK z{zFi%iIA{N#Sai5nrc7MZU}T|<(}BnT?3{T;ZumX`1pI_wN=xH1(7Hxv$bO9qbFvM z=4UX|gWc*FmBdU?L8VP}WEBU@DdV#;!@A>HA=Y*PjwWDlg|GfH5>Q(U8=Ya^l!UuA z`@jrShkPR|fU*HMN(H2f3L_iHxXfRx)nrwvq&6c~8APszz?(uMOM~~;e4-k-z`+?7 zfGGlRkkAmSbZh-=1DfW@EUpy$Y!T?8>kso)AM7dJxn-C&fjmLF2(TVpFr4e2U+g#7 z+4k*TetXy?4RKO}&ah^a69N0{Pzn%X8X;zvwD}fTRfDp#XjmKaqHNo}UcvD?D4zpu zpg)quKs{n;XPMnk&6ayDlWEX8k|(r56^l4OXTtD$NJe@v5fJxV4@4v5kU@+YF81KM zB`3Ckcdb1#4>KC1$+)+jS|{?MNO*>ms=Mx+CI?BKk~GjUN$;IXX{4>cn`P*Fl-e82 z)6I{U{cqygw40B6gQ97V*DIRULB6*KLPT`CR2Q|GilRB@t|Z3gvZLw#C-?I9 zy!hb|Fjj~seB&a|1(KNJ>wxs3916gZ*He~34@x1F)sNqi(l*9MHd0)QHWXaHyE(K7 z7cKZ-J*L4?vm!Z3S1w#G4ti~Cddo)5wN>F(8-aiB*r&s{6%BN!A zfXYqSk3jA<$0DOjjri6<$##L%7TK|6qVIW0hR0*(fg#o6fLB0H$oz`;1a}}DIS=m zbyp1H(H}*@XgRD90l;D@8c^gVE|w&ON1VYZKqwZG5%G1S)>4fd>}E_8%j0} z>CWmY4@fF`)8Fw6=$}2#(#%l{FRR_s*mX%Ry$HHIkK6B%!5A!-uyP}Uc?5jE0|so# zJYf39QTYezJ;eLe`Rl1hBpc|f(m|4R>6nc&+U%5MHUVSI^MY5$rR0aBG=BCa?{*tv z8T?`Y(3M|9)vn`N-fV}=sLpm8aiki6a}XqLIP~HXQxETrC1SUhA1v?k|2gmVR&_R2s(seFN2Y%r46JqWZi{zMzO@6d9I)pcW^+TATpWS22)!K7 z{@c%I{Tj3rhq(T^vsRbu&Ze%9K%2Jx;;cHVUtnV^eewPNOqD#*TeOfPRjbx2AAHc} zt-4#2+gs(Qnd`dLr*F8*$-Dx&zg#^>Qus?OAzM6)zDVOgj)gmgIpO%m1%Wz|)Je^w zE56KO{+Rh8zqjowkH|kGk|#&d2je}T?ZiXYJha&VyO4V8#=E9bh(Tco8rT zPe-~LXJF3m-dlc?;6F}7;88&8_{fAd=8#U#frP4_L49h#jzVGc!5lN~#ic3g6~oWV zv^sIRNviD2sp=g0o*CI#Z^KCv z#FxvQ-B_rBq7Gjt0mKsW!!`BC6$k3Nbv~=i32Sh;2_&#wx~G` z(eO_m^%*b>b$6$%N#e-yrUExgrg)Xbt1_?iT*?_%W<73Jkye1Kq|hQGIg_l`b~tzn z`?hTr4-{}gX!g?+=y~FiGlIKtQ3(zuiP@z5*mQMqJp{b_?lasFliFvhEL3A?EU$@}>?(xy?0}JwQH8W)@ zgM%@G>PXH-ueM<_`@adULW)`<8U01d5R+zQxRm%!F$xyv|chrOou44}{FQ zu6YqRf~q96u+ODLO0G^H%4Fs2B8k-be>oiK3g$C0AW6*^ms%)ZC=G0PHVrTJK#p08 zLXKYE*x7xsPgH(6W4>d;@{V2knw5LvDa+k`?zu!b?IaU>6Z`Pq6UTXDmMjv=q=0+& zbV0gTGkOq6NxG|T!|+7LG~A?B1pV4nGi0U@Nzx9T^F)#<4HAstN!zTAE&*ige(75b zE&EHBUNV4MV+@np3f(yUgLS?vS?RQ1T-jfytki+QU-&E97h_7L+8iXKTrxUZSLO`W zV$?#Q?RP!b+FLOvP6MA=R(dp(9y_!AD3@k>PN&3w;8lV1W+;Df)|ucTc-JF?m*BR~ zOsPF17R8HHWkv%j8E+8z^ns8d>p9D}&pP2~Dkoz~<@M#QkC?n$ z&e?ks$b<$?W~FX=nO!(W5x+0$ryG2dx-rUj?F|2CK-5Y)v02RT)wWJ`+B%|S>gH%j ztfKJtZwjIKzq@q2O_0W5goIMejlWX#_i4d8d`{b6P$HnB{fI(9u(`CzAZ=h_p7o2O zI!*lxi_iiR31c$L#i%^U6{h{zleCsq2#-&VQv#A)oq+%)VO&84x^U<84CMIggs<|k zy=BH+=Ey;ktf{G+F3hldr`GGNcZSEmemrDYNoc|SQck^RYZ`Xo=5O44Zl=_nqJ53m z?jA^dWvppdl~<{u*c`_{q0Ag3%_vJcw7Cau9bggfCgx23cwR=Xk^w6xrQHLW>mJ6~ zoLc6EiL#W%j~X5^KVItxMGgd}D4^Y)9{5DysmOKYi5BuUui;d}nD6_L6YasFOjC}# zHczo(ZSUG->j%o24td8i_|W>9e3D++Qxe`w@T9$cDvUBrFU6PyDH+cIXb67yo5J#3 zG40794Me%jg^c&;B&HbEF_T9x&XsSefG`7I4C>qZhx=cAaV){D41BBnVE){<2L>v7 z@O+e}#wYA`9CLORgK8)rap0>`tBHC{KGDrK|BkwuzlaI=96JbeGJ_Pwi(vS%g;$GU z{Zx5S_h+a9Wo0lHhxZH-?es7(>U}TAl)Q~QXj^ng`9!-l)?P)w#v|is_sESpWZ=t+AIf!#G5rs&Syz>JIdC**R%{28T7 z3V@q>j&C4r)}lPRp4ColvW%S&W~ir4e=5v=&{fKhhgb93U!Md&2bOjoJ19Yb8HK3L zy4q61UjHC7w>>t}Ha#-tZtH%1W3Rmx2ar!UlUNLfmEdH$tN}_H)_jlNOi-NOoqi9^ zg{k`SIGQU_MC|n7T(8vT(ya@_ty9AnT&F$vRoQmT4Nc^QnjT{!Vf(8~JI_I`92Py) zsKlD7l)2VxfdNW{PJnQm=uIU-Qee^9h&$N%C=>g=hc&|xSDL-sJ+%mnhFKt;XD#Gj z2zE4q&{%)2*@^mvO4vZ|*FE@S$1}z1{Oo{4vd%e)yV|NLF_6$95=Yw_z4vQ4lC3tBMDGfINUylPM{vLdC8$PvGww3M z#7!FCN}^#}-qt^>V~yZ$FrFzti)i5lP8Wc{b)L^3ngy~Q{tIn0A4raVvcVtQ$}w_8 z{3pGv*4Hunp5VvTf00XaophUX0ZP&+jLmekkfXZY#_;M=VNVsAyL*H&%BP~bR*Q}dWg0oT^8Hb z+8?1G&z0BSPn^-$hiXOPI+G&__cnoUIy{k1=Mc@&b;oJ3rj6kk$$N!*-WU(H*D=bT zr0V|Tqw7^x$?|Od3@g!L!cOqQSF7ZW$!NRFDNm;|d2K~(*`%*Q*3~y3q@}A_QE>1T z_6D(LLad5BIEtTzyE_8L9|e!)^p^N1XG>BwZkhJX2IjpB!BjvAu5P?4wikmTJr-d# ze~F%~qM?I`uv&gYSC`RHUPM?eSZ1ec==@HA#jy~*aWwx=5(dFZKo$AuQ_>Rp!25mj zSZFWpKHMx~mgDF1I61Y+^zJP>M|=fW1(A{|-QHr~ANxVa>i9KBlioZk*_GScI>eu& z1|bw(XKH?{PY2&7|BF?JPV1t%IM>@CuK1MYhZAS<3|$8;R~lD;C|B%GHu9HNvEw0;77(X?22w1IM z%aiOB(=+-KA2<0vs~0Nfhj)MhXFr;#l`0{U>G=9ec~qi63stjc&eM9u(Mj>TmCs)n zqy~jI(kAj;bc_&x@JKEnS@BxtC^T6o>twE#!UOw>4wdD*?dko{h9uAd6M2~^-V^XtQB8iDT>SuRV5`lF@KVqR6BpM!C7IOSK==Vpw&g(pxj3)fUkzqW=b~T@qFwtEZ zW+hV>@`(tZVIO~PD)HCr*ovK<9kXxHykgqU{en1fN;#jwg4p7qn!+cTEpyI5hH}vG z>x6~8sZ_AKr9oJMqy|Y0(OfufU3-I1W($>IBOJ=s6IioUUS_%(HTTpfCmY%9#O%-* z7Wh}nGS9alcExi=;#_~8?TAqrbG4o*nahwsLFg1}QWPF4TIl>4u;pQqh|II-98+uo z(Uzi8j9bgxoMgNzDV@owyPUubP~^g*#Jxy#7^83fyfvKkIEl$Fgu-3GXv3c-G_7y!TzN53|0z0QrgQ7caCIUODsHrJxMO^Wb*kGR?`kWpC;A=J&>1(h7!{7l6brcI(kLf%V{TT2<75-6 z8&zYT427ft`=>CKA>vVv&c z>9c-_$@t1_qhpRP6z0#+ww!e6an%ezStolEC*FwaLF8jo@%>hTO&IniscS@-4Xk^{ zrtKJ5&7a4q|Ll#BJS?d+UDhcz~oPM2|KSxUs4*+p8fP(ywu!Bkt8%c6sw78 zWyNMQf4$PiP-wJBw)J zFrI&zxy$w&L>{f?;zPdE1W50pp&X*=#w>q9Fo{|y964+OygHpN!b_)=H+o!D;6hCIj zaWcvUbE@H&Wtj%YJiK-AP$vs@i<*4hd0{uunqN#iOC>hj6>gO$NE&}#blRdD+`i|#RqLfDYEs|E;WZS(Jd4JuKXL$d|7$*@si*w5&^NgZ;jfd9P&&PAfyK0 z@-#u^rMW!<3dHgDRD+nfKzz(tB&HQ<8g4F2+(~@yQiKAa_dwrJf`{u|5QPP|UW&x-B%aYvU?T(iBW85A*9V0nld}B|2ByRyeWvN&^j9@JKZ@!Qbsb8_^ zONlcJ=M0REj)N6&mU~$eu?2^f;T}P5TkRP+t4-So4XIQpAtJu020vP`T?2z@1x3Vd zvJ1qX!amg}mWG+-dq>E0of@wos@EzJey05Ent8dE>tKl|t3mre*_a~%{M0D|w-9f} zC?w+bfEz#g9_ATATsZS!`bnjtFS^eH6s zdY{~Fa>v+oy@j+DD2O^9u(yLph#W_UVr5pQccN(|L%vTj^!N}UkkH#>=UUua>^w(f zJbJADK(RUlt4b}v)x_UlVCbm>IDnyO(zDGhZ+jkL3o0&`h0 z@{No_wWBu{*EDzEFzZK`(=~~~dX2&bK`()oMNe|h|4Dlo1x#xHR(r?t-E^1H#SqLUK8XTlHbx)yx-zJV%;W zKH0>$zqd^jvt0{Zv#3t^*dDNRu~*%VWSum|q z51|7P!|^AB8yP?XE}H1sStdAo3W_XgHx(MPwWI3&GkMs-JB@+sRef+T-$|bg0qg$@ zcvks%*4}As_(r{2#p-68|I7JkSlVNUnAGeZE@BMm>Ov~4d?vr*k9=pVw`DKNYshuG z{&rknNQbtbo??Qa3K@Uo4zmWL7IK@zzE~4tS9XEc*vZt)r;Y|JJv<;-Pq|0 z%OO{|+~4Q~2Y_nK%zLWsoY`7QB;R_zdr#gJaIYRa=XjEGnV2kj4}%4b7WKja_3cjMco6HoZV~yG2pj)qF`7L zVJc{QADVF*X?0cOT;3WMsv=DOy3n*h`BatGSlLolhrUJwXZBrl<;2|=MZwM#05d?$ zzq2)~RxsboSgg_(FUIe6>$S#fx_X73LiM~S2ib$bO1gL%8=}nT-y8|%NqY0{0f5ps z`ihbDjgrz?{)Wz#?J;z;zqWa=h_}v~Uwwh0e6)CN<68v4cmhg&di-qj$o@o|*H)MN zhH~@QV{>G4ak_TpTan|pCJ~N~V4rVQwtu+3Z0kPcpe!WQvt4J6;&li^~|lB(=48NU`r2 z$5ptqRbX95wQEDI>V|^m?Dw++2AZ+`PnhjdQ-wp7;&+p8j}{AOe&HW^M>tULnR|Ok zuD>oM_4^m!6*k2o77=|29Aq>saUVY9U>1M`Y;3hvO+r$Wxlm;ShBD?sjWJS$x#CFt zalGMd2ttrizow=n(pRG;iN|8%w`f9%viT0fnpPY@C_nri9kzc)_XwUrm{EN^M?~~8 z9KsqptPf>CkY>~*A_I*VIO4tc$c;w&m!_F!^Xs=YV7%&ksTIJ23`_L&b#~lbrq5XC zwJVsP@(gweY7>RvwgO%>J>JhSGf$I)DB$V(zS=M?Nr#PQOVRaGpb^N&Z?Kz!PpG`j zY2z{z2Er-Wh6fb0NAky>3RpbR633Wj$86{78f~M+Q_WnU=k|wC%-kU%`fqsdB*QBV z7l{ai1U_VJ?Zx0LjOU$ViklGOPDxDz7Q{@2g^ zTzoYk-lO!p*rq7Q`jeoGlGu3*@oJ@Ulo@R(vh4SO=F>b}N0A8?-ZIw*>G5P#o*45` zoR=`K^ynmrr?zg-4U}@Yt^%@cxh{CkoMm5 zoPXV&&8X3vA}~MBUNYsjSVrfKEPHdn=5k+U5I|P0`W2GF@sfF;XNZy%{u&bu&Q8i- z=V|l^j+gs)0&%@NSlY-OMMQ(3T%oOEF&Z96qmn4Lq!5jYQghe9lB!h2%iZ)m8(i9n zQU3Xn0y1<|34=SAp9^4;)!bVf2iYvJ>OpJ1qf4XeVnl2s<6=0?EM1vtT&$b1{(Ngg ziP`1QcuaAAau(eR)Xs)Je2aR_jJpp)irmA=VV~$?#P>g8-w^PChhYw9GrTaM=nm53 zC<$un+#*J`K`QNg-=oW9v|YuSD_BV8lzPB(|Jl~}3*`%1sRC2!;!GV6;0|>541kSrttz3llsEV32psoEb>y#`{&)#REmCm={YP3 zkS~Izr@rF*wXZJjgaYCHsz`u-g(1b@h09>l*8)ZPyAQk=cp3W?_!Lk1+m;~P8*K!4 z0ZFiI>Zi2PkyUz~diHB7y()Zd<(bL?Dhn<@{q^^L<@~-4$mL_}__@FWXmHolKV{8X zmtDCkNPNtjG0*go`N(BIsa87)*ry2&G7*|kQC5h&l5AHtZ5%aE5u`I4Cj;AF{i3TJ zcoP!fEU41C8?#|4RP34arDaw7u5&RktJ~QYgl2R(7ZZT|fW!VA{8YQHd(t7WicG+# z(LnD{Opce;bjQ6R$qxFtUgJz5bgkxTAoiq|Uby)>LlXGRQts9Xg1wpWOPu`;5H@|AnueaE;&Yr*p!z}53qVrc-7QXPLS&p48sckL6*~l23wsvl+#eZ@qD?{k}E!>@*~j(GCw3uZe+c6>cFUF(NmvF zC7+C~{t{)_o_?MERiAN})$tgb3cTL4+0ux5*#%N=;LyJ;H-rU?%dzP961Dfy#l=2g z7sV9@3e7L;bw(0rhldkSXDLwUl}hx5Tq#%^zXWR_Rz@Q6=mT7I_Se|Ta?%1L^4NDp zU9)or6R3XU9B02{=iu1H`}AmFc}s^F;7ukNi;7i&ih z)Bjxo@;ow7%fz+n`CL9A&@#?$i4;Th0(zq zq4@P%1npcbS*gTbO0&BD8R^ft-;ju`#KWw9ySA545D}A}9Ns}CKAj7;@tFi&)#MX0 zP?>BsaJb-4lf%)F2=;+n%78RaK%c^)5i9`50Me|Ahl4GHEE$u}8Xyn}nlhj}i8BndXM!{V9@ULn(5BO=r$<`sYbb4v3~;t~tLvr= za%ox-M$LVSxQl5z$uH~snh+g~V|q}Z#dTK2Q8`78(k3U&FYF74k#^;r@~!y%rO(}G_EA+zTka?F#8vv(l>5w`m)5p>zc?}JARmg2a;0vX@8X)$ zxrGwVeI2^a3I#e75dbX2(7D|AHX2wrq@S+utY)mi8fBX&1q}yIO&OsTGH`r?G}-iU zHU*Hj0#KEWC4DbARw|3e#iG>jy*FKP&EG4~32 zmoC^Zo2~LJm+tb7QgYY%8DF{mc~wIt63q`c`uX!V5sy>UWxeE81)SF@eNm%^c75VZ*KB>B;`2 z;ddS|3p!af%~7->3c!l$pDPw;A`&Gk9-}fE0qJzh^_pOfN2QS6w51KeW;$q2Gwc>K z#ui=$hJHLy5Ccv6zghsx1S)re`Nq%I(vb2=FrXH2AtGRbP*dgt3ry$(6*dbBHmpzF z)DwFHCb+zC5sVNNXL5^sPFcLNv>-LCj}*in zB%n`#2xa~aM{dQ&bC}^Iii}(a?`ivB<3!fj+0pGkwBNo3JMsYP=y%-A>orw^cxry` zw9KZ~+_i?Pr}WmHpFW3q)2ZL~;3*u^Zz*gl-tLh|@GTvdJNwA=0|P7Be32N^D_f*juK7AWtCz#4>hE>(_0DNNN*N>a1aA&IDhdw9bkWyB#<|~n11hB zccL`+tIBq9mMF%!i3+ z7PVFGOz=o-eeG5ewfKU|_u7UZRra6A9V$XI{cMyD z6jD%T>j}|h1Ft6zzWU8PYR1716h*Dx5hTjS2M1bZcwGy(MXMlwbkF7HBmQnTJ*tKi<85{MeCN8$Q(z-qr#~Oz!UG+tI~i0b9dl{Z0yvB||xj zSfxDrQSI$sY5BX_?~8CORUpWb6c-C0RKtn(ev$1}t}+)WCwF|-FPf`DGZX;A>ao}8 z=Sm1HyL1Zb9^CP)S7%I4B=R6z$X4V04t(CenRdWvFj$>f{tW5tn$OTY+iH$z=lPtr z8Hs8z(9U~uOipdHt>#->Odj?#Q?Vpj2!j##rSZy$6MhZfhoyg#kxQPix~=gT-67Rc zMJU*dnv;ve*-$zrf0y}tug1L7tTc1QlZk~_Ofx}@Hic3R5ovZU6*mP_5IUbsu`{i( zWd@q@?zuf)s*8!Q8KT9eG|RKUGzP*?L*MCAe%z3Zg-%N_D`O-kGnP%U{MPApJUXQ! z6v^u>OgO2=!ar*yf>Yt8mk!+9#p4YSJoDfdZ?`D-Lm?uLxs_J(rRaWjcjl(l~; zK?+iH{>VLBM7RoSIUI4S@8WhIf6qhQZf^tPol8<4GKO~FDaOszF=U)$eMFfuYdkqW zz+DbI#5nz-fBL#YQYm=$%cDC;(`mGQd(AgAp3TY^G|!J)7Q_n--a2QRRtGJ8K)4{? zp&DP;fJ#t$7p1e0`iG5`SUZ;~VMI#JKc$bHToof&lELh9>6+(v@NK@y&Hh32(2g=( zsSVvd5#}~IYKcssUrw z(x6waKfH!3`oiD<_5Zy0<6z!{&xf)jL%o2P%Lo|7Lh768S0_TN!+x`?g3bM7;bIK{ z6Vm?g+BJTCVDQyJ)=e?_>fj3~(wvuFsXmya5;| z*x|VcAa9N&-KDBKX7XU7%%a%*bg{X~pGvPJ-}~dLNFV;?TIB!)5=)iC)QW?#9M5Y5 zz$*|;0d4KA6yD$OQZgQ-<*qUGEUuZslsAo76}LL=}fX=+YRK2vu_!3iu+bq88_~6K6d23g`7+NXELRGw=j@D~xdDR;< zSpN0LOT*?Y4Kwiy?nVFt`{lej7~*hC>vfK=u+_JN3zv-9agadwoS08RcK&%sH1PV6 z%ii8DEN!`?BSa!z%+aHV0XS@=QCjt-G4=C;tI$J~uAk^!t2A#)+^CG`?VgGcm8PJD z9h3cJL^kJWTc*5x8kyHj(HvdXR``B_E{4}Sw&@Ox#uCibFnTHl7##W;6`Dv`*DQd~ zzt1>$l zy`tr!xYPUpkWSf{f5Sj7i_}-tF$F}i2YMV^5W%qGTd++fR^~PAav?M(Rhe?D4Rhk4 zHzj$00OwBGN+>_2Zdq-K9wJl|`a_LPZF2iA1n!vKw0mMxPE?E?>|H7uedv-Kc3`Tc znERrYG3s7Oo#pO}({__iZ|+swhCx#{SD8=QiDe60DB8|K5d-C-&7B^FbZ;?Y&#M($ zNP_3Qd(pu4q<+gzfPGdS%Zu5$0B^FA6+DYRBgg%sZ>sR_zEnm;BJUd|H}5m9tk*8} zC_fdxX19`qisj~A-_rG9A@!WVvHZZlyfGzJ@APp@I_R9IsL!~3k_7ueI4AQLE3Wlc zsJ2%gb=#nVoiKlk3(I{VD^xFu?on>(6QJU35bBa=XfzR!b_H+p_jZ;uafnByQ$ZFzeFCn{3?&FTXjn(nbO86K)<>eWp)YTN2fr4;#I; zuOdnA*$U}^3y!5y|wZ%gt2Spw?1r~Xs#>Bj<$lV% zOegfQxuQPduw&@N;gU{38I`@@s_{4=;TOt_ihJyWm3kCn_5?TuUw8;s;?(fd+}bD} zSR!4{l&r*?O*VJ_ETm@WXJ(YsE6toKRI1fV8&wE&J`FACU3z^38-{PADv@nR2gSA@ zmNAJ_%^i$9yRo{v+qLC~{I@2mg%vs%mzhz6dhtl@;cB|QY#OF&{<%y6?i>x+MlAdP z!SMKxVdz<^A}37CtcJ<7rLtm5aC`Q=mo}}{tLCH*Xp`pAT@$~J5N)ar{YBC}t_#wB zlImumyV?Xsb{vY|>W4+UU`1DHZWeWT;5Z>iR$1piKQ~KW_7y9eTQawn-6dbFZFl6l zbHiG->gi2dKiqcWY@V}|IitB|q=-+-49|NU`Le1kvnM&LFB^Ro01Z@q<;)xF%I7xO z-d5{+!?gc)RT8;d;?ZPO9xPvV>Q>6_qvS=+D?%1Jfq3HKVUJlZOf-#h-B8Oh@*)wf zp>D75YFjB-bJh_xG>!EE+aSp_bLCUYHr>IiqVf!TnJ5J;iECG?hY&ZGs*@ zMqi^@Gv{UkUbjpVm1gT^CmIz%)EFjBH@8MGdxDJTl@dp%im_D4Ld4O|(=V?dX1LXQ zabx&hE=(>-5wdPx9=)X5(pRBtl-4Ni5NH~T-D9L7$ejA?u6*K(CD=bDz|dU%gf`t3 zQO3ZuZYsH%Fu(%jvnLp<87GR3j?-7JXvC@GpFR5k?!}!!NfITQtWVex=oEq$Qbdv_)@$k~&IuRwktnFF{qbwn&9`6Nb>Uc41%a?M zgG${LZ>@pdbjP58^&MamShIiV3+(fVYy{dbgx)RP)TyehuE7}!6jVYZ%RegiAp?{fle zrZ~A&f3U?pW+7v@D4I(fNcW2BgHx@`=twsqOz=~`E=0rvH0O&X{@H$A%i7trVZ2A_ z0-AHLX$VU&kiqv@&@*~q_hy|-?`nyJ1?Y7xt?`{TNyhP**=B8&I%%g8dVJT|pQ!OT)J~x!odB)G@6&^!F&Xx#i;#~kuQXG?@y9`0` z8jmoU@C*%0W|Oo=J$eg_#%Ba)iUY57W}7z`OL!oVThJ2as~-$ZUM^d+rqr!I^IFjX zWBVC5Xt}pViP5L?6Ps)lU5J|-On4|x5|JRH{|v!INPmIG^6cHduk;ZDTpT-w*`2b=}lq&|5&VzP9gpLxa=Pdj-IB)8~jZ0xqAXJQ<(_Q1Ei` z&6%0u5p%gQxx6o&7S&E2IIwkfqP;HDzf-DTa)fHDUASDWrJ7-OUX|n{3@uxM!@ zW_&@H(PqGBU3px^=npz&)a3oneUBfD$JMVB=SHsCO|dRb7o{ys+C!t{MTlnUx~#vf zb?xF@Q79BkjoXBvQfjTMxl;QQ$B)tPFSYPn%>=h~4pdKK4y21jI}=0Lw_^g0MZ1>0 zMaEQ9al_sGXftG#+bw$q{AO5i7R1BwHm9v<4_%_U+g77UVKY3f)!YDfnbb-^Sf=9X zzUTJMO~iU+Qp!wX1*0>fkuR76^az-TxMX^$BA58{Kh%H&A7|P+L|>&H(ZW!uzBj$C z!e7~-%Tr?&eZCc;mcswvsPxK}{4kIt`JFHVrJ!^ByWpEmM2C~*PgS#&h!5i+1eBY&9lSe`3@5A=D2})4dQ=Lbi7ELpiQ@aGf`O>dG~-{rIee z9&s}0(W>Ca(zF2gRl|+DEbGjMZCmj6<=#PJ)7>Vh$6hE6ad&nj>*K!(9`EXsj{E;E(NN#n zqq}mP(>xZHN;%~eYdXK62QEvGuyRNb#S zGVo+VAqX@L`QWZD3X+OWkpnnSEM~p>rxKihGE`|+4RwpLb$8_IQ< zXVLJ&lFU1%8B25DCl6kvrxKufD}x$0RaH-&sQW^h_|UfME3G87B~QCKWo*@@Dv{b_ zK&puaMu`OVV>T3LX9e_4RexXEelcc*rgptnyEP4o5c4fo4V&CB9gi5nAQvfLMDcsQ z^VG9qF&i0{BT;b8BYvnDRc3XEhGa-0g&L$J zwlZr`49qW!tK8Hd13py~UzBx+xJKWsC_4{hGpMNf*5q8{KjbHZJNA z^jbTY%}}r_Ptz%g(^#edwhcZ=ca_8*&Y? zl{cCt)2II&xO<)-uML|M;dle8ZJ`~f2E8$F(2}$CX@l``6R_kU5=z#}+)tXXCsrYe znIg9musw++6$%Z}mo$XJ_)Al|E9#NL$|hRc+nIxrC#2?vrCE*+;Lu*%7Pkduz6Aoz z=6?VG_kH4)EQP{&Cn9sBZ{MzDvB&+fAEV#BeS0nl=WFQ5$W%&MJ7#9;mhXj**J`Ir zR+6|Jyh86Q(e`S^+yNbNO|Dl=uOgcpW%Vze*S5RgyIE$L{fzW@ccMx4@;YnlkxA?5 zaW003$Fc~VWK36SZSMTIvt1ql$(QxQ$NOCkX3yfdDS|@b>U(Um*1NaC9boQ^vC3-J zexu%o-s!J9#DP10tv9j7EqX!0@7UK^!6&TF4s>Fljo2K6S5MV0n9Cm|0Q3e&Q!rA= znpX9Z$)8+E81nn+%5I`6XaO5-DT|>j8V0%P3hEr&E5R&YWX(0Rh&Q}B338(XS`fzLR;O0^i zd>Hn<8c&)sFK*C4k~U4@vH;Ce=+&!2e5nwaToqMrp`;65!)&i}-NFU5JrG-atd}08 zK?AM@KeF)*dP-jqQZ@nvt^QL%gXO>D3BQc`kD#^uZ_*#iOk;S?;n2L=z$7UxKT4FBS~l*jqV5r3fL zc?yV&`?|@ewX^2-Wh-^gXstuOJjO5YEOQBWd8of5@oLxDN$2purs%J=pL_ArjuQT~ z`pGQWzw#ySrGw631ydqhJG9;XUw&X4AwKL~`rM8aD$d$;T{udabsN{W56yK?!3~Mk z4%MMZK8T74XzxsGaW`k;61Y+_7WOR4s*$=FT3yC`ppYc2Lt3S*wviCb!H35qsum>>o?g+x^38-2Cux#N_m_E3sN z0tqF7xNdRLU5MqF$v(gd`g-)XXqjy=ke8ct%L6}x@&+Ke05ej2PWVuP&-WV7*Xz-^YdpaeNVp4 zS347URKFp(y4dzcf?Euw`K@p14Q!Q&zAE|}u&1=ZO9lazgiD9wRd%-AyvB^#t4>)o zn zTIh5Ujl*cs#>u;pQp2VJM{vf&6*oV2Nj_6aiBDkj?Gq;%?$-RYrP1murR10)yKlB$jpRoq* zU7O+1_k{A7X`)3)%S6uynj4a-7SL)p zY{A_GL;yC~rxz{!hK~Zb)WIvKeOgsCpI)x#cu%$6yq%wB#r)V&9!U5b6c7uI!s=B! zB1wDqDUsYUg#?XSz_9olF7?xcD{h2wDDc&ny!|Y+GD2sBK(aaW{CO3T&3Tvuj8CNjN6N2 zc^<8pBeum+YM(Y_a(^QMr^u1Bg5DHL?aMT55*qSP76$I$#wd9XhZgTn_04@GZH^3E znglJ&eDjmkh${UN9h6h?id^^6oQ?kIhlxNE{|n1N3fR(~3Up*`2 zijvce&z>hx^xV344M)^U?$&HBi@N=CsB!yR$aWt@D4j$@85l>8CgVft*s;SQ5ux&v zuRW5-qk1%jf{J!1qa-^6yn6Hp>aAVR%!xZca8VP7<010#C z&pr(kf!0j6UhAS}@7lX}z714Y-k-Mr2U6J$%r9TLNgk@iro>GrLVqrvwAd_Anl0%1 zNXlv{{r)9TfBC(>^h9tn+sIz+UU!XPOV+D_OXveoVLr~j@2jP1&!}hW_$mEMQ~cA} zyb|tYM@Csk%p{W)s+AS^SYU_@HzktNfMc>tk=jufPq`bxkAWgW)u9_gl_#s{wq6h} z>tG`AhC9kff1(D{|A5GBWz>?bPhM<^gF2Z}8KFMxG&N-#7Wf)HTQ?+ny{83(w0{iY zX}{%0@LVcF^bQm!$DPJOmJ9`JZ{7m9kmpTCW4yrK5Wa+krveuUd*Pv0edJrHe_c_J+3K;Y0fGo2K7-^3KpC?_WFK2zB=YrOQX#|1ZRY}N$ zsjg3wbQaq1zOBrX2Esqh)oYCB=NAGx(#X}&Tlw5RR8wig^q~--1elwg97Q}g_Zmel z?@kHWkas)hZA1u-uXWbPdM8_271IRIjYHLUr-uPBp=?(Ras7yfm^#HYOSK& z`wvMb^~2LMmRw~tZiUa+5rruoQg&l_>o4?H(nG{Q-Ana{or#-gdml%+`dImrvbG{( z7p&tb<2KF1iyEl$<3+|T(cr$3H{GD2`gSx^hn7h3?N z-7f#2g>parXHTO6Xp+A#C2Zuc{Zdc36GglYx@H|9PCaBM{&in*V!%HPSi-P^+!JO5 zI@rugFRTlbeLpC5i#EQCqt8&7BKWgRe%EPME#GG`?dVxT9A|p(!G9fnHgQW#ss8N_Q1c&3xd57=V@14Ul( z;Oq|aNiyHKuw+(mm2ptbABVYXT46HV*GPgdjvGBFxMN#vS0!oI8@L~%w_{iUf@6pe z!J}wU#&NgP={AWH8DsoS@;|-{eIIF4Xopg5(CA$r`Op>xj-ym(=xp)QE=7Xv{$V{4qbf+kT65`SQT( z!ZyvE*xJEVow#eKj@8VD4<6E)84uEj`&>;30OfqZbRZDZHBUS=J|IdC=Y78387%)% z9dc1B&9C;GL0lCl^(lD;dekR|9TQ7r*scadjrLb$X}myZdUYo;Torx0UU9+a&q+K6 zK4o6kXer21DjvD?6l{8}e?ow4KMQBv`LY4j_lk?k1Ir+oK{PaH?B{SH*qzj};=~S$xWpk*YrTFKJ~fRkm`kA6J*@ z(N}Xe3Y2Hsg` zd_4%nK)XGK!B0X5uzJQ&ykzsh$u(ATY$O1^q0w5^ggB79gS0qa&ySdKa40%KHcB;6 zSuzO;!>CpsnY9ilN0f=q%y4Dq;hn8qwyJ1qlNKKx4x-X>n%%9B&MK?4XR z6VrUXNWt|*BRA29)zaX!+%fR}Xm1 zh)0bC`jGnm?+!;tk`SQRu6~VKx=N|OR5wj=Uc%_QBZ4r2r{vhfwQ+~O1RC?#%j#l_ zFq%tNZ*=in4T>4nmTeIZUgv8d7i+Y-Eo94Z+TEXj|F2#QO7z`i_A{c#-IYcf6OTsE zROZjR+n1d=Z%+j1JTn zd+6vm8?`#Qp7VM|4Fn(8W8II^OkLUcMnV0%8i zr-c?L`(fwaopm_}=js0UIS}xkC!hfcsZ1Uc`D4(y%EXaKXp!_}&7Sgy>)}~Pk7k*v z0R*+iSy#a$v~R zeX^24%(kxlnZBzNfrHfi>tqOoyp%v43|w(75S}?G)apg?N;OE`O0+b$p?Yc&Fa4;>M((f(+qN5a0fa6{?2lCvuLHUtJ~ zs?$>|(7(8KG&DIi>SSt=D-4F6OKZ8(PI2i%r5OSRluhu66AmjYKYItpG80XMn@&o9 zR`GQZ{5deuBqL;2oG;ZZDUr_&L2EFS#)4iOjE8~wMjVvio6QBl+}v)l0*m+ix|BR6 zq7j@*t-zf3jCOGVB%GV-9-qnRuVe{8>Sv@<-AIjL3V*mP=gMK7dWVl_LqBz>zeAM?E0)b*m z(-tW@b|C-yqZl(%hEkVNw2uUR%ev%$PwfoW32O$$RZzsii+!`7Q&yF){S3^1cz<&M zQOa^}ud$yq9;5$y=a4dqMi8Wo()uUXucO%AZcab&9@l#!UG*^*LMtD{)wQJ!^~{{|qje>0#VA_7t-GV0Vt=7IO_^w2S|1KGCn=&7 zIiMqlKFliD13Y7lJK7x7ntg0O;-~v1`zg0pU=VC&Sr_guH7d{#*$<^ee(Eg@iS`F% zHA>;eTJ<4O1GTx+rl($J0Z@RWFJ@}K3xQP1SdkK<1Xw00W+4cO!<}9e@|b5YYCH+E zFWSfJrGrx^O4gG#;Z|M={+0UQpTC}7#2Ib8d!Ua7GQO-kqNNQmX*UEU0pJe@7AE4U zwf@t!j*X40k61-dQ|KSSc*Zpj9>=l0*@|=`jumLC5r}r@uU|vj7K7zem7BeOK_t37 zhCmC^0leiNW{O-pQ_NwEDVnA>L($P+o!;NhiVSBkC^Ts;Yr+#e1qvfIbcC$AnegCRn?NkwemQ9q{hZ80)DRKKV55>n@+ zrF_6xec$!x3-5M?t7hpcw?AKqOMFRL_1?t$qmqSty(Mj6DiAf?M7yNXV2p=OfuA`f zBa>sjholVH6rcqddf`ip%Fh>sbg|fg9}8rHx@*{h-8b_G>|28~r~`VU8QhR8o~FUQ zVm$X6d{aD^e%QJ#Rz-f)Y+bL?@#<8df815HKiz1(<-p~CrfcD+F|np^Vcxs=+ty|2{Ww#AoH6&% zo#cyzwgikJ)APFGIg@CG*hvi-ht@)l>k0=EIZLZ=Unl@u0cII6x44LJA^Z!4lKC?+ z9iBtCzQH?K4wgx1B&ErK=cc(pgvCHGS8NR*-4R`eCMk0^@ZhL4ck!fIkTYX0{Nqgm zXA54u6v#2s$LYCGvvG4HO>^;rGg?keO=~o~A8voFukYHJ1yE)-pw)>!Y}+;oIY8agmiMNa9*?C0;5E;h zHZt=0bU-%>p5aW6&N2xd_SY96bo}-0C)BUNVo1v5@6@~jh<6gp=2vF&@wdr}H$BYT z{4PCWcnu{5WIqkMf5GmJVYAB1Ad)%YW&d!Hr;EKvkJ70OOUUK-T=0;^+mHL5gr0C3 zEfR5KgQKbmo0CAPN#e)o^I~h<*%Y~*smuj4Wl)?JMmXI8iCS${OeonAC~;6QHNP2d z87I7@!9)1R!d8j3ifO>Ls+-yplcA1kmC*3XzXVu6ap`AXI@6oLTU$`DRye7g8L|tZ zpEjfb+C53hi6{uQV+PGfmYNmYK&cfMz2Hn@A#As71>D9s->gk`+WGpOc2;8bao>Iw z+|m*+q}t6T$4O})h=stm(t^*S)}vJOojv*?LbHPePzF;5I;L%%b*y%a&;$ig1fR%r z&(EdrJEy-Frq5agd~+-oM}-f|I^f1|NcM`aXW8ji6?K547g`8XK4#|3K%L?MWfbCz zu0Te^JT~LavfwTq1(Ui=feqFWFM%nOSdLj|`ofd%rjvvjgu(Vy^JZUHZQ6_h6WNlg9F`pn0bGzs>?3HLw0ZOK&|M5DU zPKimPl{Zeo*d(cX7TUPF^a~>+90YH4G8YBWFps2b{&?jK$gEYWx3(D1 z!<21adU``7ytCf#r&HikiojIc~8C+D%CNYW3!UMh+0Xdsi zJa%p$1_QS`eLF%c*M|;d-cycTNT3ng2n@+=H5Bb2YKy3*W@TT9jMnMqPRxN}#5li# ze0*p1fWUan)K^A~Y4FG;5kt>L0VD19O>3u&F_-A{u@MHIcSe0TnJmI^0V)0=rO?PJ0vAVOUPhak5s4~M34*5kF z25O02RuL8fQ>{_BoGq=8f#?NIsMkGNodk7Ylh7DoD8 zzPfI@YFNx}*sLL!U@enFT-YvoYpfdnBm?&Bf@OHevw%+U zNRBWjHA7s0U^svMzgEe2yb+DSJl{eE#<^>v`hffK8eg-Ib!p$35ZH= z5}7G;Zk%*q^70w$Uk`XiORbbdlm;NByg~_?BxhNeLBCc$A7><$B}~vTOe5~&dmARs zotTzJbPr_fT)?GJloLIi(i>qk;>rz=9}hSpoIKo}ii>mnOkQ42-`w&=W1Po!xvcF- zEnhzAm-46a){EHM_yRk8D~DsL$RUfV1i!Yw-s%fDz8_C7(k|$ygu(YpZpJvgCa5gz z5rLK^>vQvTkX<$?3u_0KNH*~diAHfFDBFo!mU)+qkEVP3!7wP3Uf{|L*1y4G*7)n! zqpZcO4g-UdfaDhx0NmOOot^!(ktSw_&U!;}Nr}%A5Eb1#&YUEYt0*XFT+&5E=|j=< z9|0W|t=$~l^XX$>=y>)o!GlGDE;{5K{rqWO_{J-W&Yzw!e;C)M$@9{JN@+AeU~GqY z5Kiw*B<7HqHp9|Xm#W1QE}fP?(CUxm4>Si|42@W%F=%{!XE;1D$fP_A?m$ZdjhZhO z$MvEw3*)8HHSKT#$bZ+I%5UrFk#v%-aEB0KAZqEQbl_q|krJE>MX7oAwZ0-PRqgo|BCn>&`IF=Y?=7?)5<=Q#D7yDqGNhr5l|ces8J$>Q}~C`goaq;?B(t0HPdZ@otlM-AqfX#@VUglq#y zWsHU;X<;Tgvt)_3&m3ev^ZX7iX$`k*O%m?D+_2dep;STdlq9yCR!B#D=dR@7LJ z85N`5m3X>xbXYH-LD6v6GPDl}URyDKQhVzb^W8M3^|hoU-b4nq-D5+^lon2;PL zp(ocvSOQQmHb;Zou95p}Tj@NO8%~3BV^2n9QToa)l4ofo^B7W2=o7O2Zy7hzS9+Qa zUv#>;B0uVSJW_+F zhC<5xXSd1N+X}5uO%?u&Sz?xr+3NE3!%pTXIOg(K;@F{1e<)9X;eFV@x8p{La*u76dWsCAC0 z;3<~x07XE$zic`7(5?15A?1C^k-R-y@)9btnLDSgvH^s3d$6>z1M4mtq?T|Iz2YM3 zA?o4=EdIQF9Ci+?4{lBwn@bE6?KU%Y0AxOc_BM={1iR09FGv=mecTfslJU`zg93YT zOo1Jo@g$P+4GQO+;4Q?&^kJcoTaNzub94*cZc~hIGLFQb;6R~&lI|MOw~CDqzYY(N zjCe>+aKWO9$K$o$5FXMp@zCQ4CIsQ>3o`==r}2dIkaDmk(QT?&E&SMTv9|S&6XJknCMcy%W2@rdP%wEgdul!cz zeevkyGTT7sO3FwDl~dss9`+PIA%681n@s6mWE&6(nC5c8(lsyV9gs(PP7hc92rczs z1*EYX;^fJiOiBZui#@5-C{m?XGQ-G^>`gnqI*TpO>_G@HJQ>KO2~5KWF-$y0DAG#q zt@IR34uMfZFui753z0sPh|B0G^vM_P~}qobEq zrQ0l5Oo}5#*R0Y-wylJR92l8TH7-l~!I80%rumsuY;$h{jKzA1WRep%|$Mtgz z>Xr+=pZTauYs&7%qXV9JSn}5Q%GN$Inb@Zcg!Jn~;z5y>%z8 z^3vmGU7;TFwL<%I6im0bLCFC%Q-^5POQUw?oOW(4%3o!?IS^&_RtF+&ldlJfLJ~Uf zM+45QzIfJS^;%d8uD;1{8XM`_dH&`30P?~}5KCuNoE&~*P6xuc7wzHzhfi8dI^1I1 zK?i^(IYS9uox^YP70QEYqMHOIy;UmhPlW)g916w1eH_QvJjhlsxs zzRRIMb@u&1a;aLGnikCh(OuI)>sTNZU)6T+O%J?}F;*Owza|+_T<_`~#Wq-@lQQe; zoozSdrLkLV(vK&*9zm(eQ8rS$3sVd2QGM&{l&w>T>}7wI?C(l~^;=Qa)VPBkGn3IpP+HR#54sm{HY` z+mRkD9%1=qq|fB0SeqliDuv(YXIAV~ZgKgK%|}d^D44=pDbsI+P4mHNj^!aETG1E; z%18w+gU}@LiOGOh`t`J+uUxQjskjx;D#*6=jSCkq50sTIXTH*TAUTuoOfr{&8gQp5 z(IZ+dDQS+uxbwB$YU{MpYSgV6Js%ppFk+MQ@*7}oqcGrMU7Tw&lSwJMSnWmIIA)e^ zM6u4dyCpc1LsKr^Z`u`$#G4rQPG{dIe`MWotu39|N|QZdx{AG7JZ#+T$Dj;p*7UX{56pUxSdX5*+lmX{xiD172Y)8r^qOtsfs`JakDoOQx94|Zfum+8Ls zezZtV@&Kz_v2H}f%*thGFWQJGGO015Xk}l@lu>S0J&{A?_VALZ`AGj98-GQO?`Ion zey1g>LZ#y|HU7rnV|vAv3w8~GK4I%wfbk`UB}`S4+3I45lSh*7q z+hO`l8Q2kJcgc&M^(|;weL5bf!FXvPPq_skm5O+LD_)Dkv9d#P0VRZg1LnA0ds|x@ z9@udrnhD%^KuibLb#T>`9o55XyXu1r3*6Q%0o~}MTRq8ti@^1h*ru{v4Dn@&i)wLO z{w41mvtC!Fhm;x_C*nwI(|N*U>hvW_IEolaZFrT!HA2U&7A(LOnqvi2eC;=E(YKM^1`El#k zQ}QEbC`U9$-j_)}w5QbIh2(D4+Jr@t1`hn$ssHzl@?M0Sl7Qxy%a@DVJVYcuZt+M* zTgMhni6_ZJ)FzV0xF>J;a#d{z1%Moi#u59?PRq~TzJGU00Y8ZnP-B1t17 zR+L{Za&t*>4R9ORsqnewx*$Ff1j%AY>`r=>#l14Jah6z<{Y3dmuGV3S_LkZwNdFL4 zgH)oe?3}!rpC6S)$#jo=`r1deGnOa~Z%=e`N^B385_1APJ3fuNIMJ8rg!Roe5xQJDC_U?_s{tY_J-Nuwi)+f zWY`BH3AvFA+bwfZXCvY)F-@=*oP4jXFR69SX!cT+vC}QbE^8!5_)9F^g)w0jJz=Z- zj9E~}LB=d`lqDe%*8d7mP6ZWuc1||eUZutZKJf0wtU>8^+)9T=@YB7`DX_^3FP)i+ z-l}ZOlBq&7M@<==uP0j=kQyv*To%6Pj9eXS-qE8CZ7~IF59R2j!o&fVtm}T)n)zyOF+NOMiR^UwBUR5fNa=fSkCVa9152N(|@>YDi4> zO%JI&l0c6qkRajwR%$ zO>Wq5=AjE(0Ms-6Kt3n-O}y}A4gOiWEJ6fSvzK+T!b$J6YU+fqO93Djd_VvMQB)SN#!#r_D+d_kI&~iIvSZzS(4M_ivYX2bq40%5HH_M* z$^tksg4Srrsj8}+r(w65Ms@aBOk-Q2Zcf*zcyvzRM4MRH#VQd_I0ORy@W$NX!*e$t z0v3rCeE9YlhRre!e~<-Idp>cWJ{Hro9peUl!p4jv$vgDAsPKfCX;7=1yl zVD}F<8`K3jl<0sMOc_Wlt(rF{w;X`k) zw9awDr~6u`W$5Pfn!R+azh&bYS84v0w}D z2dB>*Lf_-4s)9MGaRN8iK=~Q5i-NDXC$tjK?G_&6p5gi(t6M!~9vq3pNGo2^m%7E? z>R~VSM}-qMjC$2P@HQ!V(6)!=L`dX!M$6Ch;}dq}`uZ|%M!hK|!({mL?*qB+E}bdi z2o%QKl~6Wb!?$t?jpGD+s%ZDfJc>-pKeI__E~mGcjsvS!7Y zusJ3)F4{W)=5srbLX5AK{q_nHnrrs;8QkXe^_70lKB#Ib&#-wSRLkR?ylTBoRU3f< z>157=O}yQ)t+ZSJghcUYG!J_kE8*RpAE}H2p%*%;JcBuLsRFkF{z1=w6aoc*p%r%r z2~2&v#X&v7qc#&8uiKzycKF>vbrF;+Rr+85ANEn+GiKgDpXB0|8&bDimk2NgQpNxn ze+{HkULf-<_n7Ne(RYR1SE3so6@q`V?lR(FK?xt_cBx0HJUI&wlgc!1SUaIVy9165W~)bEVdWK?t&E>anro9=REA^l2S{WD}o3I-yMc) zHONyJ~x~)-!6B6-+T3?r`y=Z8V zO!akq*TxVy`3(ue*5q20roz;H@kvO+I>w7{OMSbH3d~_IE!AtI^LSQqFvJ4Fa>~ws zOhb@g;DiViL=ZM;Cg{79Q>AfzaNnr%J(?J}els|}5TWs2c#c!wp<}+N)i_mc5wZ7W zemAhVwjT7ER#jTZI`nqNuM6Z`ZRtLRzY~Bz(+$xG;BXs#^j`+y`4DGI214ERq58vL z3MK1bq-Q<%Noag7-KE5Z^8Qv1UNPj8x-bbMdy|$ohJ$T}bI>`+59*tyv-HtI;PvcI zo|H+!6L5#jX?qG?N~|F25cWDvxT>YndE_OD#dU_~)dm2+`bXvj&Hq-`fuRDm3+B=R zYXWOLZz&qidpsRa@kdJ6rJ;C3PHHnP%c>iy@9_{QpEUqGU2?+IsT<#j` zWPWZHu#qxyaxzb1yEcMbmQ;b((h5=-535UK%USd1ii`NKG-F+nKC~31jRuTxdElq! zfocYDIvNB=U9Vcu=-9|45-b$pGVH3D>%Bu-UOz|o_*Q1(?DprNv9bjF7brsO;7Mik{3{fR zIjt7%It@V#4hzHeobL+%ymqLi)X+54QbM;#AlG{5(X)B%eE)bGzOJ0squW0&_+)V&)k&ZlVcwHls)yDF-7GhRwz{SlA71SeGBHRa#K0Baw`(tc>suBaw4;>+a^8 zyE`uH>D?LzyZSD4ir1++>Pr?$R3{gKHkcZf%5688(jxLY?;7mlzHc#ftUNg=wW9_cFMZljE zbDsz__PRp@cT8%1DH*Z(;yfsZo>_26cjDdiSBqYf{YXrVEem$b+i-;W#F0P&cizO% zpK!&@xt&$|OSqT7p*}I|w}A1)Ov}EhX5s`eaEZ{)j+Yxf)L-k2@t+|J2|508##_3& z!N#qw`E-OWV_Xf@2|(3x@m;c#;6p)5w6Ac@P+@O;9(k#3PTuN~dk;p2^C~m5M$q`n zcuap(cA~Vz<#{E6V7!wZG^fW|(pzO%7JafdOZ-X&%c+Es63hSqUL!oo zoyiE#N#9>D?yfR3EkLnsvow~=`(VoKP~trS=1V3$E-C5F)tp#%Osa^*X0dPC3!RHX zM_t~ojTX`?0`iOI*n&`bxX?+CZmCva=4&l}Q;fxA(Craq{Q}ryRkxQe+Goa>C*2@1 zPKy2YtuRm_^Z*E<&aZ-pNR{oVT}WoI5}prRv|7S=%N^py1zaw|Ad%pJy(^+zUlueI zVwk2+cCQ-$f{KzOyRP=Jh{bjxf^5tLEYx^B>>5N9cu7tIEk+Z9>}4!3iCk@h-qU2X zP+3&RXfPER%PaAAh7A(j2^#CyZFwKZ=7^+l2SZ#n&oRS1XbWI3xcA+g0SYCJwuqw z0lq`Ao}SV699L>VoU*kH+D~c2?VpULl4)!(2N*|mV?75{qY12aHJv=!gz<&?Cryez zBL$AD4emjwM2Hrm!{oMw5TYsQZG$4moADV~ArKBN>X*)(VZKrxm8ycdnP08+k$ovU z%{w*|#qZFcvM7#@Z#veL{Bc8G{rSh0?Wy~%+qLPfK|PLo`5I5}2V%+zg=B<&_{zoG z+xxbS*Y0R~mu@dgewfFq#iV*u=qyTtrb;6+#jV5h5NQkH|5|=uqI+Yzj2>NY2bN+| zI`nor>!afKKV?4&bXr~3xZl;F-)GgTO=}M778E9qdU~I6vmfOp!&O69Tv^`QyJd6r zwuU!pcB145xvW~3WbX(X6cL|PsTNk|tWnHEjvORy1jLMMz-bKKceKX81rj6k=C3;s z&G^iV$q6NS%SRurI6yTzd2uPUsH}YAjI2)G=RN(j#_Yx2Le_!BUR?gEQ~5Yu2LkK$ zs$H5td%U1>SNXN_(p!Hm?71sf4;Z9z*(qK!)%f52$1TXr8%s-|6fkEriA>VG?j}$9 zvQtpJWbNProyDFlZL$@B1;;-3xZU%Bhi>e68_H36S>?2j0Ak@B;)!{tLlRM%2%FBw z`auBC8Ivgpn2$os>qKBYV3LUJnZef>v$3-91?j*3H=fA{k-H^kBBfc07Lyf?`#!dk z+0dv*UEEZC>R@OSr8JmDa98lcwx9A-gh3Sj zPVeG{tq5mo-YMS6?BXV>ie#Ap47xQ7xHPSQA2fbzEiy~0qEPxGWkKaZ_zYE#=I?FR%$ z`X}qka2xh9=8he`O2Zg!>S6}k_RZB{TkkUOvE@H&OK|}lr?Mf8h(Ik~SvfcNDxH>Z zFz|tqX~j*_Y~(%l-@5#^wC$?DrIPl(DCsw6sl2~mtKY|&#{^g9*rTM=E-w3x3XBeL z&D$R6Yov?=pRNn;BM+?e`1rwNT?Rnl`2+5kl8tc#i*K597G11%OOC*4UDHDqD;=6k zHr5L*?Jp-&qRZ%eR;uAfBX9-Argcvy;pJx@^m>V@b@JeJlB#%ROq4E)sCM3S+)ZZh z(Vsvs(E-}a6UbJ? zi)t=*-PZ9{NTKsE!OCsNmDboQGZLu0htOgNbTfdX+Q}&4&m=}8vBXe=XnIucAv-Yc~5wEt#<(A_qRo#V9!r3PQ(T_+p zvDb$fg~Kxb)%*&vb!|;U&7}tCp>S;~S<9`fi_$p`0m5Iqo$}%pN)cPc^YgkcIkeX% z^WiLVfJnG$--9^Gg`n?Y!p+vm-x-%%zfK;QZnOS8jze;IOttTF`ARb4c4HV6{^UM* z%?bRR?$#0HN*;nEb>pN5w>oZFlNOzreHv`^dcxDLwCP@1JD#@Wv3j)Xvlr8etTDh~ zH+qA1FPfNN=bV$U$_{&w&l^1_REHp7O4+=1b4=r+>{F zJz}v137f{^?qY}leL_mwIf;h)#KP2$@ky@pJwsMfjkzVxOw~oop1wSB86Z#E4XT z@RsOP5gsq4QI%Q#rAz&e71cMl|C^R(y%bQy;I z=SraX>8v=nGuK(Qwce=wMqWCe%!=cD?vBcuIAC&p;8EwnXh!KY)$5|VY9g~bYoanc zYopFCEbk`%)_U7iNk+F+dH6k@OPRtu!fW|{B~$mW6rG`^P9mMg|(`OwEA(}UJ(8eEa{%8cMe z%`O7PK5(|??Uy0VT|B4)+wy5mxdFml#Mz~8&TD!I`8A0Vy9 z_LYqv+(tyYkaA?dME-0IVQF zq6on(SOc)SW|R7tuYcQIk^a?H%$GdpFj7aqHr3b^DfUK#a1 z1%xQI+DKBV)IxZTwM^89h-xhu@a^wm+Hf4=b(#WY-J3M zntBML_NYog>eV&+tKxaMLl*~)Q9x2sae`0zr?5OP9ponQ9Z5$f0xfVrUsEr;ZEmLZ zzu3Y9W2TT=H9Pe@c?1a<8hSkmdIs)AmE+0`hl$i@S+5i(+8GNE>~;xS&2k6 z&H+5_A3=)xrPCLtkWR;}m6~bAM3wdqP9%TAHz4izE`}h|E6c!V97&vKp~gD3BR}D| zq)>H7mlts>H9RPj8PD3TEl9gcM4ub4xZqVWCTHxs&b}jAxdIp?eZ+&1i3cr|bE6eJ zNt(*JjbP4uHo}2$*i)qYnsq_zoNa9ui${ZSJP_@f-1>9)PibQ?0?M|6b-x(+1)Y?f zW*)*dZzB(^lAMws+SM-aZ(W6Kt~@AzN$b^?E6^ZY6htkSvC|S{q45O2aUJTNyWuGr z%RE(3ad~f1UNkvN9Gem&2`a(A@g-jV=Jt;wRv&hR94als=IV3Vc`+hRq#?sJ#t86S zRV2}$%8OgA%)m{3f!~o&zJGE8J(=}OEs+NbiN829N#(8n-Yby^$|$iNS!8W!ucpP2 zh@1sXVW7MuRhd+mt_t>)L-!~K4+Os2<%%7S9VZ}2CqF1Ij&~sytX# zm#$Hiq{;({!UaqYDMn3;hhD2bhQhpsaK+vjh3_!~%tE-2YOpH34hR`f@__ApPq7XR z6fA=70*d{S?l8&Uu&>Iw0?@tlh%6j+?umfI=!E>h!V0uVbN&)Fz23yK*~(I-)#@mv zhx7G~E2PjyyG+L)KSpRHeo7bg^1U$+^^}&D0vrpJw4o4iDNiEJElS7|{c#Wtn*zy$ zH^+50mDecSgrdLqtL*>omLX6;f$9i88pDAxlnMZ(CKMSbj&n1u*@uQ$EbBR0gBN_i za~iADLC8Zzc5udg%(^8Mn6m^kxHlhvlwT@%L+j=^&k8)FB8(p!Cn86|wejcDAqU;U zqr?!T=T`OWv#H>7z$QF4L@jNekHMRviw=Qwu5_My=y5gvw<2x#jIX>(>)h;pU;HRu z4!v#dCsv@do11eI-U8dSM)y7v4}B_g)>g?C(}x2VBCw{Q%=c~lx3{eZ@BI9z)fV)r zId5^Oxu?3(`Fp{XZ>*3Z3_K2^e_eM6zd&IQ@FQW2#Ob+N*I9jO!J?GJd?V6w@6ufM z2J(rQNelv%U*DODS1a4gBJGim|J+X8o`Nu!e3$2^Ij1=2*1ZZY#d&6sq__z0ZtVVZ z%b@`1Vwk_qejRWsHAN!<@&$7W%XUuQIX=*1$>iv>QAgDw>wv?W#}9!x{`}C2k$JN= zCaTH|y)81ceo_0D%K(8}^kLz-mYD0%z9}`;ALHZM>0euyk$Uf6X&&!%s^#-yDBrCf z8c(E+J?KL(`pMv&4DAlE8BjDo3=cWxRLd*^?lAzOuhp#56oxs`%_8+?z2M1E?yRO= zQ@i!sAJm+GC?7C(H2ZVUN(XadwV7^Fw|nXA{04o^3?sonr2X>u?#Yj!@t+x(RoTJ& z6TPNhzMN7k7=bS~_a_Pxq?eExi;EG+OK7L}E$!b%_;Z0ZlUV+=-j-PWd00{RGlh;?}k=%CeTjT3gH8S}klO z-cE{TlvhYs2G32%Ul`E}R@0~Cc;<7H^_E#ihG;W_N+Zn02X1Gb;|^{|d`gISN$vPb6iA3F7=ul4nrMeB6Y z*XQm7VkWpe4VXpfU+eMFaM3VIbb24aSPZAFLbS5=tS(aa?fUf!E=9uP#EzhpbuBPY zQ$oYO7;OpS+ttUSoS^aIlk6G?U3Qcf-(;O&w|~pSomd(FQ2*eZ;`*Cg4Ht~+R_;U7 zG*1wbjFGjFzxOaEddCv@3C?)J?>!L=pYD~CkOjz=7SenIVc z)*kS@Lr_avssNX67ObD=zEWqrym-PZ&h#5;d>goL@yeXy@sc>Kw{M&maZ0mb1Dq7= z{6`er;eHH;iOH33AW#bDI1sRT4|Q>Z>!P*U!U)Xz*6@&^wfdQ-jg6m~)r>vHwx1K5 zRNTV1ZZdGK61l%&K^-sQMq3SCD{x-6wMMlUo5U!}^Zmj<$*ePHX94rG_1O*t>`^JS z0mH<^inR_zOl>sxm`6LmKR7YhThXi3RMB&PllwK#Z)ue{h&rb({Q!uxKDj+GFHFA&Z ze4l{Gq>7VX%s=>geYaciqQHSuR|i%1y&m=(u>|Z?eHwv{KTOxa_W2G~&0f2}jLm%* zObOC9Xt+4r4eny%jmM5f+OPs{yf1`J0nyn(g$@MlHp=4b`?ixdO=}c9>CAOGjc+w6 zKXIuEBgQZ>Id!8!F3N3K0v4%h$g1*YXU0)~8k4uWS8wtDXRScS>lk&cJHrXdZxaa*E0_iv+lS{OF)}dP)V5I@OJP>2nDX zo-+~l_juI0*DOc3Ae~K1WW1WNb{8dL?XhpZgMSCsd;;M7t=eohrFscoVM9kddRA<> z4j_DA^}`RQ{cYf{w?(O1QEZ&*yN*Z1H?2wk-`wgXYdgN!d(4dHe{W=Gps5=uM& zs6F0!cNRdrQoq~f{&Bh)TmuqoOE7yfbaw4920bEo4KRPiPTm)k1NFRe4X;G*ZrTQe zN?$c1TWqgUorX6^!WMtQ*YhxV8~87K$A$rMu#mwxJ~l?O zz78iaDhNkh@=@Di*Caawo@j|?6aYm+*ZilMLlU}{gtskV88Cs}0V(j0gL#x&Xv&e1 z_7lIvR_c`sNHU&qLy8%+cu}=b!lm%&IhqnaCVFS#fUS=zl`Ct>yo4vk6u-(>U!;CX z`L&M0P-kEF5JOLUV)5e6%$A9xs$tc)^R`aO$RP00^a`i@enBS=l`jHG+2!qwpKr36 z_39rYrwrQMtQsmXcLJxux%04r>yAqrqfbnDi~EUbF~ChKf6IV++?TO?nIM~O&1Fiu zAuLZP_NZDiPKs>~!Vd=GI;gac+@dN+$6(;}cwKYSwj*XlT$m930rI*Pqr^r@f}Kcr z^X**{tEvE!Nela;kw3UMBNfPkRf#U~HFq`1uFg_FH~ZEXkPoipFdUIOy)&u5ZW94; zCOIbOR&{W&9kirDMstu9n~WP(V>?NGyCGbU7_L=z!W*>ZeW-*1VuHU9nR+_S&CWS_ z9^4@yQrXnl*Ur9^?vvj9smcmYKq-kZ-jI@VOCAy`-Pzor;FIKC~AnIxkg#JEFRE_du zH#B0&q+aZPUhF6-dB+q%QNXQ_XSDMmyplN_Y;5q}yR-|V~XBWrhISFaFAU8k6$!ku*yc^EJSGK*T z=KmJrv-}|W)j{&|Q29k__J?rgrdiT*(u&d(@*R>&7U2?b7&pUyR-wDvz_&Qyw99Xw zKbNE0@4L&_{_7xztJ>$S{4*m;MhQDpY&H;4L4auz-G8eDr11qq-w*6&e^fA8@^>Br z!b$u0v@3qp9<*DRuxmmcu?6CjG|@3k`KVi=D)YuWFKW~JOaVbnFj(b%KK&4}xuml7 zF64CBx^)%E!*m~Njk3gPT8+5sHpJ|qDdP~aq;(PO9%T5M_-^B_`~<+cm8-v=e?OG8 z*~-cl?h1o^ZZvONyYo0m+b^TgXw@OB-2?`GgGoNA*A^e%{NH5$Z)T`L)kW06IxI=<98b%6lU} zd;iB+CHAF5u!l=cJK>D$!T?2$D0_BP5;hA=VVhZf#%kkFlZ?@=RQAxazhDq`AhEds zgq7{P%O6U_+S`NmGG>G^_TNOB>Eo_1pG_M4=u(X_vqNHs79c<)55!(1c}OC*V*}wO z8{dE%PE)z|3zSu&W$!s?u>Xg-9gr~?|U0uB@mjb^C5Ev3=!e?GFI*zjmb|Q4D zyu~u@3=`&LVB1jIu!OhXiT)16P)2N6vDfmM}z$}e0Zi01L{OR))P zfu4}63BO`^8d`|I>r7G-zM8sey-&v|J?^%A((R=D$5wrax+(Cr*S?+LTU!C?AKFm% zThH_E@opW=^W-w@Hdz;)ORAL#zf~Aa6PkSkl2;ipB!Ak2QaYfg45d#1{WD2wx+u<) zA5zwZN{xUE@R2E}ozxcj?YE|}u?71ENSjIfgV}DJQ@1F~XP8Usa0{iV?=qWQpO2;v zZ%*CsfgO2a=)0Qsufd);lqckn+HkfGu_YUS*8xkbMMbG+PZ-5pIx5W9xDWu(4{*Ae z;MPsxlNSsOfn>me1GePI-i?ZjASVHTm#mzJl7?24ui?0DtQoTo zs!1+h#mj{W!Mq+g-|#}8Zy>e5meHZgrj4= z8?!cubAI>-pzZ=nX>G6<7U{7Tqq%Fdj{ zJ6-jjMV`da96|v>(2xaDnTc#7lvUN*e}?e2EZ#%xDgF@TCuW;Nd)!MzhF#ilBPbjN zUh&S~9u>OfdG`);J-nG1Jyp5fYHt>9{t)nNR%I0Sb;+PHh2|qcnGMo#QJl8w2aXxPeRIhTR9(X3!3R|_iCoR%=rf{e*YNuQ9J2MWPNq6ar z4!pI1Hcme~o3T7?Cn}71MA!X4BthWHg7F$S4~b?XA~449yUJQg`8$lGAYb32RT5)I zYp5d03mRD>Vh_R)3Wq#$U)jJeROYo@y{cnAjje|rbW=m_5v zdRhre4peW9JI6TY%}C1-uZa$T%TOO)MRQaN5+_TXK*8h&?#~4G3<`vF_JKn4B}QuG zWJA+`gV)!p1{Mu(u^pqXhCoacn)1(OF^k+Q143^xvVp zbL#KqOr9Ywh(R))QuiPaAe%G_qZz4~f;t^%wO@@YTXY1Mi1bq`U5>vt73?g58&5gA zGXtii)TcZ5eX>j{;)dPC|}Y;umdv*NnW%@a{bJ%bE9HM1yc^v49`?q&f!})o1m8}dVgcOqEpVx4TXOF@ru2`4y|3%+mhgT=W*RK8 z6(O@ep%JM|2AZRqIayLNy6|@Ka`{9v@5Cqi3d8uB4@&O^R@KgztCSwA@*G zejM6|)v@YSADEAE&J1%pcDX={?om(r#j7lDc9prji1zFK94xnCq5@^uO7aSZC05 zUNoyxd;YU#6dH<5$q{+ee{cxV;hLJs1^_YMsC=+b2Myj7GTY!a-XaVP@^r~n;5w-WnAY*kzmT$khfH&2ouL;on2i6_id@}sdR_6ReKn5@%}+F;L77DhvpWU# zR~PA$Lq(#_o)&Wd<$LE~$tH=!EFUNI+jRfk>=llRTR6cNap8$|?)VBVD91|dUAvex z4XE1lnX>E3xizcj@L_rUw+d)z`dP94nYb?R{>wC-2Wlp;wi=T(-|~XCVfGxN_6vh? z%O@zB3xze{mlYEogz~r)a~g_R!$qCdnJxh~9m-+< zUmHO+y#4ztJ!HJx;|xB;xnC|B?y6|d&&cRFbVA{Cxacs%4@gSJABt?8;h}6>RY)}U zb}k9K%06AjC<<$gIWC|eRg^(GEI}<5tiQ&0=7o96u#nP;%kfs=YF1SYoL;_|fqk%i zcYjn!!PA&59|J*g$S^xB^IAkIuG}MgpS-PX%t$xj)nXn}Snn`HfyZRcbwbgi^)=FD zs6EYAuv}CSJnQ6K_r6wz`$U7Gvh4EHB^h>UCRfN0>oF8QmleUAP=ENiR0;ep?5Ol1bMx<)P ztE$4zlNy*+vINO|PA7Ftq~gOIq0xAyhbD?C3aK`Ca&m7+=AbkI7Y(t#-b~w4x4H>u zZj^{xVV|S9z?36&D-|;2K51ql2!9gKrM(;xDaXF~J}@LE+sg!Tq`(lp4;Ai?l>b_^H}p9?N?P7 zRV(TIQAf_v`BC%S#^2;KEadAi;3bMhZ=9n7j^D%HhYl3gyyy<+^p#}IH+p>p4I>>- zw{&}XL?ScctP8us^h=)3WUiI)AbUe~H~o+&(hV9zDQ<)?dmhg;tZSyNkSKf!btpCc zm31j1>wLBpRv`YAS8^1dobY9?6!C7|e{PfB>sVKWPadRukA#v!b(vRHhXx<1k}NVz zA&n@DOMSSa1CaEZr1Qc9y0`qCHF0z6pl^ZoF$ia4Lg4a`fI&`~0(aoLagn+LQRlq|N5^ zAo?@Ty_40YcT(~JErnoFdR*_*r;T>$0D)ulk34{L2mpz=&?+f^;>O=4ZRfvdPTZ#M zx~)lhvVJ4yn>s?eeeZjjL=Y<9{s&aT4?=5{ZP?qoUOTkK1S_$(jNz z*h0Td6Ql>gJg;ZuO-W6E2>{ur0Ok9R5*P^K&cZ-$X5avZT%h=U!L(!^9B-Jyhlz~s zj9V8rTdqPRthzZZx1Lg6)q<1a1_o5keeHD;K_r_i!DZ5-6g0+b0Q$R*b|>%Z>HMFT zUP}nh?9$2{7&Z-IJ2+%5cq_Hl;YtTzhIJKRG7Qe5N3Q_~%5no`Jsq7tz})-WD7O9m z1A&SYcZZZ4FE5lR#{yqqy*2uG&M%%XD>_(xw_5yI*1|4wb;yuWmVlRmS0?QP++|gB zKYxLG@PAH&(tK)a1R7t+O?NXfhvdf*9}gpO7D`)n|5rxvc=^t{UL!E`&pX(Tml8^17>keUn3>qx z_9L=9pXlpN>w0}2baie1xNG~4aEF#*Qx>e4uAb8tATslC7%o9xQ!$=jE_X*CVQ(cj zt}IhkSE-cMl?pfKZDh11MfN=`+faqx>Zx1Ou+!y=nyU5fY>MsY@k@|BGrB%#I&fMy zf7hQMyJvp?-Xrgd)H@t_M6Yz)-%q=y{(RZqbke$g)YT?gIsND76uQQ)aAI{;TV0Te z@t9P)qS(&4Bf{aTRn|ste}4HEdCt|Ps-evg+l9%YLdZI~68eRYJi;uE+=( zy^}oQq7v`}YQUPoHF>1bgKy<2UAm3$u`IoWwkzme$12f8jI200yT!cXn)Vf@plwr% z-BhJX%=S6ry14`6?As!${;kAcOG{^H#qcJ>TwY;4qze*QhNm77#{DRX9CcvsvmK>v zXHOd}i_?jQ0%(1K`;y*ys0JjN1KW}kq$CXAMaKJE)9GT8$L0*PTpikq$arjiTgC9c z0MXNIIk91iyVMQ8uU zLx2A$raTpYXSZbU+t<*ba!q?oSJJLW2WS#E{5i8%_eRN_EOSx@h0EWSdPq0Yde526 zMsj0FOZ@-%8sBdjQ?B9TMqw}+!xpW2vVoOo$3vn|?*Dyxxe6SAQ39 zr}o=50!rC%N7bOy()6@2%<7C^)zpoujsV|rSO3JAl$Z*CT{W0^43YrJ_Mn~?;Q2Aj zd3Dkz=BEy?I7rBkCljCkJEYP;yF5|ucJ(;9gp94ebyloA9_F{nrbSsP7Au+WbZ)t^ ze9qsp)l0SXl?>D$-RZT}Gb)M87O3hX+x)fy_TH-_BOCf2@VMIzlF*J$*=Zt8L!(BR zTETTx2nyZ7gQhq1?GWmDTs`;EhQ85}V+55CSXm@0=3d%KPU~pyaU2D~hiJ(>hp_C2 zqSERdTekq`t%i}cCBccsRay4VLGDNNIGk-8UXIXnAFZ-=7uLeIlanMi33PpWqwGzZGc^&=nRnea|NaiXT#nC$KguRg@; zFjIWnUqNM&XRbUl%s3GJK&>n3u{D$lGy7*ta5~oM@T^4#>P+7MLU#X4uda)UYWq6k zz3wU|dWDqT;HmmB;tp0I3qB5^%}2CY9sWZ~qv}cWPqOz#awYkt zVfMKTxtqb&36J<(y-k6*{Go|<^2nP?XLx;d4Oo1rBJAW;$YLuQ?P3oWpZMX9ftu~R*EY_5 z>qxKAn}=;AoSJlH)-f#}#G4B4{I$Hh2uEFMx!joWsF~ooB)hs%I&KH;M`>RX{u zppQp9s+yUpG8&cB;`Wa`y;aBL<&N%mu$7#ct}8v{IlaZZ5 z=Zq!ATK!0?TvF(_71yry!WnJoSz3fFUExbel3UtEw-Cd>$K)?;JKtu#>kZqP{YrS_#AOR!cJRfQ$C&JWVVDMyly zLYXAKMK@e#{8`quROGJhxW@|h21{q&-^sT-qBk4wAa}2+LTLUe`D=yE%`~!&m;dQp z^Rse1!g_VVt8}YVd}~=Kb&KS0C0xZ>O05*hZ^(wj(LXfpj?Ltv2gj zo8?Ha&UZ5`5o>v?l+mGht-Qj4$}B;K*S85};;G9chJ`QG=>2rtb9JnpBl?`eIEl08 z=F8#vJ7>(744v9t$Nn5!hks;X6vl6}u0eqaY>4|9XCt>DZ~Z{tULNz&c1aGSL$$ev z65-Dm;A_w05pn{E{A-9!a0?dI)PUjhOP!6*ZEg-q_%@``%^}1Idxd&YNmfpta)EM1 z&RUkbaOAbpSEY9-TX`D!9r>%W4Jryw`9t|r#SViZe<6Rv*rQ|A?vR9|{=&j7ajm`3 z9#wZr`#owb!W-}fozU3pz0hm`9__JPUUN*ob?Iu32|rp z;kgF3`_32QV@_zB`;`4u!hd$xDOa20WWvcA?On%R#~mt3*&W9n#uA)vzN8Pqkp@@8H+}ttZw5(A?hRnQ>%D5kf1xQip0-5#VERy0HuB#4XRgf zb-G*_%N++ublNIM#GVdz$~vmkTjRb=*K(NNEugEZdHhGvZ3=6HEjCLRzdeFE0oX)7 zxkqdEzTys>VMG}2Y&qaOYTX-Em=toaod7orjI7}FYP7j3?FLS4rMtiskCPWEIKdHW zkTR6eV&dsj%fKEjVTzk`^Y7?1WFRaVrU76Cf;a{N8y;#fUq(YJxDqy{6sL(Qzgr|< zTp)2LI~YSUY(&;c()klTBjOkFI^I@rEht}`=}2MBxg?|{J$Jt&7HtMYDna2fN{boQ zP`M?VbKqnur#jT(B?*1#y6e$2szFjX?!3eW28EfE_{ z5Z5feEJ4dm=;L*?TbY`i`5n))QA#!1CwiHc51K$u)Sb^-%!#K(M9x5?C{R{pY?G{9 zI8Ny%ES#_@NnN&NtLCIm^Zw7?Sr#}eyUL#GU%Li(pajnQ?EiJ*rHbr0*CYGnEAue| zWbHU}Hi41@^`6J98-3-YuMD5!(ezb$i}Ge;kinU_E6UXSAt{Z>rnBBLo3|CdTj#P) z>#+3d*L^d`u1QC%+jU)z+jxH7UWLk(m^2EVnVWHB>E@UNxLY1Rlq`Gft}!F=UNfri zNks3P>pkmn2PCm2@}SA3!t**oDuLcZX9^2a$-%@x43$EZhDiO6m_Xzq9#n4qn-$u3 zwrt|f%dPMg*kK41v0d)X^U18T!x8iYdNmW93$@Z1@d$f*-xkI3G13H5CV-D@o?KVa zpOpJ&g7BCCl0`|`k#s4C9-;_@IFM4PRB$Q-SxuYTi}&+2B-&RZr>_BEkOW6iu0HSQT6zh@E+HVE_|mVKdIxxk8`>1o!DGj-sSrnCDQ&I zXOi=DGG0uOBRfl;Fg`o7AH&WekdqSmQ&UOR$NU5#A+Oa3NQXY4Q`HpCe7r)w&$Y$1 z9#KxO2rMM47A#8d%Paw{pLz3Pjy^%6@B;TDR0rTw=z~q2&(;o0mcIVc?FS;mN$jhL zoGYn2JEhaS=%ril>EShyttwvSo-rYb-8%qn$t^8EcVb>;nW95!=uZ`UuXQ+NQ_LD#8ldFQlyV_ z8HXb>1RRuE-_{gBurj>nfll`}UR0XDDRo=S6+Sd5ZX@FnDtDj4vPxo}(%t{AB*>(d z)E=s3(*NbiN^unI%{*&L$8QE%m_qn0VNpTH{VTY6%{GUaZg zuKcylw5TpaOh234XZoLP(=yv!^^_y0E?1bU@>yW%9UfOlfx$jY+qzNL&<0zYOH9myL{1h`)?iN&`dd|p}^n! z7iWqFt?}fCgs5W3CA=oLvS`R4-gv;)OrWhPdkYsRW^eYJf9z13NEw#vp2vP{7nYM9 z@z^+`AT4w1v@^RXAqyE^1G zVw`VIzDvSXlD}vkciQLJQ687Z7k>%5uqox8f!!zyy=j=owihOFIgy-@n4H}nMx$i+ zNr1riQ}Ca9vDMU~rRM_Hb#a>)6=&YvwCPqv(OUE-VECHS0RM1( zorRg7`C$_of#;R$EI$ml@aH&?&=3{}=9!!PONO3bm9Moo%xB_11kiGu5mzo%(E(|W*UN~m%89UW)1r-Q6OpSdONsqpjp2Ot(n^TqzQUf6`KywCiL*z>t6&C{%i zl^o^l9z^GW2ADjOt;6+-B{T(sGCl4f9rw~S+mk;$^ z{DUY6{rJd1(1Yq-c<;e!@mgz;u;U~(pzH-z+=z%j16r!JPW}TrHQZXizX1Y6<^?BO z>fEHteIFEep{Lq@NJZn`0j*X}C-YA_sZz!L7^r+oC9Dz@*r6B#%+y0JUf{XM+K%O5 z%i3qnkSH@DwvS;Aj9W0tm<|xay8t7gsAFAfq1ziNn1Nst8}HI`b4nqlDr&X`5))(f z2xedul)Z1uE9MQZ@9iBK85=uoc&NO%c>jSQwHz`$bH)`l)%uP=gGf}ueTlDLjo?s$ z$T}5ud;K1)P$#w5?b-M*wYsf7Jq>*bN=t96o0S<2VG8A`>R3+Zx-H=ZzDv3TI}~_K zKtLVAwuzKs9gFZR1mcOv5vZ!nbzL3Lx~ZL2ELrwDN$p|S%de~@7J19UTnUIAz$3Xb zBA{fs!4ZjJMc%bOP?dhKKW@dKc3pQ`#P7^m*Q^50?~bvs@PM~rDTwCYGo3SZGSKnk z?+^E_RQ~`_rlfhpY%0L9PhA9Y0^}0ZSl-pTiU5kN?3J{ed?992iu_-l6d{b!&^W!t97dh zt7nGy_wxIp0OCNv9gF-c`XYb@lTt1dK~s=an=7sdI8z6JnXxl+3Q#O@-IZ2egk}Z0 z0NvAKnfBV9U1WS~unHP@bWsc3!=yc;6FTAu1aU(z(Z1hH`ZnY_K+X}&rnLV!+k=fM zuj4ibZPja!&x;?05_)@ycKx-r#X}Mc>+MGqt@D(qX?TwE6ZjpAfQr9ybd8y6PZFl%4DfeL*&Dg(7b!f@w@i zj2)gy4>kF`dEl4hKLCM*hk<;r)>UOKhti_VXkzQIEM2{_TZJ zSRGrEJGS)UgfvCVXd%c#L9NT*Y8S5)TFE?oI%csOp`rtcAC`KWJiqwjRGUIa5yKXTRWOv{SP zW~}#b%gqQ$4{p!(NZ1vb%^hjkaaCt$>W$?o(}$)MX&&`08eyybb!p7YG%R6zo*-_% zStPKyoB2rXYf2eo)Xqu>0XRU3bTL7ad5`M*r8uKfQO+qS=MBMea{fHE!s)9gRK)+3 zGEr4UzVlRwsD~847orT*s|ud!(keteAq12X;-#2i@|3Fuxm}VlUf-fCJ;$r{s!4na zUcM4f{b6{cyC;|9iA2y;QxZ}&f_wc(a05#XI2<80k7E^_AxkZi3@j^aVRxL^>^7Ob_S6Y5u&tBC9%x@o1b>UV_z88v6zBou;Epp^(tqoxe1)JWq zLX6^&05_3NIkO?P_-9EVGV6l`X-`5QxvUGiDtpMPA-yKLM%)l{sKHaApYP%5ZFJKr zR>ta)V`zM}lFFitCJ;qEqpd{*mMenOLQ0?}Q6evK!eo)(=gmy#4Aj$-=1%U@W5BBMycfgJo z<+z#TBC6zRsx;upeL|I~S2LO4tnTCPTW>U3X1UBFiyi*b(lapwM1ODEl)b=m!Cgax zs)TUQyg_+vu%c_pH&Y-?uFYz}stxr(**^XGbNVI!@#-+!DRmLGLAoH_IsJ$&UV9oN zc=#`&-lj}j7GUBqFRhj+iQGTJs9DV^hS-~73XFG2d*ZER&16FeF|U=j+1>c<+K}2u z@Qh@I5^9OOJeK2t@fz}^Qm^YU@G50lL$OYCNhp3UmL))Y2Dz9MFs%#?Dv?0Jg6 zV$n;z&Aa&yk);Mi$il9-nupzPd` zE|_1o6$aDR|F39^B74{v`DgM++YxH6-RBhHc@PHS!WFHDJ0Vz%JBr2|gZvgl3P`Au zDrfd`Es*{@GD$nKf$(JG`c#tFSn9+j5?tM87gVhG2bG)0no@J1-);F2$1UzJERG$^ z!aG&4y;ZW?-}$i+#C9!vg{PA}m2OW7If4M4@@s$}5mm11m5`mP?&6aY9t7@-65;LE02$&Il8gBz;kB!3emQ*ocX3=7?L3q^K^<&Wvva# zUN?1o&rq%0|9-~Q#t=VNTzFlgZ$^f1XC|I^HBYD3 zZ|f{GmD{RpOjP}!*2A^j8HP@71^HEAdZ%1e7tT#@_oYT_{jk zoYC=^^mrvQin?FQ<(`=5GG{>kMZlkz$!CV7NNT&wbm>j)`wods5$ZPfMozvB+hbn3 z$_4P*vb^oB@?(+J>#Tn*O5jA)U&jS5EAgRBQEY)vkpl?AWaR*0b(6cNAG|xM;nt>A z{bKECm@DWJeNT{G=H|2U?!oXA4%&&swIR$Ie`08u3B~;4AJYaBj>ma2FZLvTEi?nZ zt&lAOf%g)qqT3vOmf#tDkbYdp&o6E1+KA7wzyu&(gd{Qpp3RivH6z^TzQ9}$flyq6 zYgn_i4vfEaculM+#+4LLYzDw7UielyW-I#?baRbryb;>S%auyJsS~XD3||t4~R3@K@<}WEJcd zjW53+n)c0Z-w?3!@hQ;xFr@qIP$O6}Klwt(hO-f=DT_4=G?taDB ziL0FtwWGmVSeAtY#6csIUoe6elBkN7YK0{o7b8l^^Eh9nyqRV$=kLVG;VsUJUdArq z)+Y*#WOc#*?BavacnB;#a{um}vLlgYv6Hr?f$}OrTFuJcg~bzFQz~l=q4l-I?6iRN z=txez1Q%4YvL*RNorE2g7WsCJL4xMUV~SGWS(G+_;s9jp%)6^u+_C|s02>sC4g&o2 z%I|?6ij7Am2mcvk1Bg81^lzS*kS5}6^LKTOy+2GyT9mVtZk&y)O({e#^HrR2*0MXl z8}__A>JJ4CkL-_(?hL%f_GccAx3dwOxZNoM%F*4Ts-LBd|GBq$4tIQBeq`Tl1Fse) z$-Y42ook7pXevXu7dHH!|z2d*cX8Ip# z{kDk+QwQJGz|@gMRJxTHo|TnN72+7l0D(^>NgMu;YJ1l~a zd+L1`ge=mW+&!(obC2F`jEOzRx=%?v_9TC*?$U7b?ZPK%CTolz+&8Y-`n^Xk?)I?~ z=KYPj58d|7bo2leFzOp}1-0l6CmpT)Vq7_cs&apk+wKi)XKGK}+AVSn-2Rem@dINL z#q5j2H)&&SE7Ktrt3;Pw)%1zZVKF_?q&0DYi);pejt{L4Z139!)uW>&5tWg&8q$&d zYQzag_heKG!Vh)=FQfGN3H690_Uw-zsl86#zSUmA40w~A>_VB_ic2YEP&jVFGdTLc!J;94=7^~+UF+< zNCIV!sC4bz6>ob|mVG2|MHFKDu|Ju^*%g7ytnQ;hp$~Z#vu4}=nz2JK&Yzrn-PW^p zH+tlfj~$O1lh9a4wsxVi)&APsEmuCjxvgJ*nQPCZl*sXqh?JD>zp8fba>$!$f+iua zDk*`p2pw`s_3YAOK;`VJmL*L!(4BLWAx@jU>pj&oXv8I8fgM#d2C|Ni^?6o&433TD zaEK2G(`zg?uGZD9id`#v6ZZ7RMb4L8z!TJ7+0z8d)&qHN+mtRU9Z`CfO;5A))xZDg z5Jc}0?%gNsRF(fzT%s_TS5+r9`;@*qnIqw7&V@l0CCWuwx5}I~Vzttos}wd(F8f|_ z=hf}gw%S2n@nfyOw5crG$6I zp%;9$_}WhPcK~EzdnHly31gpm*wJT^{Zg}@pq#})IePD)ShWX2PM&-<`Pq@P5rmcNLB753es^X2f~1W|_^o1I&Auz<&NSHfmi1H{v*L*{8t1yQ(X;9&T25C| zsAdqu9a^S%sgey+x6K}}eIAnt%=gsI9;-#y+M;z{!1t|v+YOnluowS5*1R+1u|q-Z zY(re*qbEfU&Z#NaE{kF=E&9jzM?(Cx?wr_!^6p4Md|E|^d5p`g(|Peo=iEB~4ErRF zh7%`>ScUd>AIUQ&yLs~hR#8eXxw-$ENnYvG#oGz$Cp22`|5;lZeLnoelWrEDoY?Ec z(XHkg#iMrUtNv7PXIFaLyts14F>4KdP-E~eX8OgQ>Gl%) zOhDwfUV|;&&^PdKYJ_j8vAdjd&7|=9MB=uz3vh5tbn=1119BAlk5zrjBxh|(bdW(% zgS5kTt=-EE9B30N*|O!$n=SXX{aVm=CdFh(t7?2Sw@}6oIiU0VvEDyjU4ME7cN-Yn z?gAhY0DuS@cliIKOq<~k2bjRxdd(nuz=i1^xS-IfA=UUU1uG{kdYoc7`|b#Xrw=OM zt|W`z>W0p0&W0?4wKwWwL*|76731rYZ=NsO_g%q7tY|A9x)Qe|P)@2D$T|%l(#JfX zMB-BrUsE&?I}Xm)Oh+HAu9@BMv+P!1{UJxQsW_L2%A6&z_W~WQXK`JycUZaH!W$S8 zTzU&#h(ecFu=@;$&b!xo{p?gz`F5c6Y}3l{@X8Q{hE}*MBl?Qrp`5C-G8-wq!WLcaLM{2QQ?{dvP@$dI>&A3HC%GgKa ztTc_@6Pv%q*5q>Gt1sfz4Kot5m6GO^s4?rjQ(CK~6i zdwsMs1Mz*Gz4wgQ^`ae?U{VKF1Lt|CtO#jtqE;LlZe@7ico^8PsAKnrVR7J4wd7P6D5A~O2YX{c0+BVIFD-`b~(KTMT)m)-DY;4N7F!3bYEvH=O zw8lx8O++`GPZry{(&MdiRr(Cd6gpAbgPSotJJJa)tC;IL7~y*Bulimk@o|v6LcUr{ zicv)C=*D{m(wCNa$8TjNv?_26*A5mpe6=lfJYL;+*rU*5RQ~NMZVZ*>ea_pNZ_vui zp4TYz-2v~kvV*4t*Vd0agHj&rli=;pMSiD$>gx*yz$ZS@6+m89wm$!o-B&dWfWRd) zBUp(w^adi|w&%FD=xuj@46e86BP{5DEU`oNIO&#!omY;}Pd&uD;)WR9NcS5z>*GDn zw#CdEIxEo);gg;yPUWmT&BAUXT|3#V;Y11w3M+?AeFU{xVAkgs2kg)2)5z)!Pu0FclNz#B-?$EVx zRIcV37GXCe?rjqKeH@89VZ*=wZEG&XG}9j3=QpbHwgb3Jblr=TLi>CC5Z=!p^Pag{ zJ)@C-`z!cKp%?n5;pCV1cl7<~lW$I`F0YVM@gi%kPc>+=ycJ=&y+f5tkT4rhuZsO2 zP^%<_FS~nj%XM4964t<9X6s)fE|7QRc_i#ODI#xJh&waDG+HO*@{^)RCZ4SHZ`tfM z8=&%M$gBxl3p|iOUUic2NB0~0l+0H!Ij%(Fu`Z}fizb5rLM1#qf zAN<)s3GuptNw~=3G(7BVoI@h*V86&V=lrF?-ZvJ|iz@iPDW%5_Z0mX&NDg0$dQFsz0rFIT#po}Z_E^|Zy){2{g*c?4<954(@xJKZV&hT28|^%(^pbnZIM$^O~b&S73B9a06;F7-`6OMF4A)GeU>Yu5D5g*Vf-5?5YJ1dp zePd7h?(6*{Rv@AV`yI@sDV;hD&+cZRo~S6pz4B2W>hK^O^v8hSDyhm_!_~E)lC0r= z#4TWG_`oqKI=_g+1%}d@oEW#lZVx~$$j;q?+9y6^6DYEu@$b(*ET*ZkkyS8`E>WNE zuYc~_FN~yfRVub?qTZ2GF(xKEdz?Kyq#g-T0i_nTkYvM!QWY2_q?H||u~M%Iz@)v! z;-^MHA`*$t_7w<*Gp=CAKV9D zzVQDa3?B2({|te`TO+C0$IRgnyjljg?%FTFgb+DcO-7xl+lPA+;KAHC^8OwI$eEC_ zoZ6}6^v~iOw=0STXoj=H!~b(cW+5Rj*Tvd-#@P#d+_?16J@xKqFg%GB%&8}^@X zR`WtFMQJ$6w>hlP$ud00$Wwk!2}|3l#BkFmhr@!PhX;TvkrmdQ)^}r9M&I^hryi)D zOFzO|K}rzW#=50&H`KSh^I{;;X@~gs%S%ksU|q-SXUUFmBy1^%ar_IpqQSA!jaIQj zAErZ(Dr4_}{7bKCa(aIuku&JphqfHHvwSe)-$t{F4Pf*KTAM-ynNePz_IiCHA=Rl( zkFNM~A`8D;-WgJ|j2iEez)e5x$M6q^xF8d~A2*il3*iZeWK3inNGn*=>GxD{ox8U6 zmmfQwjNiLgwa?GnGmnOAK5F`>S6!f6_XPp^(SnyzRDSpeH#xOMojjXz1(lI$@uwi6p;$ww{h(GIasiWY zPNqh$6O~Kvd^tH$Q0JKT8e(BB{eB806#|h*7H(LOfIm86E^q;6E*~BO3n9X;L*ZtK z0EFL!S`Q@o-0y(;z84DW;nv-rT-b?fwzR8_a(2>Un=$(2z(zC+3ME1y5C|W+LJeyo zy>hZF9VDmpB<#ukT!}YJm8~`2bNBOZU&IW)(JS@!v7;4swY{exitI@gyIAUmMv+dfhbcfG*UTOs)P+I(p#t@!OC)kW`bXDpV+m32 zQe6$9zg=Zq6+<8pcMx9c%DT+}@R6RcS2o_NeM~}p`RLNInW(ciG4q{L3=Oo=aBe-4 zhYTGIVi1%aK0s>*v;G!Dwo=#E#*9J?z&vE@7DUWXOP%N5XL?HOGKFn#1;5>TO>PB6 z=Y2&>N5EH<oBbrabh`Y z3qxPPeo*Rf*7fjVt(nSzz%lTYK4RCYijmXYY1Vdz|C=^58FgO>oXI<8Y90f)FEJ;1 zuo*eGL^zva(I5q_x^62LE?U6y7-n(*xjw;K4$Q;zRFIk$&Y#Y#1od+^r|Rj;8V%R( zAMK!bqgD(btUxLF!RiQs_TYCHF{ly#yR%@@XzvLFrhHm=vXG0ahWAyo|7r8L4<2Ez ze|z{{=d%7Hs+SNo3y4_vAg@jLp+s0_Y{_c^VWW_Ex60Z2C$Kp-5+SFwF}5mTn4YdOpVi8d2WxACwK?(wTJ7cuFiuCig@(&A zgEey5VNpsJ3l760&i#KYjuu+MEUHha>Cb5GPYvig`Wn_)6$d?Fr%%7;Fo?knjuhXE z92|_iS3L4g9n3qx%6nV0z8;+X9Mfem#a_2Z=g7|8tiUaM3_89h9Nd=mR-qOdPaZvV zU54|#wa3x+G{%ohMtw0+tXBb0%6Z}wKu@K9YxnV{Tkk7@xnrLZ3`btN%croh%9}h$fRAg3r~5fEUv2F?ew`DbVpE%N4HtN`|X z@7sX+?i$ArIa94w60cVPfgw-I8luvbr0HO2z`8%1FPJ@_r1J_O@NdWYBKMgZ29G*8 zg7`r;0#-}LBc_p9t{=9DpovLw^l^_%g^umqc`VVmgF0SNL3I#*-`(pn%^z zi(q7tnQSt3*xDWcb`3V2HDc2J3z^5Qt+0Vh)Ax4k{O!>ek8cZzfQqim4V`ZjqnQdx z(U7G$5Q^v!FpB8NO^p2c?FoNVf63Sv5>6lX`~{ZOCQI)--3 zMF?UJO4^h4Fp!i>B9LI@M}JzM(bsOF*+^DaN~^NI7L!8ku06qi~X2%kd{V?eTHWTz%dFj>j}T?yx{aH-F$- z!1EKCceWN;HRa}>-su}K6gHFpzSEe^>d=ybAhaqe1GDJtfb)8{M;7W+JOM67IU?ua zLt)M#dW5c{id(*Z#ZW$)lHIgp1CiKTLjR9q%rtBs5W zfodp9m9*8I8?rixaawOBIU*p86`#rCgU{hKX~5E zfLHS{O)aaXH_{p(*qNT9?nrW0s4@z-krW+C>a^}W```%c;^ru~+~&Cz2JH`=4K;On zcWOd(h0Fit9Et`(k+84Uk8c+bhV@)!8#7tqj{3DsT<*%cYiuKP|8vmGf0Pc(ugn`1 zM-vX{V*f8|=Fr4KS}>OKauv=*xoCw%*cx#;;r>_a^PkdsvqK$>9XKFBtjQAq(?b{P z1vHU_w&I-e6^br5qrz32dtawq(GY--UwtDXe0r29F*3MMhmW1F1iG{Q~9EjEcD;1^ddH6j{7%L#klChR8DOCnXZb_w0aTTWQ>@HiwDn zXiP?u3auGPPhGwKgofVdqYaHs6`kSkBHP?m?b0!yP~g=H4_grO9=VMrfBomA;m43jr2Z+86zdY~WEfX1T?JdSS5b7@3(9@(KUv&Ewa!}^=C z@YNGDZC5VIdon8r*r%-S%XE?#V(@^K#Y&xm1eRmh3j`wSy~_nT3&qaEkycKV6N+Hs-MIds`6X-C(Is)myLbJty^QX0>P7dsg$8M5?956AuVueKNd@&q@_h!q62|?-?G{EKJ8TgR<=lmw&r=_zjry990o;ft^oeJW!XNQp~8D2yN6oL*2$1klFP$Ib8h(%=6y$c^E z9SBn+mem4qOQ6W_fJ7dc+W|!Uqze1UnhX5!>KaXmIYQROG)Lhc^JPHsW{!T|yE_A6 zez#XoYYNvxOabWejv!Qq=aqb*JC@yc=qcimvtdXUlD7<&z`5{xu03pdPWlw0Q(pS( z2H$u`hv}~{7^($k-^O?$Ww-;zxGtJGm8QVrTqp_$|0r&6L1|CjK($AN!?Ap4JMQH@8Aa9@G|DGS zJp4edx_k(Wm^5C1aS43oT;+fJhE^3H;_VxsF>s&{C0oWLQ`GO^BkV@$i~8dC&)6ff zs4b>Lq)GAG% zCM>7Si{DTetjkQUS>fL#IPk!rKK9ZN(LMOWTgTRS+&l&<2}2lu&Ljd{n5CXs$yqo5 zn^z=R;gf%{tX`0uapFcLMTOSc*Fn=1R}->PsT4QLd)4sht&fTkWD3zq%%hh)4} zR8UUkko^dEVzQ6B)SQD|9+UZIf7 zZ%2H-o#7)_Duaqe{pm=d2+@aDcwKEI@7mRmkxNQV&kr<4EvuIpZ&B+*8=b1Q+A`6{ z?Xw2DGjT72RG(eFDe)Z^JT@+BcyGTid_zHArdwk|>N2V0d_f7hdvAZxF|CzLd+`P` zK^0(6t?>*SMmW2|JEzqrAij$^5(E;)fIwnW!(Hx_qsq6@aV%EaZx^3DD)5r}_-wrq zUXg+bjRt zs}9U9vKC{UYi=(3%kOp>mLxwqi|>i1f$!Xx-^IZGV#j;m6U||I1Henb!|L9nWSK{6 zc~;i8yupR1TKTWdr8>9FCt8jbb7z|_0=ofETo*4Z-)Z|UgrzlV%04Kejtf14|32~v z%XS_L+w^xmH(Y}>z8~4(--vnf`hF?c$#EG@O928G0&}Tze)2hgJfheOYYm*>w|is( zhNj=vZ~4QXJD;`3TIh|0umt8o#8Qbgr*?9~txe5=meI2L63T#{my0IyUp}>PJYifW z5ZzK1^IvhFzs+wAKv*JBT~t-xFnPb|zIGYlcC-t3*6RJGbjn@jRn?ak?P=c&hddQS z)8g@Iu6R9TF?KgOiYR9J3hYhlYxCNKI+G{bstUVF>WU1N2KQimdCmwqMD4t$@imfe zj__3uI=VwEFFrX{$3`e4Wl5BLl}jPI+TqZWlWZ`kq%$_L*>1;7N0((PHcn*?FUyP? z?bMFf#j0v*)tcjX`n0X{W%b23a(vN(kl=)r_nW*Tlp6uNXgF)(=TFq0c zLvjk%ltSZ4o3d_nhuYSDwJpsfTH{u`f4kbqcKX&G8%(mSLIE3c`KKZ|#g{dn*uy#C z9)LJj2EOXJc&rC#>R)7D%Q};Mcx_h!D4(}}tKSX!P3n1pE2SwT5+%xlwV5Av{i=nX zf_~nwz83q3(TR&HxAdg9#Y+>Tlvs{~ukSqg&(UYA`!@i5U=V=K+SYm!u*OI*l^nFs zX=_=SJu=4@7UbdY`{iy8U;Ec}|5(5NM^{$TxsHyrfmvNIOFT;MRAg=zow&GJv+d^f zN=-IE;OBDPjhq|vPWxhNzVFjS9XPdoAkD%jgERm(*b+=Y{vkc#Nu?AQb$@#5Z4R2s zkY2spNmV+O5P<2JWdDuB-HZ}p4nJWsXaX;gu*7NZdBr=}*KP(;x{3JbZy?z3kdr8j z{(-f3BUf<-_~!{pVJD6ygusKR@**+z#_9 zUupR8uaaG&#iBsBkip|rei7U`8GFp^9aXe&t^7^>*;pOdkf8-?`ozgo>6@unIy&#s zKvoo!R@uIQMiy^b`(7xJK9Pg5Ifgw}#EUkT$JQsde_T;h7pswSZdX`o zBSt(hd087`3w@5%ml>7RcLn^BBO^zV(9mOrW?HmyHMOy3adL2Lc{&>mzfYG}-gIUR zvQ(uPmV|mCv`7+D_a;#4$`4*Z79Nbok%`0Y9Sy^dOFK>k@$5R(jS-`_ET71?$G^1j z#hG8oLeZ3y!I zIr!2KKxMG`e%y50jm)j5zrxdGk|6RbETSD?hO(x>^k(_Cb8uRYT*DnIqva{A%}LW! z%?zE2exenF<@3*R@AmFSnk+t(IaEI3HZ91nt3`wm?IQ@KIu4F2GPNIFgW1w-^5Tjr zzliSakOP*e2+4~lXJqpP?xT`+QJ^t(OKNuLq7nQ`U_{~f^uX0Vf+JtzdIy!v3*TE2yxCq+3 zmx2?LZ@vO7E!oLXgADFuhj0Py?`ao@9K$>RJRZX#?8>k$SNF?|r3xP5aU*ScE6enB zWo2B_tEVq_xcR+Q;G}N9c<1B3U&`F5BT65Q(LlpRp!gFOz}T3DZOMUSZxE8V`)k*N z1pVct^9@hQl-|Lh@LZ@r5e~>B@eQk=Zv)hL&FJlozmJ^-vaz?bkE?{3W4|B?9Wl#rhXOZA@F^c##c(~_f3A^44sA8$3F=Yvq)2`RJ&I76~~@H!P<-0mJstYKMk^W z-sKgB0TZBoVR*UQdEOeOoXp@X?j7Q1#^VJ=N6~R*JeikR;1#*8w0Kj3_tfuvYGkcg zlALYL&ie#>9tu!z{eYXNOosb&YI;j2*As}Sbr*4<{#7@5yMvCd+RmfXXPZ>?LQ~cW z43IOF(h6MlNq0h_;<>zwepxd2Xo4-M9|&lgk_ExSSZyl2d&6@uXGa3mru04xOC7_2 zeTxNLP5zdtLmE+qnSt>7%*McATI{_ggapmw$ba4 z)47KnvtHpDgRN8Gd6DmD&VU@!V-#;qkolx`T~Nfvh6ST*^iw;4i!0=K2GrR(yB425 zx1z7lCDO16g5L&2!UyWzO^JT`w>I_7nVv$&xDn16db~&w(;2%dxz5GWS!@?W+l%RL z3d>o2*5&Tx_q9OdM5w!~h?hpmOUgYmi z>Vw5{pBc#t(lo#3iIUn=PL(2~eA%106>GSzBJ4=nWSQ33(9U#p+#cGAG;K6Cc${!w zp!zL!oX6YK? zPhI&O*L7gLVKK|yzjQ0m;&LnK;Ar(MF>(?R5;318I+O4Ld6FyC$%e^z+pvXz{l~9jfQxHf$)q$Ogb2+$5*WC2&13Btc zb|lHGdOF1yW+UPX`?*(dB8OU(XM|dJ_Tb4nu{2yl-EaSin=LoZjtvhQzi(aj{?xA2 z*VWyZZK&l1(=@1>ty>FcK=r+|ygG0RWE?!6kGnY(sWxIc3{F3!r2vugB~K?sq}csb z*>s$l@E7}ykdc*@i7ikw)1dHV851~GR7?paz>g7f2uen=i2HLeyl+Me;22Ebi^j89XnvHWgModvFZwFxteCyK_{Pfc`AnRn$l{Z&4W~^yrjq~P04i4Zpid?a^vu2|4`97BKQtU=SAMAT@hYg!+U8x>1a5l(k z(q}(LUBdg{{}lW_cLmPA9Z(({PJO5ffHP+-XyQbV#q3g zT;LT1k;*N|TQC}{og&qHOz}EtP5mBAdbb~5M<8m&Gg_RNN?QpvQB7oRPq!G@8=J>B z8VMwEe~f5`3lqY{!Q7CL**EZwt*40;t%UYAGeSk~8_lQ|*+?I{(Im zM6Iwe%GQCFR)G>y@jLRz)B3 zs#dSsj8h|R7nSjZdgw`zOOz|qmmt4pks!F_i1;7XUbJ0Cz(oD zbOuVKkK|Bnk6Kha)c7r81k~>!B zER=eoTxlpY+10w!Bfp91QnDKHMfQA@lk!iHeX7{aKbI{xi%wg_XiI~7R5UWI*rr`y z^!fLsU!velyQi>BR}f)mg6~7VNUHx5Cl^>S*vrI`Z<0SPWEZ9&R|YV50^yR%glz0C zj^_?F*>#p(F`47~xliY!W(4pzl_dS-b`I^$h8ZYJC?-nae8$odxYcTT=i}WQ7mjw# zgHPv--!4z-8`0NNptNVs+m^UC1z+DSj!*7;(4E`?{$HGn|LQS+j9Ru$Q0Mt>bebJj zeHFCu_jeXCcIaMY8*LR0P}}X-l=Xj{ULfjIKh&6cNM6Gwm|=tRs{v=kVXMiX@6%dx zLr+l#>wYSMIwgGbo6<<=B7&|ga_(B{^Vooo`bkYEnk}vvDj;g377=`jAcR>i8tPZAUT~)gNk>lRbaFvK3 zWD?)4LaDVe;q?lv3x8skl7JoX=$CQQ5$dnY{d+OuLt=6)#YesFT(Z!;@3W#F*j9AdR6S@TTvC6kCu--xuKO z%(~|<I@d0!?Ze^g<`QT~8HQx3YR;=bu2MQm^$aQ*E}bi|yq7K?87K)e zIOR1`-F(r=sugj$^Ap%yeFiYZEoM{$$&hb1?k`=>>__`<5w)(jrLeMxqql7GaA1fgXZW_ zjvEU2!V#?mf)!f|A`)i0DSej9*3%r)yLVD@COY^44&(BZIhx9)@DVSl!MaX4p8KKq z`fH{%V$bXHe%>x*f>;tBe-NyB%F~m+M<(j^NpfhL1uyMtySiU9cTqyg`L1$AnkFsq z6g_0PLKn?PReWp!6$rgew@b@KNcI;?fa7)yDh+sN-vlFNb@|nwtz2Jv3>5G&e8d+0 zMCAq-v8Y+|q9y(P|LB1B`C^m}GWACf5Ja1!6V(gpsp~!%B}ww!q3$(WywZyIjim!W z92<}wiR&_v5hXwOdws{{;_Mwm=RE(ty!y3{ zO7313dtvL9vSs+|`jZOodR1h8n+I1VWOEFnPHv&PBLo z|3{e!zMSRyk!UU&*;xx-4>t=TA8X}|NUNAA>}1A@a7(gcyTggq!|Xi6)&Ako=o5S2 zUXOQo-+_dk%60*Z#ar~Lti@-T#T;J`U16m?8+_%l+iLiq_V+N3ZgWJrYDjU*$!)(2 z<)_E6eG}h?MP0}LQpqIG<`=jx|K^w2m{etqeH&7+1yp3E+52@f>Ge&c|1`!taDLo< z?Ry`q?!;wX3uJcBLmiO8CU-{@6GP)Jkq67jz-m(rI6PuXlqD)Mo#Yn{ChH^3JoTrG zN{>9^GkZ2n9r(P zVNJskC(vRmgm0vq83Mq~zJPen*TUaG+-9HenJyK%_2mtJdY=h$hfPnamJ?W$iA~csmYBI6DmDi%%vn=XSWpGJ$OI5;gcSJwdPv?1Bd?m)mrlW zJ$qNanNc{sn=d;)ub>`RBE8-p5O^f22~?p-NblrO5jkR>OJA>yzx33)aJQXOhx}y% zAT(BNCoiCnwv#i}>79@jCv4(F$c?~cRDW&gndWeF8Ks&EB9o7GLV`kfQjS*W)b-~v zA{NyEK`xZS&V+yB)1>beuI_yWiYqJKXzKy?}t9UZbjUEgSe|1tF`&$~7NYRvxz?25tbyRbAe27dHI>nK= zhFZv@J7UY@v$A8IIK8!;uFzE#&-hkIK)?Oi_omncEP)ih?^`@WT&zmKMw?T?<#o4U z0E8)}taVbxW+J)BL2Gbl_xbFzAvr)iZ3VB&Fx9X_9~Bil+GY$LJS= zu(5Qq>zQjyj)t^d=5&>>cV)U2e>0aOktkZ67U0 zzaM+qMdXXE-m{SRi^~!+B(O4a@kAOIV1Yw%G8S3NUieQ{ z@`=%UqY^ok@;kyO+gKB^0@B;C*l44)wZBY-*1Qa;46fTrGvSyB$(NFN(RSU!j=aC& zs@kBXkRq>@lPtu5@(S57qR9%?Y;QP_pGFKTOPJJ*b$G#`g0o5Lpng(K7L6wc3jJYE zWA0}1YjK`yIlTiswHaa`F{!pLv7c&OHR$c#KB35I#*r8{HOF<>-pm@HUn(9)gb)Xs z#151Dy*9Tqou2zX*1y)bliHDNv75X?7#8Q}CX<=cF^MlxPJYRL z-p&K{r<)xG@b8_zZd9^98(9sDS-EqmV61Mjgy?!Lw?{N4=>gDN{UaJDAK70tZ2{p5 zlnkJmk6~^j0Q_QM{ws;j60EQ7!~I=!pN;eDmxlL9lSupqM)~O5%<^qqBZ}TU5>iqk z^EYF-dmkjr4syM-(x8IJ>>X(~z%px4wL7VW#aO*`n;mmvcfSd%z?`X+%B-wS231>v z(KrLy%EF1C)|2f*5E z35$#~9)VjnVylbnQv7s3OXUi`B}S%VL!(I9^)G_4>bz0 z;Zt4&XL26;b3-Cs&%rH#+VWH+|IFIZt6OJVs}Xt1WQ|SF3I)v=1O12#J3fXC^gMC0 zmpv6?TBJm5Yhi(*-f+Zo2%wfnq>>3@0h^QXZa=F2ow?#!WWk+S@+?L|NjKAE8<$^| zLkfCH^7vpF7x&a36OtmKKNt5TLcQHU-^bSKx7K|$sy1u`od2T$QkJv0L!HFkrb>?h=_O48fmctYHQl!rtQL>13-$W5(BbyiJ}MoRrs*1IF91XV7YsfBa{aVl2s zx57pJzH2CNk3p4**K0Gw{VaQP^R_d?eA^{SWqYY-VH)tjNX6$lns%fag+BmciwTD; z{eVqUm4Mgr3)34~grHgkOhHM1NIlmK)DJ;NPEBY=^bL5fof%EdN2GAc*tSba|5 zd%Da_mCezJ-OR#}B5eCDOYKr|h*?#syewp!p-?V6K2h15S)NpCOho4^p0%JDK5iEh zx5E`Egfd;y$Z2-YWKQw6dL`Uh+8l`BJ0L5q7U=v+RZic}Zm1hu}UNe`mO z=LptzGSdq5EKUf?`+YG^;{mRZ>MEv&WAW2kl}mE-NCVt17>JK7Wgxm{we_u2<8t}k zhE3`2yO=e>c54;}iy6mEDa~O){1F{NO2EspIQ_)1BZPC>#dQK?im_j?!XC+>TvujUx`O zrP>n6kf(ZfC;SY5DVK1NYw{0LRH(j&?q7GP^!vy~O?pd-yJBaRdj5PM2kMk9%57Lq z8{48QQJxx3-?aAE)fi{#%_G-5f|VtP;dT|evh}ysUl}sn2)6>_4#d`5)A05UZPLX1 z02wc&ab>YE*| z00wzTjq#4xcwee33dNraE!<1rf#}rrLC>Ne*Hz+OPOl;ShcE&{W3yKE(nV^p6KB=` zRMYM@Oo1fB_Fum@?w?s^yJuO8^%W-k>^AFHd7i`>XSn}I49ca z=gHReK08-Pi5@6RFtZAuUM|6SAmr9D@_T~cKyi9ccIdqOV(_+7_q`0!Q~}bIJ)p&& zW{@X%7USX^sK)VIDH$%xZw&JAFK)XGZ*H5^hV7)=SIL`3%j>^td5j9#)xL!K>sfi& z?cYH2ZOjQlvHR&piRSs_6lh@}Fy1D3bWyLXRg>DSOkm@f2&XQ#-T~XVg*Xa+Hzzm> z(gA&X*`GJTi-N~5ukS-Mho#wx7!m1QlKQ3LjFDcuw^Q0VZ0*zsb4BrpU(-i{iRjxZ z4wO`zbg%Kr_q%?k8tX1bhjnJ%E;{f`!2~Od6BuwtlWYrt-E_9gK&;Y|FbP3`P{}?M z?*aFreO^3N5_5SLsoPEJFHiDa>%XbLV$8Z*TJ?HoymC7LVZcg7WTsE-x}QtvjkteE z)emmI$xS`a4?+LBe*!!~@gDlt&DDD1dMDe?TRB)09>_d7wn* z>B%%mKS|5ch9vpQtJwXuLJjOM2Z}vQpox06_V}qN{w1Hf;cu>$RMe=8G?PF*FVnZ< zlGv3(nC%)xH(B;wJMqlj{ebX1v|JYhFlX+7n zbOM7NWBYsG`uS@hqD#v^z^BId-Y#pPr(%W@#^g(|t?qMl-|B&F%?8!`c&j(aaz0d{ zGRmQ$2!<3KgmgVe;%z+tR>_L5{q2jsae_f=KcLhRe{PNxD2qyj1QLQAg#pu3`yOas zD@2DAgAQrzZLUC)(Avl_%KNLYno*aAk#w*|2=AMjyPsokxx--ms^V$9V1_pjI3=1Y z#8SZ|$E_JsT`3M5xPrvD%0an8oi56j=9s90h3n8&sNajoTxSRe2822S-r=;hF%2DM ze8e+Kre}(!T_RZ$(U4rL|I%ZzEV~EFNNeM@N8t6~7*%c>!R!d8lVXBl zVJWn=l4EWf;4AzSakR{LSO?S*SHc4=Xh6ACdK~c8lySDg_f`pkFa*>HU#k^?Mk*9{ za)hMXOej0CYjHfP@rr~g=bzpZWd>K)z(RWS24$;J{WoGXRRr;k!7#8hjdn`O-U8}5 zo6@7Qu$vlPAwxkd&&~X!a5-rWMK9dA?DB9=jmEx5D3{D5oiT{fXLI@`D=Ux#grhuG zD^+!nEA~NcC)v7i@}e#|#_(t9O%4YG-k=tCW>)%JiM~ScnO!i>TNad-?#I#}>v((J!f2=gHwtwVc_EHLQC){JFeq7&ps>W$Ag5{AA z5%-n%)m`Uk9s6B0JIB6kaJrH3z;!O?qLioid$n=1i4lrqDOhOBjy_{)&~}-)5yfq~ zDifYQW_zyMSN{T4L=Pc#ME$CI0va)*OlfjUkgHml<^y$ie%U+w2tv?6msX5G3P$2| z#}ZAU`GSWiS?V@OD{M@e!KF@7;%AG)l_V?oK94RRx+$P-W{4>of3`BKkt$%=Cw)rH zdIYbw;3}9c=gIK<(6$4kYGoOTejN0P^d6Erc!4g3XYGDqwO^ERSQsi+-!=}GN!)X>w*ji{P1H>wZ{UH6 zX{an&UKRFSLBQ>AVwy2F&Q`XK_T!efPgBi&dArxpzkCbg)}*sMQ3d!ynYcWix z_|npYGkjM4H_VCfl1lDfoX0C$VNvA=MKO()qiafz$U5Uzd^r!`sw6gjbZ`=$i^_!5*E*mpvGd zg5%DuZ3wIxm4a&5e0xsqmgD* zYGLt_w3+$h0%!yaVq;0um3t$XEA$yK5Pw|pv!C9zSh@wc?lNT5)5EG6KfIzyluy3k zUv3{ba}*4FG$(pmR^nCj0s#eCNQ4~D zqf!&>E;YJNTW#siz8Z?A8ZLGxgC714l~`@O#>4Wd5=#=oawdMM<77yT(2db7k@4Wp zE%_OM$dm`us47x}?QgqM7)?HZM=$E)8)}u-P|8J5me;Vs-QgJLa01hjt`-GZf4WXYs8)21~d#k7r)eGs%T zoTM@mjdY}?b}Wv#jHbE*Kz`zf{tRkAt>Qc*%XqotdNs+gjp4Eba2n*ly|eRwCt$ys zh~nX>+L&#zD&EyQzPT7a-T4FSO1;b<&IKtjfrbAlppEY|+K)W=f(08x4LSchxPcZ; z&=#FTV)*|ywEy4&Mhf@OGx`^f5+SBVpmLE zI=62U*W>|>NHHU*R5SE{tCw-<<`9FC;fkJ1!6_8;hau))x%lmF$sfp7&pD(kD96H)c$SxIVbZT_~A3 zq=}nfv}2Lwr=d1$v7i?b+##9FLkXQFg^h;+o~eoUixID_yyG_rQYZ@APz*{54#pA0 zKa>pR#RSC`{ME;>CYUt;d;KKSEM)0R4s_P8I^L$4pB(rX9NTKK(#8fN{R*CJBK6fj zg$x42U%7H@19J?CBoA$x)b)Wp621#55p_mM7E4!7(moooafA6ECF-Zt^1qol{;FtA zId&y37DAx8Lw|yrU@Kx3nm!Z4dtT`gHi}vb$}j&kSBP&eGZ2SUb=dNsnEsur&WEKT z)j_QnLZ)5KOXZBcM8xs9Gw{W^CwZ=9$>@IzmDQpcEd(2W&^0pw4EE)QCw7R^@bLL; z`;jKBD-xYQQ2yd6a!O3cQ1R6Y?8$v6opn%hlyAYLdyZByBqP$wt`$?@3G?GqjI-WI zFr(&N%W-LTiVx^1Ho9CEPW9Z5AOL?Gi|-iXg08;`9bHFOX<@)jh53F(ufGo7X8;-H z0l)YvMmC@|H(*Hq)5~Lc+wpVu7B-~+C=Jcxyn+Svys26)m~PyI-+W15v=_={`XO5l zHTRU5<6Q%(;GtU{_)M$_Z@txr^r;MoqLKj!*lxsJ-o*}P>e`FX{w*=TWA)e>mkquq zR>aObeoL>tvlW0b{B)@!*Q#MRNDVE1iwYTY0jEF7nOpwz-CzpVB)}t%DHnxnklM&j z{5nE-m_I0{MuyF@X{w^ZXId;$ZzxX3PofMm&=br2L2ZV2EG&HUL-^jmzMYczD$O`Z z?tN3awcrjqUCwXxK5<+SI?>|?PR!D$t||ghxxLKVr-Z6Dw@24}CgX^Pq}kM_7!5qg z%Z*9SS}A#;Gxrf6Yzc??{fJaAfRlxa)hoqd(HC= z7O1`LmWceuZ0Io0(jzpSr>;rS>W?x`vcp>fVVJl1r4thU;2&FV>(dCwX&XK8S-%w< z9R&H4wYnRLSj%_btvh@R$#$Oo0`rfNf}|CtyFYe$!fDRQ{TCn#B2oP}ys`rt2n8pY zPr*hy=n`c2!FY)-Q6avwsaI|ld#8}B@=2^@?xy>AgA!eO(n7ietiyp6B?7 zzEjdImQZsbH{m6+$_l~!C_p?uVA-?$aetr2!i(>2oJ8*9svS$rL?LjaYe}8@!`*TQ zq#ig1wLj@;6j;-piPNt2DLzE!!*!-C3&;{_h7O&)YC#HO4{G<&N_9zob7B%}yt1NC zn%`Mm`%Yl-g?yhDxiV;rXh^>0f5my?!*A)t)TMO`3`(N+D9}1!YxNnLK)>@{8hpI5 zD`Qq^)g>Q(N6@}yx=%cj9sNvX@vp)=nn6ncK;7JEiZgd^P2j%)6VR%zgBZHuTvAw6 z>wG|E*}P>alWtK8B}_gAdu^xWy(?U(@8_IgZ{Dg_YfH_i| zcEU*ZONGosHYDv&Sy(wA_rub(!|ZW;oHgD9RV~OgubHzEy>?~?K2bePVezxt2%>;P z-?ra7<4n?x&FYaE?cEGI)-)$tD$5+muBu}U?sPHFKe+hV5?aCTUXV`J=9AHC=o-*Q zXUuT@-0>M!)m+!o+T(oHaeB!5lJUF^EcXIqSUNsvI7$4;|X#{w!e5pUJ_ zak1J+C*mxrK*L>l)}}XDmB5!T;U_ev;jCB9B2`6t)Wa`7=7pam>YPepUHy>E1}-i| zx=cTq2|P}#Ey5pcy4D8*2oic4dykynV%zxoUkQ#ZS%}$Wd?mL`_nI;G*TmEF^KJp z_vh{DE5H7`9RZOzAku0+?DJ`Ocwh zS7jB5f%YHF1(sTSKSuTtezZh?ey859@nDV}*wx8We3^(^>c;D^k{15Qf0gLJdBw#% zK4AOfnWngIHTLC=dT)#w{3rZBSpE+*HU0+;Htp>`-fzW8*#W`aU5e&a;9&m+kS-Mo literal 71896 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≠dR0E9ICQ{-tcR;@{R^I5P#1GUH!p=-{c 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 diff --git a/out/jsonEditor/css/img/jsoneditor-icons.svg b/out/jsonEditor/css/img/jsoneditor-icons.svg deleted file mode 100644 index 1b40068..0000000 --- a/out/jsonEditor/css/img/jsoneditor-icons.svg +++ /dev/null @@ -1,893 +0,0 @@ - - - JSON Editor Icons - - - - image/svg+xml - - JSON Editor Icons - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/out/jsonEditor/css/jsoneditor.min.css b/out/jsonEditor/css/jsoneditor.min.css deleted file mode 100644 index 4bfb968..0000000 --- a/out/jsonEditor/css/jsoneditor.min.css +++ /dev/null @@ -1 +0,0 @@ -div.jsoneditor-field,div.jsoneditor-readonly,div.jsoneditor-value{border:1px solid transparent;min-height:16px;min-width:32px;padding:2px;margin:1px;word-wrap:break-word;float:left}div.jsoneditor-field p,div.jsoneditor-value p{margin:0}div.jsoneditor-value{word-break:break-word}div.jsoneditor-readonly{min-width:16px;color:gray}div.jsoneditor-empty{border-color:#d3d3d3;border-style:dashed;border-radius:2px}div.jsoneditor-field.jsoneditor-empty::after,div.jsoneditor-value.jsoneditor-empty::after{pointer-events:none;color:#d3d3d3;font-size:8pt}div.jsoneditor-field.jsoneditor-empty::after{content:"field"}div.jsoneditor-value.jsoneditor-empty::after{content:"value"}div.jsoneditor-value.jsoneditor-url{color:green;text-decoration:underline}a.jsoneditor-value.jsoneditor-url:focus,a.jsoneditor-value.jsoneditor-url:hover{color:#ee422e}div.jsoneditor td.jsoneditor-separator{padding:3px 0;vertical-align:top;color:gray}div.jsoneditor-field.jsoneditor-highlight,div.jsoneditor-field[contenteditable=true]:focus,div.jsoneditor-field[contenteditable=true]:hover,div.jsoneditor-value.jsoneditor-highlight,div.jsoneditor-value[contenteditable=true]:focus,div.jsoneditor-value[contenteditable=true]:hover{background-color:#FFFFAB;border:1px solid #ff0;border-radius:2px}div.jsoneditor-field.jsoneditor-highlight-active,div.jsoneditor-field.jsoneditor-highlight-active:focus,div.jsoneditor-field.jsoneditor-highlight-active:hover,div.jsoneditor-value.jsoneditor-highlight-active,div.jsoneditor-value.jsoneditor-highlight-active:focus,div.jsoneditor-value.jsoneditor-highlight-active:hover{background-color:#fe0;border:1px solid #ffc700;border-radius:2px}div.jsoneditor-value.jsoneditor-string{color:green}div.jsoneditor-value.jsoneditor-array,div.jsoneditor-value.jsoneditor-object{min-width:16px;color:grey}div.jsoneditor-value.jsoneditor-number{color:#ee422e}div.jsoneditor-value.jsoneditor-boolean{color:#ff8c00}div.jsoneditor-value.jsoneditor-null{color:#004ED0}div.jsoneditor-value.jsoneditor-invalid{color:#000}div.jsoneditor-tree button{width:24px;height:24px;padding:0;margin:0;border:none;cursor:pointer;background:url(img/jsoneditor-icons.svg)}div.jsoneditor-mode-form tr.jsoneditor-expandable td.jsoneditor-tree,div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree{cursor:pointer}div.jsoneditor-tree button.jsoneditor-collapsed{background-position:0 -48px}div.jsoneditor-tree button.jsoneditor-expanded{background-position:0 -72px}div.jsoneditor-tree button.jsoneditor-contextmenu{background-position:-48px -72px}div.jsoneditor-tree button.jsoneditor-contextmenu.jsoneditor-selected,div.jsoneditor-tree button.jsoneditor-contextmenu:focus,div.jsoneditor-tree button.jsoneditor-contextmenu:hover,tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu{background-position:-48px -48px}div.jsoneditor-tree :focus{outline:0}div.jsoneditor-tree button:focus{background-color:#f5f5f5;outline:#e5e5e5 solid 1px}div.jsoneditor-tree button.jsoneditor-invisible{visibility:hidden;background:0 0}div.jsoneditor{color:#1A1A1A;border:1px solid #3883fa;box-sizing:border-box;width:100%;height:100%;overflow:hidden;position:relative;padding:0;line-height:100%}div.jsoneditor,div.jsoneditor-outer{-moz-box-sizing:border-box;-webkit-box-sizing:border-box}div.jsoneditor-tree table.jsoneditor-tree{border-collapse:collapse;border-spacing:0;width:100%;margin:0}div.jsoneditor-outer{width:100%;height:100%;margin:-35px 0 0;padding:35px 0 0;box-sizing:border-box}div.jsoneditor-tree{width:100%;height:100%;position:relative;overflow:auto}textarea.jsoneditor-text{width:100%;height:100%;margin:0;box-sizing:border-box;outline-width:0;border:none;background-color:#fff;resize:none}div.jsoneditor-menu,textarea.jsoneditor-text{-moz-box-sizing:border-box;-webkit-box-sizing:border-box}tr.jsoneditor-highlight,tr.jsoneditor-selected{background-color:#e6e6e6}tr.jsoneditor-selected button.jsoneditor-contextmenu,tr.jsoneditor-selected button.jsoneditor-dragarea{visibility:hidden}tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu,tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea{visibility:visible}div.jsoneditor-tree button.jsoneditor-dragarea{background:url(img/jsoneditor-icons.svg)-72px -72px;cursor:move}div.jsoneditor-tree button.jsoneditor-dragarea:focus,div.jsoneditor-tree button.jsoneditor-dragarea:hover,tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea{background-position:-72px -48px}div.jsoneditor td,div.jsoneditor th,div.jsoneditor tr{padding:0;margin:0}div.jsoneditor td,div.jsoneditor td.jsoneditor-tree{vertical-align:top}.jsoneditor-schema-error,div.jsoneditor td,div.jsoneditor textarea,div.jsoneditor th,div.jsoneditor-field,div.jsoneditor-value{font-family:droid sans mono,consolas,monospace,courier new,courier,sans-serif;font-size:10pt;color:#1A1A1A}.jsoneditor-schema-error{cursor:default;display:inline-block;height:24px;line-height:24px;position:relative;text-align:center;width:24px}div.jsoneditor-tree .jsoneditor-schema-error{width:24px;height:24px;padding:0;margin:0 4px 0 0;background:url(img/jsoneditor-icons.svg)-168px -48px}.jsoneditor-schema-error .jsoneditor-popover{background-color:#4c4c4c;border-radius:3px;box-shadow:0 0 5px rgba(0,0,0,.4);color:#fff;display:none;padding:7px 10px;position:absolute;width:200px;z-index:4}.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above{bottom:32px;left:-98px}.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below{top:32px;left:-98px}.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left{top:-7px;right:32px}.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right{top:-7px;left:32px}.jsoneditor-schema-error .jsoneditor-popover:before{border-right:7px solid transparent;border-left:7px solid transparent;content:'';display:block;left:50%;margin-left:-7px;position:absolute}.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above:before{border-top:7px solid #4c4c4c;bottom:-7px}.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below:before{border-bottom:7px solid #4c4c4c;top:-7px}.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left:before,.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right:before{border-top:7px solid transparent;border-bottom:7px solid transparent;content:'';top:19px;margin-left:inherit;margin-top:-7px;position:absolute}.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left:before{border-left:7px solid #4c4c4c;right:-14px;left:inherit}.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right:before{border-right:7px solid #4c4c4c;left:-14px}.jsoneditor-schema-error:focus .jsoneditor-popover,.jsoneditor-schema-error:hover .jsoneditor-popover{display:block;-webkit-animation:fade-in .3s linear 1,move-up .3s linear 1;-moz-animation:fade-in .3s linear 1,move-up .3s linear 1;-ms-animation:fade-in .3s linear 1,move-up .3s linear 1}@-webkit-keyframes fade-in{from{opacity:0}to{opacity:1}}@-moz-keyframes fade-in{from{opacity:0}to{opacity:1}}@-ms-keyframes fade-in{from{opacity:0}to{opacity:1}}.jsoneditor .jsoneditor-text-errors{width:100%;border-collapse:collapse;background-color:#ffef8b;border-top:1px solid gold}.jsoneditor .jsoneditor-text-errors td{padding:3px 6px;vertical-align:middle}.jsoneditor-text-errors .jsoneditor-schema-error{border:none;width:24px;height:24px;padding:0;margin:0 4px 0 0;background:url(img/jsoneditor-icons.svg)-168px -48px}div.jsoneditor-contextmenu-root{position:relative;width:0;height:0}div.jsoneditor-contextmenu{position:absolute;z-index:99999}div.jsoneditor-contextmenu ul{position:relative;left:0;top:0;width:124px;background:#fff;border:1px solid #d3d3d3;box-shadow:2px 2px 12px rgba(128,128,128,.3);list-style:none;margin:0;padding:0}div.jsoneditor-contextmenu ul li button{padding:0;margin:0;width:124px;height:24px;border:none;cursor:pointer;color:#4d4d4d;background:0 0;line-height:26px;text-align:left}div.jsoneditor-contextmenu ul li button::-moz-focus-inner{padding:0;border:0}div.jsoneditor-contextmenu ul li button:focus,div.jsoneditor-contextmenu ul li button:hover{color:#1a1a1a;background-color:#f5f5f5;outline:0}div.jsoneditor-contextmenu ul li button.jsoneditor-default{width:92px}div.jsoneditor-contextmenu ul li button.jsoneditor-expand{float:right;width:32px;height:24px;border-left:1px solid #e5e5e5}div.jsoneditor-contextmenu div.jsoneditor-icon{float:left;width:24px;height:24px;border:none;padding:0;margin:0;background-image:url(img/jsoneditor-icons.svg)}div.jsoneditor-contextmenu ul li button div.jsoneditor-expand{float:right;width:24px;height:24px;padding:0;margin:0 4px 0 0;background:url(img/jsoneditor-icons.svg)0 -72px;opacity:.4}div.jsoneditor-contextmenu ul li button.jsoneditor-expand:focus div.jsoneditor-expand,div.jsoneditor-contextmenu ul li button.jsoneditor-expand:hover div.jsoneditor-expand,div.jsoneditor-contextmenu ul li button:focus div.jsoneditor-expand,div.jsoneditor-contextmenu ul li button:hover div.jsoneditor-expand,div.jsoneditor-contextmenu ul li.jsoneditor-selected div.jsoneditor-expand{opacity:1}div.jsoneditor-contextmenu div.jsoneditor-separator{height:0;border-top:1px solid #e5e5e5;padding-top:5px;margin-top:5px}div.jsoneditor-contextmenu button.jsoneditor-remove>div.jsoneditor-icon{background-position:-24px -24px}div.jsoneditor-contextmenu button.jsoneditor-remove:focus>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-remove:hover>div.jsoneditor-icon{background-position:-24px 0}div.jsoneditor-contextmenu button.jsoneditor-append>div.jsoneditor-icon{background-position:0 -24px}div.jsoneditor-contextmenu button.jsoneditor-append:focus>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-append:hover>div.jsoneditor-icon{background-position:0 0}div.jsoneditor-contextmenu button.jsoneditor-insert>div.jsoneditor-icon{background-position:0 -24px}div.jsoneditor-contextmenu button.jsoneditor-insert:focus>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-insert:hover>div.jsoneditor-icon{background-position:0 0}div.jsoneditor-contextmenu button.jsoneditor-duplicate>div.jsoneditor-icon{background-position:-48px -24px}div.jsoneditor-contextmenu button.jsoneditor-duplicate:focus>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-duplicate:hover>div.jsoneditor-icon{background-position:-48px 0}div.jsoneditor-contextmenu button.jsoneditor-sort-asc>div.jsoneditor-icon{background-position:-168px -24px}div.jsoneditor-contextmenu button.jsoneditor-sort-asc:focus>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-sort-asc:hover>div.jsoneditor-icon{background-position:-168px 0}div.jsoneditor-contextmenu button.jsoneditor-sort-desc>div.jsoneditor-icon{background-position:-192px -24px}div.jsoneditor-contextmenu button.jsoneditor-sort-desc:focus>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-sort-desc:hover>div.jsoneditor-icon{background-position:-192px 0}div.jsoneditor-contextmenu ul li button.jsoneditor-selected,div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus,div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover{color:#fff;background-color:#ee422e}div.jsoneditor-contextmenu ul li{overflow:hidden}div.jsoneditor-contextmenu ul li ul{display:none;position:relative;left:-10px;top:0;border:none;box-shadow:inset 0 0 10px rgba(128,128,128,.5);padding:0 10px;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}div.jsoneditor-contextmenu ul li ul li button{padding-left:24px;animation:all ease-in-out 1s}div.jsoneditor-contextmenu ul li ul li button:focus,div.jsoneditor-contextmenu ul li ul li button:hover{background-color:#f5f5f5}div.jsoneditor-contextmenu button.jsoneditor-type-string>div.jsoneditor-icon{background-position:-144px -24px}div.jsoneditor-contextmenu button.jsoneditor-type-string.jsoneditor-selected>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-type-string:focus>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-type-string:hover>div.jsoneditor-icon{background-position:-144px 0}div.jsoneditor-contextmenu button.jsoneditor-type-auto>div.jsoneditor-icon{background-position:-120px -24px}div.jsoneditor-contextmenu button.jsoneditor-type-auto.jsoneditor-selected>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-type-auto:focus>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-type-auto:hover>div.jsoneditor-icon{background-position:-120px 0}div.jsoneditor-contextmenu button.jsoneditor-type-object>div.jsoneditor-icon{background-position:-72px -24px}div.jsoneditor-contextmenu button.jsoneditor-type-object.jsoneditor-selected>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-type-object:focus>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-type-object:hover>div.jsoneditor-icon{background-position:-72px 0}div.jsoneditor-contextmenu button.jsoneditor-type-array>div.jsoneditor-icon{background-position:-96px -24px}div.jsoneditor-contextmenu button.jsoneditor-type-array.jsoneditor-selected>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-type-array:focus>div.jsoneditor-icon,div.jsoneditor-contextmenu button.jsoneditor-type-array:hover>div.jsoneditor-icon{background-position:-96px 0}div.jsoneditor-contextmenu button.jsoneditor-type-modes>div.jsoneditor-icon{background-image:none;width:6px}div.jsoneditor-menu{width:100%;height:35px;padding:2px;margin:0;box-sizing:border-box;color:#fff;background-color:#3883fa;border-bottom:1px solid #3883fa}div.jsoneditor-menu>button,div.jsoneditor-menu>div.jsoneditor-modes>button{width:26px;height:26px;margin:2px;padding:0;border-radius:2px;border:1px solid transparent;background:url(img/jsoneditor-icons.svg);color:#fff;opacity:.8;font-family:arial,sans-serif;font-size:10pt;float:left}div.jsoneditor-menu>button:hover,div.jsoneditor-menu>div.jsoneditor-modes>button:hover{background-color:rgba(255,255,255,.2);border:1px solid rgba(255,255,255,.4)}div.jsoneditor-menu>button:active,div.jsoneditor-menu>button:focus,div.jsoneditor-menu>div.jsoneditor-modes>button:active,div.jsoneditor-menu>div.jsoneditor-modes>button:focus{background-color:rgba(255,255,255,.3)}div.jsoneditor-menu>button:disabled,div.jsoneditor-menu>div.jsoneditor-modes>button:disabled{opacity:.5}div.jsoneditor-menu>button.jsoneditor-collapse-all{background-position:0 -96px}div.jsoneditor-menu>button.jsoneditor-expand-all{background-position:0 -120px}div.jsoneditor-menu>button.jsoneditor-undo{background-position:-24px -96px}div.jsoneditor-menu>button.jsoneditor-undo:disabled{background-position:-24px -120px}div.jsoneditor-menu>button.jsoneditor-redo{background-position:-48px -96px}div.jsoneditor-menu>button.jsoneditor-redo:disabled{background-position:-48px -120px}div.jsoneditor-menu>button.jsoneditor-compact{background-position:-72px -96px}div.jsoneditor-menu>button.jsoneditor-format{background-position:-72px -120px}div.jsoneditor-menu>div.jsoneditor-modes{display:inline-block;float:left}div.jsoneditor-menu>div.jsoneditor-modes>button{background-image:none;width:auto;padding-left:6px;padding-right:6px}div.jsoneditor-menu>button.jsoneditor-separator,div.jsoneditor-menu>div.jsoneditor-modes>button.jsoneditor-separator{margin-left:10px}div.jsoneditor-menu a{font-family:arial,sans-serif;font-size:10pt;color:#fff;opacity:.8;vertical-align:middle}div.jsoneditor-menu a:hover{opacity:1}div.jsoneditor-menu a.jsoneditor-poweredBy{font-size:8pt;position:absolute;right:0;top:0;padding:10px}table.jsoneditor-search div.jsoneditor-results,table.jsoneditor-search input{font-family:arial,sans-serif;font-size:10pt;color:#1A1A1A;background:0 0}table.jsoneditor-search{position:absolute;right:2px;top:2px}table.jsoneditor-search div.jsoneditor-frame{border:1px solid transparent;background-color:#fff;padding:0 2px;margin:0}table.jsoneditor-search div.jsoneditor-frame table{border-collapse:collapse}table.jsoneditor-search input{width:120px;border:none;outline:0;margin:1px;line-height:20px}table.jsoneditor-search .jsoneditor-results{color:#4d4d4d;padding-right:5px;line-height:24px}table.jsoneditor-search button{width:16px;height:24px;padding:0;margin:0;border:none;background:url(img/jsoneditor-icons.svg);vertical-align:top}table.jsoneditor-search button:hover{background-color:transparent}table.jsoneditor-search button.jsoneditor-refresh{width:18px;background-position:-99px -73px}table.jsoneditor-search button.jsoneditor-next{cursor:pointer;background-position:-124px -73px}table.jsoneditor-search button.jsoneditor-next:hover{background-position:-124px -49px}table.jsoneditor-search button.jsoneditor-previous{cursor:pointer;background-position:-148px -73px;margin-right:2px}table.jsoneditor-search button.jsoneditor-previous:hover{background-position:-148px -49px} \ No newline at end of file diff --git a/out/jsonEditor/editor.js b/out/jsonEditor/editor.js deleted file mode 100644 index 588a14a..0000000 --- a/out/jsonEditor/editor.js +++ /dev/null @@ -1,144 +0,0 @@ -var editor = new JSONEditor($('#jsonEditor').get(0)); -var onSaveMetadataHandler; - -function setMetadata(stringMetadata) { - editor.set(JSON.parse(stringMetadata)); -} - -function setPath(path) { - var selectedNode = editor.node && editor.node.findNode(path); - - if (selectedNode != null) { - _focusTo(selectedNode); - } -} - -function onSaveMetadata(handler) { - onSaveMetadataHandler = handler; -} - -function saveMetadata() { - if (onSaveMetadataHandler) { - onSaveMetadataHandler(editor.get()); - } -} - -function _getRootParent(parentValues, childMargin) { - var totalParent = parentValues - .parent() - .parent(); - var isExit = false; - var rootParent; - - while (!isExit) { - var previous = totalParent.prev(); - - if (previous.hasClass('jsoneditor-expandable')) { - var previousChild = previous.children().eq(2).children(); - var previousChildMargin = parseFloat(previousChild.css('margin-left')); - - if (previousChildMargin < childMargin && previousChildMargin != 0) { - rootParent = previous; - isExit = true; - } - - if (previousChildMargin == 0) { - isExit = true; - } - } - - totalParent = previous; - } - - return rootParent; -} - -function _focusToScripts(textContent) { - editor.node.childs.forEach(function (item) { - if (item.field === 'Scripts') { - item.childs.forEach(function (obj) { - obj.childs.forEach(function (field) { - if (field.previousField == 'Name' && field.previousValue == textContent) { - _focusTo(field); - } - }); - }); - } - }); -} - -function _focusTo(node) { - node.scrollTo(); - - setTimeout(function () { - node.focus(); - }, 300); -} - -function _getFocusable(fieldName, node) { - node = node || editor.node; - - if ($.isArray(node.childs)) { - for (var i = 0, ii = node.childs.length; i < ii; i++) { - if (node.childs[i].previousField === 'Name' && node.childs[i].previousValue === fieldName) { - return node.childs[i]; - } else { - var result = _getFocusable(fieldName, node.childs[i]); - - if (result) { - return result; - } - } - } - } else { - return undefined; - } -} - -$(document).on('click', function (event) { - if (!event.ctrlKey) { - return; - } - - var selection = editor.getSelection().dom; - var textContent = selection.textContent; - var parent = $(selection).parent().parent(); - var child = parent.children().eq(1); - - switch (child.text()) { - - case 'Name': - var parentValues = parent - .parent() - .parent(); - - var childMargin = parseFloat(parentValues.css('margin-left')); - - if (childMargin) { - var rootParent = _getRootParent(parentValues, childMargin); - - if (rootParent) { - var events = [ - 'OnLoaded', - 'OnClosed', - 'OnClick' - ]; - - if (events.indexOf(rootParent.find('.jsoneditor-field').text()) != -1) { - _focusToScripts(textContent); - } - } - } - - break; - - case 'Source': - var node = _getFocusable(textContent); - - if (node) { - _focusTo(node); - } - - break; - } -}); diff --git a/out/jsonEditor/index.html b/out/jsonEditor/index.html deleted file mode 100644 index 9651686..0000000 --- a/out/jsonEditor/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - -