var EXPO = EXPO || {}; //isolated namespace //общий для всех страниц модуль Функционал общий для всех страниц // module requires JQuery library // protection against duplication of a module code if (EXPO.company){ console.warn('WARNING: EXPO.company is already defined!'); }else{ EXPO.company = (function() { // variables var that = {}; that.opt = { updateFormClass:'update-profile-form' }; //default module setting that.lang ={}; //dependences var $waiter, com = EXPO.common; //private /** * Rating functional. Object stores data, HTML Instance of rating field, and can refresh its value * @param {Object} opt - options for rating instance, like HTML Id and other * @constructor */ function Rating(opt){ this.opt = opt; this.$inst = $('#'+opt.id); this.value = this.$inst.text; } Rating.prototype = { /** * refreshes value of HTML instance with new. * @param {number} newRating - new profile rating value */ refresh: function (newRating) { this.value = newRating; this.$inst.text(this.value); } }; // factory for on page form objects function Forms(){} // methods to perform ajax responses to send and receive data from the server Forms.prototype = { // ajax request realization submit: function (dataToSend) { var self = this; if(!dataToSend){ dataToSend = new FormData(this.$form[0]); } $.ajax({ type: 'POST', url: self.ajaxPath, data:dataToSend, processData: false, contentType: false, success: function(data) { self.afterSubmit(data); if(data.success){ EXPO.company.rating.refresh(data.rating); } $('#wait-ajax').fadeOut(); } }); }, // check if there exists custom data manipulation handler and evaluate it beforeSubmit: function (data, formName) { var handler = this.beforeSubmitHandler, formData = data; if(typeof formData != "string"){ this.formData =formData; }else{ this.formData = JSON.parse('{"' + decodeURI(formData).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}'); } this.formId = formName; if(typeof handler == 'function'){ // if particular data change required this.formData = handler(data, formName); this.submit(data); $('#wait-ajax').show(); } else{ this.submit(data); $('#wait-ajax').show(); } }, afterSubmit: function (data) { var handler = this.afterSubmitHandler; if(typeof handler == 'function'){ handler(data); } else{ throw{ name: 'Error', message: " handler function for processing response after form submit not defined, please define it!" }; } }, /** * refreshes form state: if value was entered by user, then there will be label with rhis value * or there will be prompt to enter value * @function * @public */ refreshHTML: function () { var pureText = $.trim( this.$staticValue.text()).replace(/[^0-9a-zA-Zа-я\s]/g,'').replace( /(\d)\s/, '' ).replace(/\s+/g,''); if(($.trim( this.$staticValue.text()) == '' || pureText == 'NoneNone') && this.$wrapper.length && this.refrashable){ this.$editable.addClass('hidden'); this.$editable.removeClass(EXPO.company.opt.formCurrentClass); this.$description.removeClass('hidden'); }else if(this.$wrapper.length && this.refrashable){ this.$editable.removeClass('hidden'); this.$description.addClass('hidden'); } } }; /** * factory object directly * @param {String} type - type of fabricated object * @param {String} ajaxpath - attribute action from each form html element */ Forms.factory = function (type, ajaxpath) { var constr = type, newForm; if (typeof Forms[constr] !== 'function'){ throw{ name: 'Error', message: constr + "doesen't exist" }; } if(typeof Forms[constr].prototype.beforeSubmit !== "function"){ Forms[constr].prototype = new Forms(); } newForm = new Forms[constr](ajaxpath); return newForm; }; /** * set of child objects that will override the factory default */ Forms.name_form = function (path) { var self = this; this.afterSubmitHandler = function (data) { if (data.success){ $('#static-name-value').text($('#id_name').val()); $('.p-editable').removeClass('pe-current'); self.refreshHTML(); }else{ this.$editable.addClass('err'); } }; this.ajaxPath = path; }; Forms.spec_form = function (path) { var self = this; this.afterSubmitHandler = function (data) { if (data.success){ $('#static-spec-value').html(com.nl2br($('#id_specialization').val())); $('.p-editable').removeClass('pe-current'); self.refreshHTML(); }else{ this.$editable.addClass('err'); } }; this.ajaxPath = path; }; Forms.address_form = function (path) { var self = this; this.afterSubmitHandler = function (data) { if (data.success){ $('#static-address-value').text($('#id_address_inf').val()); $('.p-editable').removeClass('pe-current'); self.refreshHTML(); }else{ this.$editable.addClass('err'); } }; this.ajaxPath = path; }; Forms.social_form = function (path) { var self = this, $img, imgSrc, $input, inputValue,item; this.afterSubmitHandler = function (data) { if (data.success){ for (item in self.formData) { $input = $('#id_'+item); $input.parent('.required').removeClass('err'); if($.trim(self.formData[item]) != '' && $input.length){ $img = $('#img-'+item); if($img.length){ inputValue = $.trim($input.val()); if ($img.parent('a').length){ $img.parent('a').attr('href',inputValue); imgSrc = $img.attr('src').replace('_hover',''); $img.attr('src',imgSrc); }else { imgSrc = $img.attr('src').replace('_hover',''); $img.attr('src',imgSrc); $img.wrap(''); } } }else if($input.length){ $img = $('#img-'+item); if ($img.parent('a').length){ imgSrc = $img.attr('src').replace('.png','_hover.png'); $img.attr('src',imgSrc); $img.unwrap(); } } } $('.p-editable').removeClass('pe-current'); }else { for (item in data.errors) { $input = $('#id_' + item); $input.parent('.required').addClass('err'); $input.blur(function () { $input.parent('.required').removeClass('err'); self.$form.submit(); }); } } self.refreshHTML(); }; this.beforeSubmitHandler = function (data, formName){ var formData = $('#'+formName).serialize(); return JSON.parse('{"' + decodeURI(formData).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}'); }; this.refreshHTML = function () { console.log(this); var fullComplete = true; $('input:text',this.$form).each(function () { if($.trim($(this).val()) == ''){ fullComplete = false; } }); if(fullComplete){ $('.full-complete',this.$description).removeClass('hidden'); $('.not-complete',this.$description).addClass('hidden'); }else{ $('.full-complete',this.$description).addClass('hidden'); $('.not-complete',this.$description).removeClass('hidden'); } }; this.ajaxPath = path; }; Forms.phone_form = function (path) { var self = this; this.afterSubmitHandler = function (data) { if (data.success){ $('#static-phone-value').text($('#id_phone')[0].value); $('.p-editable').removeClass('pe-current'); self.refreshHTML(); } }; this.ajaxPath = path; }; Forms.email_form = function (path) { var mailValue; var self = this; this.afterSubmitHandler = function (data) { if (data.success){ mailValue = $('#id_email').val(); $('#static-email-value').attr('href', 'mailto:'+mailValue).text(mailValue); $('.p-editable').removeClass('pe-current'); self.refreshHTML(); }else{ this.$editable.addClass('err'); } }; this.ajaxPath = path; }; Forms.web_page_form = function (path) { var userLink; var self = this; this.afterSubmitHandler = function (data) { if (data.success){ userLink = $('#id_web_page').val(); $('#static-web-page-value').attr('href',userLink).text(userLink); $('.p-editable').removeClass('pe-current'); self.refreshHTML(); } }; this.ajaxPath = path; }; Forms.home_form = function (path) { var self = this; this.afterSubmitHandler = function (data) { if (data.success){ var country = $('#s2id_id_country').find('.select2-chosen').text(), city = $('#s2id_id_city').find('.select2-chosen').text(); $('#static-home-country').text(country); $('#static-home-city').text(city); $('.p-editable').removeClass('pe-current'); self.refreshHTML(); } }; this.ajaxPath = path; }; Forms.found_form = function (path) { var currValue, $input; var self = this; this.afterSubmitHandler = function (data) { if (data.success){ var $fullComplete = $('.full-complete',this.$staticValue); $input = $('#id_foundation'); currValue = $.trim($input.val()); $fullComplete.text(currValue); $('.p-editable').removeClass('pe-current'); self.refreshHTML(); } }; this.ajaxPath = path; this.refreshHTML = function () { var $fullComplete = $('.full-complete',this.$staticValue), $notComplete = $('.not-complete',this.$staticValue); if($.trim($fullComplete.text()) == ''){ $fullComplete.addClass('hidden'); $notComplete.removeClass('hidden'); }else{ $fullComplete.removeClass('hidden'); $notComplete.addClass('hidden'); } return false; } }; Forms.staff_form = function (path) { var currValue, $input; var self = this; this.afterSubmitHandler = function (data) { if (data.success){ var $fullComplete = $('.full-complete',this.$staticValue); $input = $('#id_staff_number'); currValue = $.trim($input.val()); $fullComplete.text(currValue); $('.p-editable').removeClass('pe-current'); self.refreshHTML(); } }; this.ajaxPath = path; this.refreshHTML = function () { var $fullComplete = $('.full-complete',this.$staticValue), $notComplete = $('.not-complete',this.$staticValue); if($.trim($fullComplete.text()) == ''){ $fullComplete.addClass('hidden'); $notComplete.removeClass('hidden'); }else{ $fullComplete.removeClass('hidden'); $notComplete.addClass('hidden'); } return false; } }; Forms.description_form = function (path) { var currValue, $input = $('#id_description'); var self = this; this.afterSubmitHandler = function (data) { if (data.success){ var $fullComplete = $('.full-complete',this.$staticValue); currValue = $.trim($input.val()); $fullComplete.html(com.nl2br(currValue)); $('.p-editable').removeClass('pe-current'); self.refreshHTML(); } }; this.ajaxPath = path; this.refreshHTML = function () { var $fullComplete = $('.full-complete',this.$staticValue), $notComplete = $('.not-complete',this.$staticValue); if($.trim($fullComplete.text()) == ''){ $fullComplete.addClass('hidden'); $notComplete.removeClass('hidden'); }else{ $fullComplete.removeClass('hidden'); $notComplete.addClass('hidden'); } return false; } }; Forms.avatar_form = function (path) { var self = this, $input = $('#id_avatar'), $editPhoto = $('#pic-edit-photo'), $pickBlock = $('#pick-block'), $form, $avatar = $('img',$pickBlock); /** * callback after successful request to the server * @param data -data object recieved from server */ this.afterSubmitHandler = function (data) { if (data.success){ if($avatar.length){ $avatar.attr('src', data.url); self.refreshHTML(); } } }; this.beforeSubmitHandsler = function(data){ if(typeof data != 'string'){ self.submit(data); $('#wait-ajax').show(); }else{ $form = $('#'+self.formId); $form.off('submit'); $form.trigger('submit'); } }; $input.on('change', function () { $(this).parents('form').submit(); }); this.ajaxPath = path; this.refreshHTML = function () { if($.trim(this.$image.attr('src')) == this.noImageSrc){ this.$editable.addClass('hidden'); this.$description.removeClass('hidden'); }else{ this.$editable.removeClass('hidden'); this.$description.addClass('hidden'); } } }; Forms.tag_form = function (path) { var self = this; /** * callback after successful request to the server * @param data -data object recieved from server */ this.afterSubmitHandler = function (data) { var divider =', '; if (data.success){ this.$staticValue.html(''); for(var i=0; i < data.tags.length; i++){ this.$staticValue.append($(""+data.tags[i].text+"")); if(i != data.tags.length-1) { this.$staticValue.append($(divider)); } } self.refreshHTML(); } }; this.ajaxPath = path; this.$input = $('#id_tag'); this.refreshHTML = function () { this.$label = $('.label', this.$editable); this.$initial = $(".initial-position",this.$wrapper); this.formId = this.$form.attr("id"); if( $.trim(this.$input.val()) == ''){ //this.$form.detach().appendTo(this.$initial); //this.$label.detach().appendTo(this.$initial); this.$form.detach().appendTo(this.$editable); this.$label.detach().appendTo(this.$editable); this.$initial.removeClass("hidden"); this.$description.addClass("hidden"); }else{ if($('#'+this.formId, this.$editable).length < 0){ this.$form.detach().appendTo(this.$editable); this.$label.detach().appendTo(this.$editable); } this.$editable.addClass("hidden"); this.$initial.addClass("hidden"); this.$description.removeClass("hidden"); } } }; var Map = function (opt) { this.opt = opt; var self = this, canvasId = this.opt.canvasId, initGooglemap = function () { var mapHolder = document.getElementById(self.opt.canvasId), input = document.getElementById(self.opt.autocompleteId); self.mapOptions = { /** * default zoom for country */ zoom: self.opt.zoom.country }; self.map = new google.maps.Map(mapHolder, self.mapOptions); /** * address to cordinates converter * @type {google.maps.Geocoder} */ self.geocoder = new google.maps.Geocoder(); /** * refresh map with new data */ self.refresh(); /** * autocomplete for adress bar input * @type {HTMLElement} */ var autocomplete = new google.maps.places.Autocomplete(input); autocomplete.bindTo('bounds', self.map); /** * autocomplete item selected event */ google.maps.event.addListener(autocomplete, 'place_changed', function() { if(!self.status.visible){ var place = autocomplete.getPlace(); if (!place.geometry) { return; } /** * If the place has a geometry, then present it on a map. */ if (place.geometry.viewport) { self.map.fitBounds(place.geometry.viewport); } else { self.map.setCenter(place.geometry.location); self.map.setZoom(14); } self.marker.setPosition(place.geometry.location); EXPO.company.forms.address_form.submit(); } }); }; /** * initialize map when body loads */ google.maps.event.addDomListener(window, 'load', initGooglemap); /** * container with map itself and address static text * @type {*|jQuery|HTMLElement} */ this.$wrapper= $(document.getElementById(this.opt.blockId)); /** * show and hide map button * @type {*|jQuery|HTMLElement} */ this.$toggle = $(".map-toggle",this.$wrapper); /** * container with map to hide and show * @type {*|jQuery|HTMLElement} */ this.$container = $(".map-wrap", this.$wrapper); this.status ={ /** * when container with map is hidden pararmeter visible = false */ visible:false }; this.$toggle.on("click", function () { if($(this).hasClass("active")){ self.hideMap(); }else{ self.showMap(); /** * just refresh the map drawing */ google.maps.event.trigger(self.map, 'resize'); self.refresh(); } return false; }); }; /** * methods * @type {{showMap: Function, hideMap: Function, refresh: Function}} */ Map.prototype = { /** * just show map container html tag */ showMap: function () { this.$toggle.addClass("active").children(".label").text(this.$toggle.attr("data-hide-text")); this.status.visible = true; this.$container.removeClass("hidden"); }, /** * just hide map container html tag */ hideMap: function () { this.$toggle.removeClass("active").children(".label").text(this.$toggle.attr("data-show-text")); this.status.visible = false; this.$container.addClass("hidden"); }, /** * collects dependent data and force map to refresh with that new data */ refresh: function () { var self = this, country =$("#id_country option:selected").text(), city = $(document.getElementById("id_city")).attr("data-init-text"), address = $.trim(document.getElementById(self.opt.autocompleteId).value), fullAddress; if( $.trim(country) != ''){ this.status.visible = true; this.$toggle.removeClass("hidden"); if($.trim(city) == ''){ fullAddress = country; self.map.set("zoom",self.opt.zoom.country); }else{ if($.trim(address) == ''){ fullAddress = country + ' '+city; self.map.set("zoom",self.opt.zoom.city); }else{ fullAddress = country + ' '+city+ ' '+ address; self.map.set("zoom",self.opt.zoom.street); } } /** * convert text adress data to lat/Ling coordinates with help of google api */ this.geocoder.geocode({"address":fullAddress}, function (results, status) { if (status == google.maps.GeocoderStatus.OK){ self.map.setCenter(results[0].geometry.location); /** * refresh marker position */ if(!self.marker){ self.marker = new google.maps.Marker({ map: self.map, position: results[0].geometry.location }); }else{ self.marker.set("position",results[0].geometry.location); } }else{ console.log("!ERORR: Geocode was not successful for the following reason: " + status); } }); }else{ this.$toggle.addClass("hidden") this.status.visible = false; } } }; // module methods //инициализация общих свойств that.init = function(options) { $.extend(this.lang, options.lang); options.lang = null; $.extend(this.opt, options); var self = this, initMaskedInput = function (inputId) { var maskList = $.masksSort($.masksLoad("/static/client/js/plugins/inputmask/phone-codes.json"), ['#'], /[0-9]|#/, "mask"), maskOpts = { inputmask: { definitions: { '#': { validator: "[0-9]", cardinality: 1 } }, showMaskOnHover: false, insertMode:false, autoUnmask: true }, match: /[0-9]/, insertMode:false, replace: '#', list: maskList, listKey: "mask", onMaskChange: function() { $(this).attr("placeholder", '+_(___)___-__-__'); } }, selector = '#'+inputId; $(selector).inputmasks(maskOpts); }; this.rating = new Rating(this.opt.rating); this.forms = {}; $(function () { var $editables = $('.'+self.opt.editableClass), $country = $('#'+self.opt.selectBox[0].id), $city = $('#'+self.opt.selectBox[1].id), $theme = $('#'+self.opt.selectBox[3].id), $address = $("#id_address_inf"); //start of document.ready $waiter = $('#wait-ajax').css({'z-index': '8012'}); /** * google map */ self.map = new Map(self.opt.map); /** * styling with 3-rd party libs */ /** * company theme multiple select */ $theme.select2({ width: 'element', placeholder: self.opt.selectBox[3].placeHolder, maximumSelectionSize: 3 }); $theme.on("change", function () { var $theme = $('#theme_form'), url = $theme.attr("action"), //toSendObj = new FormData(toSendObj); toSendObj = $theme.serialize(); com.postRequest(toSendObj,url); }); /** * select country */ $country.select2({ width: 'element', placeholder:self.opt.selectBox[0].placeholder }); $country.on("change", function () { $city.val(0); $city.select2("val", ""); }); $city.on("change", function () { var chosen = $(this).closest(".epf-field").find(".select2-chosen").text(); $(this).attr("data-init-text",chosen); self.forms.address_form.$form.find("input:text").val(""); self.forms.address_form.$staticValue.text(""); self.forms.address_form.refreshHTML(); self.forms.home_form.submit(); self.forms.address_form.submit(); //$("#id_address_inf").val('').closest(".address-wrap").find(".static-value").text(' '); self.map.refresh(); }); /** * enable city if country is not chosen */ if($country.val() == 0 || $country.val() == ''){ $city.prop('disabled', true); } $city.select2({ placeholder: self.opt.selectBox[1].placeHolder, width: 'element', ajax: { url: self.opt.selectBox[1].path, dataType: "json", quietMillis: 200, data: function(term, page, country){ var country = $('#'+self.opt.selectBox[0].id).val(); return {term: term, page: page, country: country}; }, results: function (data) { var results = []; $.each(data, function(index, item){ results.push({ id: item.id, text: item.label }); }); return {results: results}; } }, initSelection : function(element, callback) { var id= $.trim($(element).val()); var text = $(element).attr('data-init-text'); callback({id: id, text:text}); } }); /** * tags */ $('#'+self.opt.selectBox[2].id).val('0'); $('#'+self.opt.selectBox[2].id).select2({ placeholder: self.opt.selectBox[2].placeholder, width: '368px', multiple: true, maximumSelectionSize: 5, ajax: { url: self.opt.selectBox[2].path, dataType: "json", quietMillis: 200, data: function(term, page, country){ var themes = $('#theme-inf').attr('data-theme'); themes = themes.split(','); themes.pop(); return {term: term, page: page, themes: themes}; }, results: function (data) { var results = []; $.each(data, function(index, item){ results.push({ id: item.id, text: item.label }); }); return {results: results}; } }, initSelection : function(element, callback) { var data = [], dataObjArr; element.val(''); if($.trim(element.attr('data-predifined')) != '' && $.trim(element.attr('data-predifined')) != '[]'){ dataObjArr = JSON.parse(element.attr('data-predifined')); callback(dataObjArr); }else{ $('#tag_form .select2-input').width(336).addClass('select2-default').val(self.opt.selectBox[2].placeholder); } } }); $('#'+self.opt.selectBox[2].id).on('change', function (e) { var $form = $('#tag_form'); $form.submit(); }); // make mask on phone field input initMaskedInput(self.opt.phoneBox); //forms init $('.'+self.opt.updateFormClass).each(function () { var formName = $(this).attr('id'), path = $(this).attr('action'), inputData, $wrapper = $(this).closest('.'+self.opt.formWrapperClass), $staticValue = $('.'+self.opt.staticValueClass, $wrapper), $description = $('.'+self.opt.descriptionClass, $wrapper), $editable = $('.'+self.opt.editableClass, $wrapper), $closeButton = $('.'+self.opt.closeButtonClass, $wrapper), $image = $('.'+self.opt.avatarImageClass, $wrapper); //make and initialize form objects self.forms[formName] = Forms.factory(formName,path); if($('.'+self.opt.editButtonClass, $wrapper).hasClass('no-refresh')){ self.forms[formName].refrashable = false; }else{ self.forms[formName].refrashable = true; } self.forms[formName].$form = $(this); self.forms[formName].$wrapper = $wrapper; self.forms[formName].$staticValue = $staticValue; self.forms[formName].$description = $description; self.forms[formName].$editable = $editable; /** * Send proper information if there is image. mainly for avatar editing */ if($image.length){ self.forms[formName].$image = $image; self.forms[formName].noImageSrc = self.opt.noImageSrc; } // submit events handler $(this).off('submit'); $(this).on('submit', function () { //check if formData is supported $waiter.show(); if ( window.FormData && ("upload" in ($.ajaxSettings.xhr())) ){ inputData = new FormData(this); self.forms[formName].beforeSubmit(inputData, formName); } else { inputData = $(this).serialize(); self.forms[formName].beforeSubmit(inputData, formName); } return false; }); $closeButton.on('click', function() { $editable.removeClass(self.opt.formCurrentClass); self.forms[formName].refreshHTML(); return false; }); if($('.'+self.opt.avatarButtonClass, $wrapper).length){ /** * avatar image choose button */ $('.'+self.opt.editButtonClass+','+' .'+self.opt.avatarButtonClass, $wrapper).on('click', function () { var $input = $('#'+self.opt.avatarInputId); $input.trigger('click'); return false; }); }else{ /** * edit button */ $('.'+self.opt.editButtonClass+', .'+self.opt.avatarButtonClass, $wrapper).on('click', function () { //close other active editable forms var $wrapper = $(this).closest('.'+self.opt.formWrapperClass), formId = $wrapper.find('.'+self.opt.updateFormClass).attr('id'), $description = $wrapper.find('.'+self.opt.descriptionClass), $editable = $wrapper.find('.'+self.opt.editableClass); $editables.each(function () { var $wrapper = $(this).closest('.'+self.opt.formWrapperClass), formId = $wrapper.find('.'+self.opt.updateFormClass).attr('id'), $description = $wrapper.find('.'+self.opt.descriptionClass), $editable = $wrapper.find('.'+self.opt.editableClass); if($(this).hasClass(self.opt.formCurrentClass)){ if(self.forms[formId].refrashable){ self.forms[formId].refreshHTML(); $editable.removeClass(EXPO.company.opt.formCurrentClass); }else{ $editable.removeClass(self.opt.formCurrentClass); } } }); if(self.forms[formId].refrashable){ $editable.removeClass('hidden'); $description.addClass('hidden'); }else{ } $editable.addClass(self.opt.formCurrentClass); $(document).on('click.form', function(event) { var targetObj = $(event.target); if (targetObj.parents().filter('.e-form').length < 1) { $editable.removeClass(self.opt.formCurrentClass); self.forms[formName].refreshHTML(); $(document).off('click.form'); } }); return false; }); } }); /** * preview button */ $('#'+self.opt.previewBtnId).attr('href',window.location.href+"?logout=1"); }); }; return that; }()); }