Created
August 28, 2018 14:57
-
-
Save Piterden/1b1a05358da977b2e84559f4481b2096 to your computer and use it in GitHub Desktop.
My JS code from 2014 year
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| String.prototype.visualLength = function() { | |
| var ruler = document.getElementById("ruler"); | |
| ruler.innerHTML = this; | |
| return ruler.offsetWidth + 30; | |
| }; | |
| (function(document, window, webix, visax, undefined) { | |
| /** | |
| * Lexicon helper | |
| * @param {string} langKey | |
| * @return {string} localized value | |
| */ | |
| var _ = function(langKey) { | |
| return visax.lexicon[langKey] || langKey; | |
| }; | |
| /********************* | |
| * PRIVATE | |
| *********************/ | |
| var | |
| $$userSessionsStore, // session storage | |
| $$personsStore, // persons for current session storage | |
| currentSessionId, | |
| validPersons = [], // заполненные заявители | |
| winResizeEv, // event id | |
| timeoutID, // save timeout id | |
| mainWrapper, | |
| /** | |
| * Capitalize word | |
| * @param {string} word Word | |
| * @param {bool} onlyFirstLetter Return only first letter with dot | |
| * @return {string} Capitalized | |
| */ | |
| _C = function(word, onlyFirstLetter) { | |
| if(!word) return ''; | |
| word = word.toLowerCase(); | |
| return(!onlyFirstLetter) ? word[0].toUpperCase() + word.slice(1) | |
| + ' ' : word[0].toUpperCase() + '. '; | |
| }, | |
| /** | |
| * Коллбек таймаута ко всем событиям сохранения за | |
| */ | |
| updatePerson = function() { | |
| var $form = $$('visaForm'); | |
| if($form.isDirty()) { | |
| if (timeoutID !== undefined) { | |
| clearTimeout(timeoutID); | |
| } | |
| var values = $form.getValues(), | |
| index = $$('visaList').getIndexById(values.id); | |
| // Timeout before live save is run | |
| timeoutID = webix.delay(function() { | |
| values.action = 'person/update'; | |
| $$personsStore.updateItem(values.id, values); | |
| $$('personProps' + index).bind($form); | |
| if ($form.validate()) { | |
| } | |
| }, $form, [], 800); | |
| } | |
| }, | |
| /** | |
| * Загрузка новой сессии по id | |
| */ | |
| loadSession = function(id) { | |
| var session = $$userSessionsStore.getItem(id), | |
| persons = session.persons, | |
| url = 'visa/' + session.url_hash, | |
| title = document.title + ' | Пользователь ' + session.email; | |
| // Кешируем id активной сессии | |
| $$userSessionsStore.setCursor(id); | |
| mainWrapper.hideProgress(); | |
| $$personsStore.clearAll(); | |
| $$personsStore.parse(persons); | |
| initStep2(id); | |
| $$('tabbar').setValue('Step2'); | |
| $$('Step2').enable(); | |
| window.history.pushState({ webix: true }, title, url); | |
| initStep3(session, persons); | |
| }, | |
| /** | |
| * Инициализация 2 шага - главная форма | |
| * Initialize step 2 - main order form | |
| * @param {number} id of current session | |
| * @return {void} | |
| */ | |
| initStep2 = function(id) { | |
| var $modal = $$('sessions_list'), | |
| $personsList = $$('visaList'), | |
| $singlePersonForm = $$('visaForm'), | |
| recentPersIndex = getRecentPersonIndex(id), | |
| recentPersId = $$personsStore.getIdByIndex(recentPersIndex), | |
| persons = $$userSessionsStore.getItem(id).persons, | |
| $surnamesList = $$('surnamesList'); | |
| id = id || currentSessionId; | |
| if($modal !== undefined) $modal.close(); | |
| // Связывание хранилищ, форм и списков | |
| $personsList.sync($$personsStore); | |
| $$personsStore.addBind($personsList); | |
| $singlePersonForm.bind($personsList); | |
| // Выбор актуального заявителя и сессии | |
| $personsList.select(recentPersId); | |
| $$userSessionsStore.setCursor(id); | |
| // Обновление списка фамилий | |
| $surnamesList.updateSelf(recentPersId); | |
| bindEventListeners($singlePersonForm, $personsList, $surnamesList); | |
| updateAllCosts(); | |
| }, | |
| /** | |
| * Toggle person in form by click on list item | |
| * @param {number} oldId | |
| * @return {void} | |
| */ | |
| togglePerson = function($singlePersonForm, oldId) { | |
| $$personsStore.updateItem(oldId, $singlePersonForm.getDirtyValues()); | |
| }, | |
| /** | |
| * Обновляет превью полей загрузки файлов | |
| * @param {[type]} personId [description] | |
| * @return {[type]} [description] | |
| */ | |
| updateUploaderThumbs = function(personId) { | |
| var person = $$personsStore.getItem(personId), | |
| $lastVisaThumb = $$('last_visa_scan_thumb'), | |
| $passportThumb = $$('passport_scan_thumb'); | |
| $lastVisaThumb.define('data', { url: person.last_visa_scan }); | |
| $passportThumb.define('data', { url: person.passport_scan }); | |
| }, | |
| /** | |
| * Вешаем обработчики событий | |
| * @return {[type]} [description] | |
| */ | |
| bindEventListeners = function($singlePersonForm, $personsList, $surnamesList) { | |
| /** | |
| * Переключение заявителей в списке | |
| * Persons list item click handler (side bar step 2) | |
| */ | |
| $personsList.attachEvent('onItemClick', function(newId) { | |
| /* eslint-disable no-console */ | |
| console.log(newId); | |
| /* eslint-enable no-console */ | |
| var oldId = this.getSelectedId(); | |
| if(newId == oldId) return false; | |
| if($singlePersonForm.isDirty()) { | |
| togglePerson($singlePersonForm, oldId); | |
| } | |
| $surnamesList.updateSelf(newId); | |
| updateUploaderThumbs(newId); | |
| }); | |
| /** | |
| * Обновление после выбора в списке | |
| */ | |
| $personsList.attachEvent('onSelectChange', function(id) { | |
| $surnamesList.updateSelf(id); | |
| }); | |
| /** | |
| * После редактирования фамилии в списке предыдущих фамилий | |
| */ | |
| $surnamesList.attachEvent("onAfterEditStop", function(state, editor) { | |
| if(state.value != state.old) { | |
| this.updateSelfStr(); | |
| } | |
| }); | |
| $surnamesList.$view.addEventListener('keyup', function(e) { | |
| var text = e.target.value, | |
| width = String(text).visualLength(); | |
| e.target.parentNode.style.width = width + "px"; | |
| }); | |
| /** | |
| * Прекращение ввода текста внутри формы | |
| * Handling 'onkeyup' native DOM event | |
| * @param (HTML_Node, event, handler, this) | |
| * @return event id | |
| */ | |
| webix.event($singlePersonForm.getNode(), 'keyup', function() { | |
| setTimeout(updatePerson, 0); | |
| }, { master: $$('visaForm') }); | |
| }, | |
| /** | |
| * Получает индекс заявителя в списке | |
| * @param {Number} id заявителя | |
| * @return {Number} индекс | |
| */ | |
| getPersonIndex = function(id) { | |
| return $$personsStore.getIndexById(id); | |
| }, | |
| /** | |
| * Формирует заголовок заявителя из ФИО | |
| * @param {Object} person объект заявителя | |
| * @return {String} Фамилия И.О. или Заявитель № | |
| */ | |
| getPersonTitle = function(person) { | |
| return person.sirname && person.sirname.length ? | |
| _C(person.sirname) + _C(person.firstname) + _C(person.patronymic) : | |
| false; | |
| }, | |
| /** | |
| * Получает свойства заявителя для шага 3 | |
| * @param {Object} person объект заявителя | |
| * @return {Array} список свойств | |
| */ | |
| getPropertiesList = function(person) { | |
| var elems = []; | |
| for(var key in person) { | |
| if(person.hasOwnProperty(key) && key != 'id' && key != 'session') { | |
| var val = person[key] || _('empty'), | |
| el = { label: _(key), type: "text", id: key, value: val }; | |
| if(key == 'birth_date' || key == 'desired_time') { | |
| el.type = 'date'; | |
| el.format = webix.i18n.parseFormatStr; | |
| } | |
| elems.push(el); | |
| } | |
| } | |
| return elems; | |
| }, | |
| /** | |
| * Добавляет заявителя на 3 шаг в аккордеон | |
| * @param {Object} person объект заявителя | |
| * @param {Number} i индекс в списке | |
| */ | |
| addPersonToAccordion = function(person, i) { | |
| if(i === undefined) { | |
| i = getPersonIndex(person.id); | |
| } | |
| var elems = getPropertiesList(person), | |
| title = getPersonTitle(person) || 'Заявитель №' + (i + 1), | |
| header = title + ' ' + person.price, | |
| headerAlt = title + '(Открыть) ' + person.price, | |
| viewConfig = { | |
| borderless: true, | |
| header: header, | |
| headerAlt: headerAlt, | |
| headerHeight: 41, | |
| headerAltHeight: 41, | |
| view: 'accordionitem', | |
| collapsed: true, | |
| css: 'collapsed', | |
| body: { | |
| view: 'property', | |
| id: 'personProps' + i, | |
| editable: false, | |
| elements: elems, | |
| nameWidth: 400, | |
| height: elems.length * 40 | |
| } | |
| }; | |
| $$('propsAccord').addView(viewConfig, i + 2); | |
| }, | |
| /** | |
| * Init step 3 | |
| * @param {object} session | |
| * @param {array} persons | |
| * @return {void} | |
| */ | |
| initStep3 = function(session, persons) { | |
| var $sessionPS = $$('sessionProps'); | |
| $sessionPS.setValues(session); | |
| $sessionPS.show(); | |
| for(var i = 0, l = persons.length; i < l; i++) { | |
| var person = persons[i]; | |
| addPersonToAccordion(person, i); | |
| } | |
| updateAllCosts(); | |
| }, | |
| /** | |
| * Получает интервал дат | |
| * @return {Array} интервал от и до | |
| */ | |
| getDesiredDatesRange = function() { | |
| var start = new Date(), | |
| y = start.getFullYear(), | |
| m = start.getMonth(), | |
| d = start.getDate(), | |
| end = new Date(y, m + 3, d); | |
| return [start, end]; | |
| }, | |
| /** | |
| * Generate URL helper | |
| * @param {string} model name | |
| * @param {string} action name | |
| * @return {string} url | |
| */ | |
| getAjaxUrl = function(model, action) { | |
| return visax.web_connector_url + "?action=" + model + "/" + action; | |
| }, | |
| /** | |
| * Обработчик всех AJAX коллбеков | |
| * @param {[type]} resp [description] | |
| * @return {[type]} [description] | |
| */ | |
| ajaxCallback = function(data) { | |
| if(typeof data == 'string') { | |
| data = JSON.parse(data); | |
| } | |
| mainWrapper.hideProgress(); | |
| if(data.success) { | |
| return window[data.message](data); | |
| } | |
| return webix.message({ | |
| type: "error", | |
| text: data.message, | |
| expire: 5000 | |
| }); | |
| }, | |
| /** | |
| * Select person in loaded session helper | |
| * @param {number} s_id session id | |
| * @return {number} person id | |
| */ | |
| getRecentPersonIndex = function(sessionId) { | |
| return 0; | |
| }, | |
| /** | |
| * Список количеств заявителей | |
| * @return {Array} опции | |
| */ | |
| getPersonsLimit = function() { | |
| var mp = Number(visax.max_persons), | |
| optArr = []; | |
| for(var i = 1; i <= mp; i++) { | |
| optArr.push({ id: i, value: i }); | |
| } | |
| return optArr; | |
| }, | |
| /** | |
| * Получает возраст заявителя по ID | |
| * @param {Number} id | |
| * @return {Number} возраст (лет) | |
| */ | |
| getPersonAgeById = function(id) { | |
| var person = $$personsStore.getItem(id) || {}, | |
| b_d = person.birth_date || visax.default_birth_date; | |
| return ((new Date()) - b_d) / 1000 / 60 / 60 / 24 / 365; | |
| }, | |
| /** | |
| * Считает цену для заявителя по ID | |
| * @param {Number} id | |
| * @return {Number} цена | |
| */ | |
| calcPersonCostById = function(id) { | |
| id = id || $$('visaForm').getValues().id; | |
| var person = $$personsStore.getItem(id), | |
| cost = 540 + 500, | |
| age = getPersonAgeById(id); | |
| // Age rules | |
| if(age > 17 && age <= 64) cost -= 50; | |
| if(age > 64 && age <= 69) cost += 400; | |
| if(age > 69 && age <= 74) cost += 850; | |
| if(age > 74 && age <= 79) cost += 1300; | |
| if(age > 79 && age <= 84) cost += 1750; | |
| if(age > 84) cost += 2650; | |
| // Region rules | |
| if(!!person && person.registration_region != 1) cost += 50; | |
| return cost; | |
| }, | |
| /** | |
| * Обновление цен | |
| * @return {[type]} [description] | |
| */ | |
| updateAllCosts = function() { | |
| var persons = $$personsStore.data.getRange(), | |
| session = $$userSessionsStore.getItem($$userSessionsStore.getCursor()) || {}, | |
| totalCost = 0; | |
| if(session.state && session.state == 'filling') { | |
| persons.forEach(function(person, index) { | |
| var personCost = calcPersonCostById(person.id); | |
| totalCost += personCost; | |
| }); | |
| } | |
| var data = { cost: totalCost }; | |
| $$('priceBlock').define('data', data); | |
| $$('priceBlockClone').define('data', data); | |
| }, | |
| /** | |
| * Обновляет превью документов | |
| * @param {String} uploaderId | |
| * @param {Object} data | |
| */ | |
| refreshThumbs = function(uploaderId, data) { | |
| var $uploaderView = $$(uploaderId), | |
| files = getFileFromField($uploaderView), | |
| $thumbView = $$($uploaderView.config.name + '_thumb'), | |
| fileUrl = data.url; | |
| if(fileUrl) { | |
| $uploaderView.setValue(fileUrl); | |
| } else { | |
| if(files.length > 0 && files[0].status == 'server') { | |
| fileUrl = files[0].value; | |
| } | |
| } | |
| $thumbView.define('data', { | |
| url: fileUrl || '' | |
| }); | |
| setTimeout(updatePerson, 0); | |
| return true; | |
| }, | |
| /** | |
| * Получает файл из файлового поля | |
| * @param {Object} $uploaderView | |
| * @return {Array} список файлов | |
| */ | |
| getFileFromField = function($uploaderView) { | |
| return $uploaderView && $uploaderView.files.data.getRange(); | |
| }, | |
| /** | |
| * Вернет true при возрасте меньше 18 лет | |
| * @return {Boolean} | |
| */ | |
| ageLowerThen18 = function() { | |
| var $form = $$('visaForm'), | |
| now = Date.now(), birth_date; | |
| if ($form !== undefined) { | |
| birth_date = Date.parse($form.getValues().birth_date); | |
| return (now - birth_date) / 1000 < (18 * 60 * 60 * 24 * 365); | |
| } | |
| return false; | |
| }, | |
| /** | |
| * Шаблон формы оплаты | |
| * @param {Object} obj | |
| */ | |
| TplPaymentForm = function(obj) { | |
| return "<div class='price-wrap'>" + | |
| "<div class='top-line'>" + | |
| "<span class='label'>Итого: </span>" + | |
| "<strong id='totalPrice'>" + webix.i18n.priceFormat(obj.cost) + "</strong>" + | |
| "</div>" + | |
| "<div class='bottom-line hide'>" + | |
| "<form action='https://rbkmoney.ru/acceptpurchase.aspx' name='pay' method='POST'>" + | |
| "<input type='hidden' name='eshopId' value=''>" + | |
| "<input type='hidden' name='orderId' value=''>" + | |
| "<input type='hidden' name='serviceName' value=''>" + | |
| "<input type='hidden' name='recipientAmount' value=''>" + | |
| "<input type='hidden' name='recipientCurrency' value='RUR'>" + | |
| "<input type='hidden' name='user_email' value=''>" + | |
| "<input type='hidden' name='successUrl' value=''>" + | |
| "<input type='hidden' name='failUrl' value=''>" + | |
| "<input type='hidden' name='userField_1' value=''>" + | |
| "<input type='hidden' name='userField_2' value=''>" + | |
| "<button id='toPay' class='btn btn-primary' type='submit'>Проверить данные и оплатить</button>" + | |
| "</form>" + | |
| "</div>" + | |
| "</div>"; | |
| }, | |
| /** | |
| * Шаг 1 | |
| */ | |
| UiStep1 = function() { | |
| return { // STEP 1 | |
| view: "form", | |
| id: "Step1", | |
| scroll: false, | |
| borderless: true, | |
| elements: [{ | |
| view: "template", | |
| template: "<div class='header-wrap'>" + | |
| "<h2>Шаг 1 - оформление визы</h2>" + | |
| "</div>", | |
| height: 77, | |
| borderless: true | |
| }, { | |
| cols: [{ | |
| view: "richselect", | |
| id: "countryList", | |
| name: "country", | |
| label: _('country'), | |
| placeholder: _('country_pls'), | |
| invalidMessage: _('country_inv'), | |
| icon: "bars", | |
| gravity: 1, | |
| value: 1, | |
| options: { | |
| view: "suggest", | |
| id: "countryListSuggest", | |
| borderless: true, | |
| body: { | |
| header: true, | |
| template: "<span>#name#</span>", | |
| url: getAjaxUrl('country', 'getlist') | |
| }, | |
| }, | |
| }, { | |
| view: "template", | |
| gravity: 2, | |
| borderless: true, | |
| template: _('country_cmnt') | |
| }] | |
| }, { | |
| cols: [{ | |
| view: "richselect", | |
| name: "persons_count", | |
| label: _('persons_count'), | |
| placeholder: _('persons_count_pls'), | |
| invalidMessage: _('persons_count_inv'), | |
| icon: "bars", | |
| gravity: 1, | |
| value: 1, | |
| options: getPersonsLimit() | |
| }, { | |
| view: "template", | |
| gravity: 2, | |
| borderless: true, | |
| template: _('persons_count_cmnt') | |
| }] | |
| }, { | |
| cols: [{ | |
| view: "phonefield", | |
| id: "phoneMasked", | |
| name: "phone", | |
| label: _('phone'), | |
| gravity: 1, | |
| icon: false, | |
| value: "(123) 456-78-90" | |
| }, { | |
| view: "template", | |
| gravity: 2, | |
| borderless: true, | |
| template: _('phone_cmnt') | |
| }] | |
| }, { | |
| cols: [{ | |
| view: "text", | |
| name: "email", | |
| label: _('email'), | |
| placeholder: _('email_pls'), | |
| validate: "isEmail", | |
| gravity: 1, | |
| value: "denfromp@gmail.com" | |
| }, { | |
| view: "template", | |
| gravity: 2, | |
| borderless: true, | |
| template: _('email_cmnt') | |
| }] | |
| }, { | |
| margin: 5, | |
| cols: [{ | |
| view: "button", | |
| type: "form", | |
| value: _('clear'), | |
| gravity: 3, | |
| css: "clean-butt", | |
| click: function() { | |
| this.getFormView().clear(); | |
| } | |
| }, { | |
| view: "button", | |
| type: "form", | |
| value: _('continue'), | |
| gravity: 2, | |
| css: "submit-butt", | |
| click: function() { | |
| var form = this.getFormView(); | |
| if(!form.validate()) { | |
| return webix.message({ | |
| type: "error", | |
| text: _('invalid_form'), | |
| expire: 5000 | |
| }); | |
| } | |
| mainWrapper.showProgress({ | |
| type: "icon", | |
| delay: 3000 | |
| }); | |
| webix.ajax().post(getAjaxUrl('session', 'create'), form.getValues(), ajaxCallback); | |
| } | |
| }, { | |
| view: "spacer", | |
| gravity: 10 | |
| }] | |
| }, { | |
| view: "text", | |
| name: "step", | |
| hidden: true, | |
| readonly: true, | |
| value: "check" | |
| }], | |
| elementsConfig: { | |
| labelPosition: "top", | |
| required: true, | |
| inputHeight: 44, | |
| bottomPadding: 44 | |
| } | |
| }; | |
| }, | |
| /** | |
| * Главная форма (шаг 2) | |
| */ | |
| UiMainForm = function() { | |
| return { // MAIN FORM | |
| id: "visaForm", | |
| view: "form", | |
| gravity: 3, | |
| scroll: false, | |
| autoheight: true, | |
| elementsConfig: { | |
| labelPosition: "top", | |
| margin: 10 | |
| }, | |
| elements: [ | |
| { | |
| view: "template", | |
| template: "<div class='header-wrap'>" + | |
| "<h2>Шаг 2 - данные о заявителях</h2>" + | |
| "</div>", | |
| height: 77, | |
| borderless: true | |
| }, { | |
| cols: [{ | |
| view: "text", | |
| name: "sirname", | |
| required: true, | |
| label: _('sirname'), | |
| placeholder: _('sirname_pls') | |
| }, { | |
| view: "text", | |
| name: "firstname", | |
| required: true, | |
| label: _('firstname'), | |
| placeholder: _('firstname_pls') | |
| }, { | |
| view: "text", | |
| name: "patronymic", | |
| label: _('patronymic'), | |
| placeholder: _('patronymic') | |
| }], | |
| height: 68 | |
| }, { | |
| view: "text", | |
| name: "prev_surnames", | |
| id: "prevSurStr", | |
| hidden: true, | |
| height: 68, | |
| }, { | |
| view: "editlist", | |
| name: "prev_surnames_list", | |
| id: "surnamesList", | |
| label: _('prev_surnames'), | |
| placeholder: _('prev_surnames_pls'), | |
| height: 68, | |
| editable: true, | |
| editor: "text", | |
| editValue: "value", | |
| editaction: "click", | |
| scroll: false, | |
| layout: 'x' | |
| }, { | |
| height: 68, | |
| cols: [{ | |
| view: "datepicker", | |
| id: "birthDatepicker", | |
| name: "birth_date", | |
| timepicker: false, | |
| minTime: "8:00", | |
| maxTime: "18:30", | |
| icons: true, | |
| required: true, | |
| label: _('birth_date'), | |
| placeholder: _('birth_date_pls'), | |
| on: { | |
| "onChange": function(/*newv, oldv*/) { | |
| var $parentsGroup = $$('parentsGroup'), | |
| $maritalStatus = $$('maritalStatus'), | |
| $tripTarget = $$('tripTarget'), | |
| $upload = $$('uploadPassportAPI'), | |
| $desiredDateField = $$('desiredDateField'), | |
| $desiredTimeField = $$('desiredTimeField'), | |
| button = $upload.$view.getElementsByTagName('button'); | |
| if (ageLowerThen18()) { // Меньше 18 | |
| $maritalStatus.define('required', false); | |
| $desiredDateField.define('required', false); | |
| $desiredTimeField.define('required', false); | |
| $parentsGroup.show(); | |
| $maritalStatus.hide(); | |
| $tripTarget.hide(); | |
| if(button.length > 0) { | |
| button[0].innerText = "Загрузить скан свидетельства о рождении"; | |
| } | |
| } else { // Больше 18 | |
| $maritalStatus.define('required', true); | |
| $desiredDateField.define('required', true); | |
| $desiredTimeField.define('required', true); | |
| $parentsGroup.hide(); | |
| $maritalStatus.show(); | |
| $tripTarget.show(); | |
| if(button.length > 0) { | |
| button[0].innerText = "Загрузить скан паспорта"; | |
| } | |
| } | |
| $maritalStatus.refresh(); | |
| setTimeout(updatePerson, 0); | |
| }, | |
| "onAfterRender": function() { | |
| this.getPopup().attachEvent("onShow", function() { | |
| var upButton = this.$view.getElementsByClassName('webix_cal_month_name')[0]; | |
| upButton.click(); | |
| upButton.click(); | |
| }); | |
| } | |
| } | |
| }, { | |
| view: "phonefield", | |
| id: "dynamicPhone", | |
| name: "phone", | |
| required: true, | |
| label: _('phone'), | |
| }, { | |
| view: "richselect", | |
| id: "regionsList", | |
| required: true, | |
| label: _('registration_region'), | |
| placeholder: _('registration_region_pls'), | |
| name: "registration_region", | |
| // invalidMessage: _('registration_region_inv'), | |
| options: { | |
| view: "suggest", | |
| id: "regoinsListSuggest", | |
| borderless: true, | |
| body: { | |
| header: true, | |
| data: webix.storage.local.get('data_helpers').regions, | |
| }, | |
| }, | |
| on: { | |
| "onChange": function() { | |
| setTimeout(updatePerson, 0); | |
| } | |
| } | |
| }] | |
| }, { | |
| view: "fieldset", | |
| id: "parentsGroup", | |
| label: _('parents_group'), | |
| hidden: true, | |
| body: { | |
| rows: [{ | |
| height: 68, | |
| cols: [{ | |
| view: "text", | |
| name: "mother_fio", | |
| label: _('mother_fio'), | |
| placeholder: _('mother_fio_pls'), | |
| }, { | |
| view: "phonefield", | |
| name: "mother_phone", | |
| label: _('mother_phone'), | |
| placeholder: _('mother_phone_pls'), | |
| }] | |
| }, { | |
| view: "text", | |
| name: "mother_address", | |
| label: _('mother_address'), | |
| placeholder: _('mother_address_pls'), | |
| height: 68, | |
| }, { | |
| height: 68, | |
| cols: [{ | |
| view: "text", | |
| name: "father_fio", | |
| label: _('father_fio'), | |
| placeholder: _('father_fio_pls'), | |
| }, { | |
| view: "phonefield", | |
| name: "father_phone", | |
| label: _('father_phone'), | |
| placeholder: _('father_phone_pls'), | |
| }] | |
| }, { | |
| view: "text", | |
| name: "father_address", | |
| label: _('father_address'), | |
| placeholder: _('father_address_pls'), | |
| height: 68, | |
| }] | |
| } | |
| }, { | |
| height: 68, | |
| cols: [{ | |
| view: "richselect", | |
| id: "maritalStatus", | |
| name: "marital_status", | |
| required: true, | |
| label: _('marital_status'), | |
| placeholder: _('marital_status_pls'), | |
| borderless: true, | |
| value: 0, | |
| hidden: ageLowerThen18(), | |
| options: [ | |
| { id: 0, value: _('no_married') }, | |
| { id: 1, value: _('married') }, | |
| { id: 2, value: "Разведен / Разведена" }, | |
| { id: 3, value: "Вдовец / Вдова" } | |
| ], | |
| on: { | |
| "onChange": function() { | |
| setTimeout(updatePerson, 0); | |
| } | |
| } | |
| }, { | |
| height: 68, | |
| view: "datepicker", | |
| name: "desired_time", | |
| id: "desiredDateField", | |
| required: true, | |
| label: _('desired_date'), | |
| placeholder: _('desired_date_pls'), | |
| timepicker: false, | |
| suggest: { | |
| type: "calendar", | |
| body: { | |
| minDate: getDesiredDatesRange()[0], | |
| maxDate: getDesiredDatesRange()[1], | |
| blockDates: function(date) { | |
| return date.getDay() > 5 || date.getDay() < 1; | |
| } | |
| }, | |
| }, | |
| on: { | |
| "onChange": function(nVal) { | |
| var t = $$('desiredTimeField').getValue() || '00:00', | |
| a = t.split(':'); | |
| if(!nVal || typeof nVal == 'string') { | |
| nVal = new Date(nVal); | |
| } | |
| nVal.setHours(a[0], a[1]); | |
| setTimeout(updatePerson, 0); | |
| } | |
| } | |
| }, { | |
| height: 68, | |
| view: "richselect", | |
| id: "desiredTimeField", | |
| required: true, | |
| label: _('desired_time'), | |
| placeholder: _('desired_time_pls'), | |
| borderless: true, | |
| options: webix.storage.local.get('data_helpers').workTimes, | |
| on: { | |
| "onChange": function(nVal) { | |
| var $dt = $$('desiredDateField'), | |
| d = $dt.getValue() || new Date(), | |
| a = nVal.split(':'); | |
| d.setHours(a[0], a[1]); | |
| $dt.setValue(d); | |
| $$('visaForm').setDirty(true); | |
| setTimeout(updatePerson, 0); | |
| }, | |
| "onAfterRender": function() { | |
| var d = $$('desiredDateField').getValue(); | |
| if(!d || typeof d == 'string') { | |
| d = new Date(d); | |
| } | |
| var str = ('0' + d.getHours()).slice(-2) + ':' + ('0' + d.getMinutes()).slice(-2), | |
| timeSet = webix.storage.local.get('data_helpers').workTimes | |
| .find(function(t) { | |
| return t.id == str; | |
| }); | |
| if(timeSet !== -1) { | |
| this.setValue(str); | |
| } | |
| } | |
| } | |
| }] | |
| }, { | |
| height: 68, | |
| cols: [{ | |
| view: "richselect", | |
| id: "tripTarget", | |
| name: "trip_target", | |
| required: !ageLowerThen18(), | |
| label: _('trip_target'), | |
| placeholder: _('trip_target_pls'), | |
| borderless: true, | |
| gravity: 3, | |
| hidden: ageLowerThen18(), | |
| options: webix.storage.local.get('data_helpers').tripTargets, | |
| on: { | |
| "onChange": function(val) { | |
| var $userTripTarget = $$('userTripTarget'); | |
| if (val == 'others') { | |
| $userTripTarget.show(); | |
| $userTripTarget.define('required', true); | |
| } else { | |
| $userTripTarget.hide(); | |
| $userTripTarget.define('required', false); | |
| } | |
| $userTripTarget.refresh(); | |
| setTimeout(updatePerson, 0); | |
| } | |
| } | |
| }, { | |
| view: "richselect", | |
| id: "visaType", | |
| name: "visa_type", | |
| required: true, | |
| label: _('visa_type'), | |
| placeholder: _('visa_type_pls'), | |
| borderless: true, | |
| gravity: 3, | |
| options: [ | |
| { id: "one", value: _('one_time') }, | |
| { id: "many", value: _('many_time') } | |
| ], | |
| on: { | |
| "onChange": function(val) { | |
| var $tripDays = $$('tripDays'), | |
| $visaType = $$('visaType'); | |
| if (val == 'one') { | |
| $visaType.define('gravity', 2); | |
| $visaType.refresh(); | |
| $tripDays.show(); | |
| } else { | |
| $visaType.define('gravity', 3); | |
| $visaType.refresh(); | |
| $tripDays.hide(); | |
| } | |
| setTimeout(updatePerson, 0); | |
| } | |
| } | |
| }, { | |
| view: "text", | |
| id: "tripDays", | |
| name: "trip_days", | |
| gravity: 1, | |
| label: _('trip_days'), | |
| placeholder: _('trip_days_pls'), | |
| borderless: true, | |
| hidden: true | |
| }, { | |
| view: "richselect", | |
| name: "employment", | |
| required: true, | |
| label: _('employment'), | |
| placeholder: _('employment_pls'), | |
| gravity: 3, | |
| options: [ | |
| { id: "work", value: _('work') }, | |
| { id: "vuz", value: _('vuz') }, | |
| { id: "school", value: _('school') }, | |
| { id: "not_work", value: _('not_work') }, | |
| { id: "pension", value: _('pension') } | |
| ], | |
| on: { | |
| "onChange": function() { | |
| var $employmentGroup = $$('employment_group'); | |
| if(!this.data.value || this.data.value == 'not_work' || this.data.value == 'pension') { | |
| $employmentGroup.hide(); | |
| } else { | |
| $employmentGroup.show(); | |
| } | |
| setTimeout(updatePerson, 0); | |
| } | |
| } | |
| }] | |
| }, { | |
| height: 68, | |
| id: "userTripTarget", | |
| hidden: true, | |
| required: true, | |
| view: "text", | |
| name: "user_trip_target", | |
| label: _('user_trip_target'), | |
| placeholder: _('user_trip_target_pls') | |
| }, { | |
| view: "fieldset", | |
| id: "employment_group", | |
| label: _('employment_group'), | |
| hidden: true, | |
| body: { | |
| rows: [{ | |
| height: 68, | |
| view: "text", | |
| name: "empl_function", | |
| label: _('empl_function'), | |
| placeholder: _('empl_function_pls') | |
| }, { | |
| height: 68, | |
| view: "text", | |
| name: "empl_address", | |
| label: _('empl_address'), | |
| placeholder: _('empl_address_pls') | |
| }, { | |
| height: 68, | |
| view: "text", | |
| name: "empl_phone", | |
| label: _('empl_phone'), | |
| placeholder: _('empl_phone_pls') | |
| }] | |
| } | |
| }, { | |
| height: 108, | |
| cols: [{ | |
| view: "textarea", | |
| name: "registration_address", | |
| required: true, | |
| label: _('registration_address'), | |
| placeholder: _('registration_address_pls'), | |
| }, { | |
| view: "textarea", | |
| name: "residential_address", | |
| required: true, | |
| label: _('residential_address'), | |
| placeholder: _('residential_address_pls'), | |
| }] | |
| }, { | |
| height: 465, | |
| cols: [{ | |
| rows: [{ | |
| view: "visaxupload", | |
| name: "passport_scan", | |
| id: "uploadPassportAPI", | |
| value: _('passport_scan_text'), | |
| formData: { | |
| source: 2, | |
| path: "passportscans/" | |
| } | |
| }, { | |
| view: "uploaderthumb", | |
| id: "passport_scan_thumb", | |
| uploader: "uploadPassportAPI" | |
| }] | |
| }, { | |
| rows: [{ | |
| view: "checkbox", | |
| name: "last_visa", | |
| labelRight: _('last_visa'), | |
| customCheckbox: false, | |
| height: 40, | |
| relatedView: "last_visa_scan_wrap", | |
| relatedAction: "show", | |
| on: { | |
| "onChange": function() { | |
| setTimeout(updatePerson, 0); | |
| } | |
| } | |
| }, { | |
| id: "last_visa_scan_wrap", | |
| rows: [{ | |
| view: "visaxupload", | |
| name: "last_visa_scan", | |
| id: "uploadVizaAPI", | |
| value: _('last_visa_scan_text'), | |
| formData: { | |
| source: 2, | |
| path: "visascans/" | |
| } | |
| }, { | |
| view: "uploaderthumb", | |
| id: "last_visa_scan_thumb", | |
| uploader: "uploadVizaAPI" | |
| }] | |
| }] | |
| }] | |
| }, | |
| { view: "text", name: "price", id: "priceField", hidden: true, value: 0 }, | |
| { view: "text", name: "id", hidden: true, readonly: true, }, | |
| { view: "text", name: "session", hidden: true, readonly: true, } | |
| ] | |
| }; | |
| }, | |
| /** | |
| * Список заявителей сбоку (шаг 2) | |
| */ | |
| UiPersonsSidebar = function() { | |
| return { // SIDE LIST | |
| id: "sideBarWrap", | |
| gravity: 1, | |
| rows: [{ css: "text-center", view: "label", label: "Заявители:" }, { | |
| view: "toolbar", | |
| id: "visaListButtons", | |
| labelAlign: 'left', | |
| css: "float-block", | |
| cols: [ | |
| { view: "spacer" }, { | |
| view: "button", | |
| id: "addPerson", | |
| type: "icon-top", | |
| icon: "plus", | |
| tooltip: _("person_add"), | |
| css: "text-center addPersonBtn", | |
| gravity: 10, | |
| value: _("person_add"), | |
| click: function() { | |
| webix.ajax().post(getAjaxUrl('person', 'create'), { | |
| session: $$userSessionsStore.getCursor() | |
| }, ajaxCallback); | |
| } | |
| }, | |
| { view: "spacer" } | |
| ], | |
| }, { | |
| view: "list", | |
| id: "visaList", | |
| css: "float-block", | |
| editable: true, | |
| form: "visaForm", | |
| type: "perslist", | |
| select: true, | |
| autoheight: true, | |
| scroll: false | |
| }, { | |
| view: "template", | |
| id: "priceBlock", | |
| template: TplPaymentForm, | |
| data: { | |
| cost: 0 | |
| } | |
| }] | |
| }; | |
| }, | |
| /** | |
| * Шаг 2 | |
| */ | |
| UiStep2 = function() { | |
| return { | |
| id: "Step2", // STEP 2 | |
| disabled: true, | |
| gravity: 1, | |
| borderless: true, | |
| autoheight: true, | |
| css: "mt1", | |
| cols: [ | |
| UiMainForm(), | |
| { view: "resizer", id: "resize_2" }, | |
| UiPersonsSidebar() | |
| ] | |
| }; | |
| }, | |
| /** | |
| * Шаг 3 | |
| */ | |
| UiStep3 = function() { | |
| return { // STEP 3 | |
| id: "Step3", | |
| paddingY: 20, | |
| cols: [{ | |
| id: "propsAccord", | |
| view: "accordion", | |
| gravity: 3, | |
| paddingX: 18, | |
| borderless: true, | |
| multi: true, | |
| rows: [{ | |
| view: "template", | |
| template: "<div class='header-wrap step3'>" + | |
| "<h2>Шаг 3 - проверка и оплата</h2>" + | |
| "</div>", | |
| height: 94, | |
| borderless: true | |
| }, { | |
| borderless: true, | |
| header: _('session'), | |
| headerHeight: 41, | |
| headerAlt: _('session') + " (Открыть)", | |
| headerAltHeight: 41, | |
| view: "accordionitem", | |
| collapsed: false, | |
| body: { | |
| view: "property", | |
| id: "sessionProps", | |
| height: 40 * 7, | |
| editable: false, | |
| nameWidth: 300, | |
| elements: [ | |
| { type: "text", id: "id", hidden: true }, | |
| { label: _('country'), type: "text", id: "country_name" }, | |
| { label: _('email'), type: "text", id: "email" }, | |
| { label: _('phone'), type: "text", id: "phone" }, | |
| { label: _('createdon'), type: "date", id: "createdon", format: webix.i18n.parseFormatStr }, | |
| { label: _('editedon'), type: "date", id: "editedon", format: webix.i18n.parseFormatStr }, | |
| { label: _('persons_count'), type: "text", id: "persons_count" }, | |
| { label: _('url_hash'), type: "text", id: "url_hash" }, | |
| ] | |
| } | |
| }] | |
| }, { | |
| view: "template", | |
| id: "priceBlockClone", | |
| template: TplPaymentForm, | |
| data: { | |
| cost: 0 | |
| } | |
| }] | |
| }; | |
| }; | |
| /** | |
| * END VAR | |
| */ | |
| /** | |
| * Тип списка для заявителей в боковой колонке | |
| */ | |
| webix.type(webix.ui.list, { | |
| name: "perslist", | |
| icon: "fa-times", | |
| butWidth: 21, | |
| butHeight: 21, | |
| templateStart: webix.template('<div webix_l_id="#id#" class="{common.classname()}"><div class="overall">'), | |
| templateEnd: webix.template('</div>{common.removeButton()}</div>'), | |
| template: function(obj) { | |
| var idx = $$('visaList').getIndexById(obj.id); | |
| if(obj.sirname !== undefined && obj.sirname !== null && obj.sirname.length > 1) { | |
| return "<div class='title'>" + _C(obj.sirname) + _C(obj.firstname, true) + _C(obj.patronymic, true) + "</div><div class='cost'>" + webix.i18n.priceFormat(obj.price) + "</div>"; | |
| } | |
| return "<div class='small'>Заявитель №" + (idx + 1) + "</div><div class='cost'>" + webix.i18n.priceFormat(obj.price) + "</div>"; | |
| }, | |
| removeButton: webix.template( | |
| ' <div class="webix_view webix_control webix_el_button person_remove absolute" style="width: {common.butWidth}px; height: {common.butHeight}px;">' + | |
| ' <div class="webix_el_box" style="width:{common.butWidth}; height:{common.butHeight}px">' + | |
| ' <button type="button" class="webix_img_btn" style="line-height:{common.butHeight - 6}px;">' + | |
| ' <span class="webix_icon_btn {common.icon}" style="max-width:{common.butHeight - 6}px;"></span>' + | |
| ' </button>' + | |
| ' </div>' + | |
| ' </div>' | |
| ), | |
| on_click: { | |
| person_remove: function(e, id) { | |
| if (this.getVisibleCount() <= 1) { | |
| return false; | |
| } | |
| webix.confirm({ | |
| title: _('warning'), | |
| text: _('remove_person_confirm_msg'), | |
| ok: _('yes'), | |
| cancel: _('no'), | |
| type: 'confirm-warning', | |
| callback: function(ok) { | |
| if(ok) { | |
| webix.ajax().post(getAjaxUrl('person', 'remove'), { id: id }, ajaxCallback); | |
| } | |
| } | |
| }); | |
| } | |
| } | |
| }); | |
| /** | |
| * Тип списка с функцией добавления/удаления для предыдущих фамилий | |
| */ | |
| webix.type(webix.ui.list, { | |
| name: "multilist", | |
| classname: function(obj, common, marks) { | |
| var css = "webix_list_item"; | |
| if(obj.$css) { | |
| if(typeof obj.$css == "object") | |
| obj.$css = webix.html.createCss(obj.$css); | |
| css += " " + obj.$css; | |
| } | |
| if(marks && marks.$css) | |
| css += " " + marks.$css; | |
| return css; | |
| }, | |
| $css: { | |
| width: "auto", | |
| height: "34px", | |
| position: "relative", | |
| }, | |
| butWidth: 21, | |
| butHeight: 21, | |
| icon: 'fa-times', | |
| template: webix.template("#value# {common.removeButton()}"), | |
| templateStart: webix.template('<div webix_l_id="#id#" class="{common.classname()}">'), | |
| templateEnd: webix.template('</div>'), | |
| removeButton: webix.template( | |
| ' <div class="webix_view webix_control webix_el_button sirname_remove absolute" style="width: {common.butWidth}px; height: {common.butHeight}px;">' + | |
| ' <div class="webix_el_box" style="width:{common.butWidth}; height:{common.butHeight}px">' + | |
| ' <button type="button" class="webix_img_btn" style="line-height:{common.butHeight - 6}px;">' + | |
| ' <span class="webix_icon_btn {common.icon}" style="max-width:{common.butHeight - 6}px;"></span>' + | |
| ' </button>' + | |
| ' </div>' + | |
| ' </div>' | |
| ), | |
| on_click: { | |
| "sirname_remove": function(e, id) { | |
| this.editCancel(); | |
| this.remove(id); | |
| this.updateSelfStr(); | |
| } | |
| } | |
| }); | |
| /** | |
| * Прототип UI-элемента редактируемого списка | |
| */ | |
| webix.protoUI({ | |
| name: "editlist", | |
| defaults: { | |
| gravity: 1, | |
| autoheight: true, | |
| width: "auto", | |
| borderless: true, | |
| addIcon: 'fa-plus', | |
| padding: 5, | |
| type: 'multilist' | |
| }, | |
| label_setter: function(label) { | |
| if(label !== undefined && label !== '' && label) { | |
| var rootNode = this.getNode(), | |
| conf = this.config, | |
| addButton = webix.html.create('DIV', { | |
| 'class': 'webix_view webix_control webix_el_button button_add absolute', | |
| 'view_id': 'addPrevSur', | |
| 'style': 'width: ' + conf.buttWidth || 30 + 'px; height: ' + conf.buttHeight || 30 + 'px;' | |
| }), | |
| labelNode = webix.html.create('LABEL', { | |
| 'class': 'webix_inp_top_label', | |
| 'style': 'display:block;text-align:left;line-height:20px;position:relative;padding:2px 0 0 32px;' | |
| }, label); | |
| addButton.appendChild(webix.html.create('BUTTON', { | |
| 'type': 'button', | |
| 'class': 'webix_img_btn', | |
| 'style': 'line-height: 1;height: 21px;' | |
| })).appendChild(webix.html.create('SPAN', { | |
| 'class': 'webix_icon_btn ' + conf.addIcon || 'fa-plus', | |
| 'style': 'max-width:21px;' | |
| })); | |
| labelNode.appendChild(addButton); | |
| webix.html.insertBefore(labelNode, rootNode.childNodes[0]); | |
| return label; | |
| } | |
| }, | |
| $getSize: function() { | |
| return [1, 10000, 1, 10000]; | |
| }, | |
| getValues: function() { | |
| return Array.prototype.slice | |
| .call(this.getNode().childNodes[1].childNodes) | |
| .map(function(el, i, arr) { | |
| return _C(el.innerText.toLowerCase()).trim(); | |
| }); | |
| }, | |
| updateSelf: function(id) { | |
| if($$personsStore.getItem(id) === undefined) return; | |
| var $surnamesList = $$('surnamesList'), | |
| str = $$('visaForm').getDirtyValues().prev_surnames || ''; | |
| if(!str || str === '') { | |
| $$('surnamesList').clearAll(); | |
| return; | |
| } | |
| var arr = str.split(','), | |
| result = []; | |
| arr.forEach(function(surname, idx) { | |
| result.push({ id: idx + 1, value: _C(surname).trim() }); | |
| }); | |
| $$('surnamesList').clearAll(); | |
| $$('surnamesList').parse(result); | |
| }, | |
| updateSelfStr: function() { | |
| var values = this.getValues(), | |
| $strField = $$('prevSurStr'); | |
| $strField.setValue(values.join(',')); | |
| setTimeout(updatePerson, 0); | |
| }, | |
| on_click: { | |
| "button_add": function() { | |
| var id = this.count() + 1; | |
| this.add({ | |
| id: id, | |
| value: '' | |
| }); | |
| this.edit(id); | |
| } | |
| } | |
| }, webix.BaseBind, webix.EditAbility, webix.ui.list); | |
| /** | |
| * Прототип телефонного поля ввода | |
| */ | |
| webix.protoUI({ | |
| name: "phonefield", | |
| $cssName: "text webix_el_richselect", | |
| defaults: { | |
| validate: "isPhone", | |
| placeholder: "(___) ___-__-__", | |
| icon: "phone", | |
| on: { | |
| "onAfterRender": function(data) { | |
| // Инициализация плагина VanillaMask | |
| if(!VanillaMask) return; | |
| var id = this.getInputNode().id, | |
| _this = this; | |
| this.validator = this.validator || | |
| new VanillaMask(document.getElementById(String(id)), { | |
| masks: ["(999) 999-99-99"], | |
| onComplete: function() { | |
| _this.validate(); | |
| _this.attachEvent('onChange', function() { | |
| _this.validate(); | |
| }); | |
| } | |
| }); | |
| }, | |
| }, | |
| } | |
| }, webix.ui.text); | |
| /** | |
| * Прототип превью области для загрузчиков картинок | |
| */ | |
| webix.protoUI({ | |
| name: "uploaderthumb", | |
| defaults: { | |
| css: "webix_el_template", | |
| autoheight: true, | |
| borderless: true, | |
| template: function(data, self) { | |
| if(!data.url) { | |
| return '<div class="wrapper" style="display:none;"></div>'; | |
| } | |
| return '<div class="wrapper" style="position:relative;">' + | |
| '<img src="' + data.url + '" style="width:100%;"/>' + | |
| '<div class="removeFile"></div>' + | |
| '</div>'; | |
| }, | |
| data: function() { | |
| var value = $$(this.config.uploader).getValue(); | |
| return { url: value }; | |
| }, | |
| onClick: { | |
| removeFile: function() { | |
| var _this = this, | |
| uploaderId = this.config.uploader, | |
| person = this.getFormView().getValues(); | |
| webix.confirm({ | |
| title: _('file_remove'), | |
| ok: _('ok'), | |
| cancel: _('cancel'), | |
| text: _('file_remove_confirm'), | |
| callback: function(ok) { | |
| if(ok) { | |
| $$(uploaderId).setValue(''); | |
| setTimeout(updatePerson, 0); | |
| _this.define('data', { url: '' }); | |
| } | |
| } | |
| }); | |
| } | |
| } | |
| }, | |
| }, webix.ui.template); | |
| /** | |
| * Прототип поля загрузки файлов | |
| */ | |
| webix.protoUI({ | |
| name: "visaxupload", | |
| defaults: { | |
| multiple: false, | |
| accept: "image/png, image/gif, image/jpg", | |
| upload: getAjaxUrl('person', 'file/upload'), | |
| status: function(f) {}, | |
| datatype: "json", | |
| on: { | |
| "onUploadComplete": ajaxCallback, | |
| "onBeforeRender": function(data) { | |
| // data.link = data.link || data.name && data.name + '_thumb'; | |
| refreshThumbs(data.id, data); | |
| } | |
| } | |
| }, | |
| // getRelatedCheckbox: function() { | |
| // return this.getParentView() | |
| // } | |
| }, webix.ui.uploader); | |
| /************************* | |
| ***** On DOM ready ****** | |
| *************************/ | |
| webix.ready(function() { | |
| webix.i18n.setLocale("ru-RU"); | |
| webix.Date.startOnMonday = true; | |
| /** | |
| * Modx data driver JSON | |
| */ | |
| webix.DataDriver.modx = webix.extend({ | |
| getInfo: function(data) { | |
| // console.log(data); | |
| return { | |
| _size: (data.total || 0), | |
| _from: (data.pos || 0), | |
| _parent: (data.parent || 0), | |
| _config: (data.config), | |
| _key: (data.webix_security) | |
| }; | |
| } | |
| }, webix.DataDriver.json); | |
| /** | |
| * Phone validation rule | |
| * @param {[type]} t [description] | |
| * @return {Boolean} [description] | |
| */ | |
| webix.rules.isPhone = function(t) { | |
| var patt = /^\(\d{3}\) \d{3}-\d{2}-\d{2}$/; | |
| return patt.test(t.trim()); | |
| }; | |
| /** | |
| * Session storage definition | |
| * @return {void} | |
| */ | |
| $$userSessionsStore = new webix.DataCollection({ | |
| id: "$$userSessionsStore", | |
| // url: getAjaxUrl('session', 'getlist'), | |
| scheme: { | |
| //turning strings into objects on loading | |
| $init: function(obj) { | |
| // formatting dates. turning strings into objects on loading. | |
| if(obj.editedon !== undefined && obj.editedon !== null) | |
| obj.editedon = webix.i18n.parseFormatDate(obj.editedon); | |
| if(obj.createdon !== undefined && obj.createdon !== null) | |
| obj.createdon = webix.i18n.parseFormatDate(obj.createdon); | |
| // get lang keys | |
| obj._status = obj.status; | |
| obj.status = _(obj.status); | |
| }, | |
| //turing objects back to strings on saving | |
| $save: function(obj) { | |
| // return dates | |
| if(obj.editedon !== undefined && obj.editedon !== null) | |
| obj.editedon = webix.i18n.parseFormatStr(obj.editedon); | |
| if(obj.createdon !== undefined && obj.createdon !== null) | |
| obj.createdon = webix.i18n.parseFormatStr(obj.createdon); | |
| } | |
| } | |
| }); | |
| /** | |
| * Persons of one session storage definition | |
| * @return {void} | |
| */ | |
| $$personsStore = new webix.DataCollection({ | |
| id: "$$personsStore", | |
| scheme: { | |
| $init: function(obj) { | |
| obj.birth_date = obj.birth_date || visax.default_birth_date; | |
| if(obj.birth_date !== undefined && obj.birth_date !== null) | |
| obj.birth_date = webix.i18n.parseFormatDate(obj.birth_date); | |
| obj.price = calcPersonCostById(obj.id); | |
| updateAllCosts(); | |
| }, | |
| $save: function(obj) { | |
| if(obj.birth_date !== undefined && obj.birth_date !== null) | |
| obj.birth_date = webix.i18n.parseFormatStr(obj.birth_date); | |
| }, | |
| $update: function(obj) { | |
| this.serialize(); | |
| obj.price = calcPersonCostById(obj.id); | |
| updateAllCosts(); | |
| webix.ajax().post(getAjaxUrl('person', 'update'), obj, ajaxCallback); | |
| }, | |
| }, | |
| }); | |
| /** | |
| * Extending stores to send queries | |
| */ | |
| webix.extend($$userSessionsStore, webix.DataProcessor); | |
| webix.extend($$personsStore, webix.DataProcessor); | |
| /** | |
| * Main layout object | |
| * @object | |
| */ | |
| mainWrapper = webix.ui({ | |
| id: "mainWrapper", | |
| container: "ajaxWrapper", | |
| rows: [{ // TAB BAR | |
| view: "segmented", | |
| id: "tabbar", | |
| value: "Step1", | |
| multiview: true, | |
| options: [ | |
| { value: _('step_1'), id: 'Step1' }, | |
| { value: _('step_2'), id: 'Step2' }, | |
| { value: _('step_3'), id: 'Step3' } | |
| ] | |
| }, { | |
| view: "multiview", | |
| id: "visaMultiview", | |
| keepViews: true, | |
| cells: [ | |
| UiStep1(), | |
| UiStep2(), | |
| UiStep3() | |
| ] | |
| }] | |
| }); | |
| webix.extend(mainWrapper, webix.ProgressBar); | |
| if(visax.sessions.length > 0) { | |
| $$userSessionsStore.add(visax.sessions[0]); | |
| loadSession(visax.sessions[0].id); | |
| } | |
| }); | |
| /********************************************************************* | |
| ********************************************************************* | |
| * PUBLIC METHODS | |
| ********************************************************************* | |
| ********************************************************************/ | |
| webix.extend(window, { | |
| /** | |
| * Запускается со стороны бэкенда после успешного обновления заявителя | |
| */ | |
| person_updated: function(data) { | |
| var person = data.object, | |
| index = $$('visaList').getIndexById(person.id), | |
| $accordionItem = $$('personProps' + index).getParentView(), | |
| name = (!person.sirname.length) | |
| ? 'Заявитель №' + (index + 1) | |
| : _C(person.sirname) + _C(person.firstname) + _C(person.patronymic); | |
| $$('visaForm').setDirty(!data.success); | |
| $accordionItem.define('header', name); | |
| $accordionItem.define('headerAlt', name + ' (Открыть)'); | |
| $accordionItem.refresh(); | |
| }, | |
| /** | |
| * Запускается со стороны бэкенда после успешного добавления заявителя | |
| */ | |
| person_added: function(data) { | |
| if(data.success) { | |
| var count = $$personsStore.count(); | |
| $$personsStore.add(data.object); | |
| addPersonToAccordion(data.object, count); | |
| updateAllCosts(); | |
| } | |
| }, | |
| /** | |
| * Запускается со стороны бэкенда после успешного удаления заявителя | |
| */ | |
| person_removed: function(data) { | |
| if (data.success) { | |
| var person = data.object, | |
| newId = person.id, | |
| propViewName = '$accordionitem' + (getPersonIndex(id) + 2); | |
| $$('propsAccord').removeView(propViewName); | |
| $$personsStore.remove(id); | |
| id = $$personsStore.getLastId(); | |
| updateAllCosts(); | |
| } | |
| }, | |
| /** | |
| * Запускается со стороны бэкенда после успешного удаления сессии | |
| */ | |
| session_removed: function(data) { | |
| if (data.success) { | |
| $$userSessionsStore.remove(data.object.id); | |
| updateAllCosts(); | |
| } | |
| }, | |
| /** | |
| * Вызывается из бэкенда после создания новой сессии | |
| */ | |
| new_session: function(data) { | |
| var session = data.results, | |
| persons = session.persons || [], | |
| url = 'visa/' + session.url_hash, | |
| title = document.title + ' | Пользователь ' + session.email; | |
| $$userSessionsStore.add(session, session.id); | |
| $$personsStore.clearAll(); | |
| $$personsStore.parse(persons); | |
| // Кешируем id активной сессии | |
| $$userSessionsStore.setCursor(session.id); | |
| initStep2(session.id); | |
| $$('tabbar').setValue('Step2'); | |
| $$('Step2').enable(); | |
| window.history.pushState({ webix: true }, title, url); | |
| initStep3(session, persons); | |
| webix.alert({ | |
| title: _('msg.session_created_title'), | |
| ok: _('ok'), | |
| text: 'На адрес ' + session.email + ', выслано письмо со ссылкой,' + | |
| ' чтобы вы в любой момент могли вернуться к заполнению данных анкеты.<br>' + | |
| 'Также, вернуться к заполнению можно, перейдя по ссылке на эту страницу.' | |
| }); | |
| }, | |
| /** | |
| * Вызывается из бэкенда при существовании подходящих сессий | |
| * Показывает всплывающее окно со списком сессий | |
| */ | |
| show_modal: function(data) { | |
| if(typeof data == 'string') data = JSON.parse(data); | |
| var sessions = data.results, | |
| email = sessions[0].email, | |
| persons = [], | |
| formFields = $$('Step1').getValues(); | |
| // mainWrapper.hideProgress(); | |
| $$userSessionsStore.clearAll(); | |
| $$userSessionsStore.parse(sessions); | |
| webix.ui({ | |
| view: "window", | |
| id: "sessions_list", | |
| move: true, | |
| resize: true, | |
| position: "center", | |
| height: 450, | |
| head: { | |
| view: "toolbar", | |
| cols: [ | |
| { view: "label", label: _('sess_list') + " " + email, gravity: 5 }, | |
| { view: "button", label: _('close'), align: "right", gravity: 1, click: "$$('sessions_list').close();" } | |
| ] | |
| }, | |
| body: { | |
| rows: [{ | |
| view: "treetable", | |
| id: "sessionsTable", | |
| select: "row", | |
| autowidth: true, | |
| scheme: { | |
| $init: function(obj) { | |
| obj.data = obj.persons; | |
| for(var key in obj.data) { | |
| if(obj.data.hasOwnProperty(key)) { | |
| obj.data[key].id = obj.id + '.' + obj.data[key].id; | |
| obj.data[key].session = obj.id; | |
| } | |
| } | |
| }, | |
| }, | |
| columns: [ | |
| { id: "id", header: _('id'), adjust: "data", fillspace: true, template: "<span class='text-right'>#id#</span>" }, | |
| { id: "country_name", header: _('country_name'), fillspace: true }, | |
| { id: "persons_count", header: _('persons_count'), adjust: "header" }, | |
| { id: "createdon", header: _('createdon'), format: webix.i18n.longDateFormatStr, adjust: "header" }, | |
| { id: "editedon", header: _('editedon'), format: webix.i18n.longDateFormatStr, adjust: "header" }, | |
| { id: "state", header: _('state'), adjust: "data", fillspace: true }, { | |
| id: "edit", | |
| header: _('actions'), | |
| adjust: "data", | |
| template: function(obj, common) { | |
| return '<span class="editBtn" title="' + | |
| _('return_filling') + '"><i class="fa fa-edit"></i></span>' + | |
| '<span class="delBtn" title="' + | |
| _('show_persons') + '"><i class="fa fa-times"></i></span>'; | |
| } | |
| } | |
| ], | |
| data: $$userSessionsStore, | |
| onClick:{ | |
| 'editBtn': function(e, id, trg) { | |
| webix.confirm({ | |
| title: _('email_repeat'), | |
| ok: _('ok'), | |
| cancel: _('cancel'), | |
| text: _('email_repeat_confirm'), | |
| callback: function(success) { | |
| if(success) { | |
| var data = { sessionId: id.row, email: email }; | |
| mainWrapper.showProgress({ type: "icon", delay: 3000 }); | |
| webix.ajax().post(getAjaxUrl('session', 'sendmail'), data, ajaxCallback); | |
| } | |
| } | |
| }); | |
| return false; | |
| }, | |
| 'delBtn': function(e, id, trg) { | |
| webix.confirm({ | |
| title: _('session_remove'), | |
| ok: _('ok'), | |
| cancel: _('cancel'), | |
| text: _('session_remove_confirm'), | |
| callback: function(success) { | |
| if(success) { | |
| var data = { id: id.row }; | |
| mainWrapper.showProgress({ type: "icon", delay: 3000 }); | |
| webix.ajax().post(getAjaxUrl('session', 'remove'), data, ajaxCallback); | |
| } | |
| } | |
| }); | |
| return false; | |
| } | |
| } | |
| }, { | |
| cols: [{}, { | |
| view: "button", | |
| gravity: 2, | |
| value: _('new_sess_start'), | |
| type: "form", | |
| click: function() { | |
| formFields.step = 'force'; | |
| mainWrapper.showProgress({ type: "icon", delay: 3000 }); | |
| webix.ajax().post(getAjaxUrl('session', 'create'), formFields, ajaxCallback); | |
| } | |
| }, {}] | |
| }] | |
| } | |
| }).show(); | |
| }, | |
| /** | |
| * Срабатывает после успешной отправки email | |
| * @param {Obj} data [description] | |
| * @return {[type]} [description] | |
| */ | |
| email_ok: function(data) { | |
| var b = $$('emailRepeatButt'); | |
| if(b !== undefined) { | |
| b.destructor(); | |
| } | |
| webix.message({ | |
| text: _('email_ok'), | |
| expire: 5000 | |
| }); | |
| }, | |
| email_fail: function(data) { | |
| webix.message({ | |
| type: "error", | |
| text: _('email_fail'), | |
| expire: 5000 | |
| }); | |
| }, | |
| passportscans_file_uploaded: function(data) { | |
| refreshThumbs('uploadPassportAPI', data.object); | |
| }, | |
| visascans_file_uploaded: function(data) { | |
| refreshThumbs('uploadVizaAPI', data.object); | |
| } | |
| }); | |
| })(document, window, webix, visax); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment