1/// <reference path="../../../../../.docs/jsdoc/index.d.ts" /> 2 3Object.size = function(obj){ var size = 0, key; for (key in obj) {if (obj.hasOwnProperty(key)) size++;}return size;}; 4 5const ACTION_SUBMIT_TYPE_ADD_RETURN_SECTION = 101; 6const ACTION_SUBMIT_TYPE_ADD_REPEAT = 102; 7const ACTION_SUBMIT_TYPE_ADD_SAME = 103; 8const ACTION_SUBMIT_TYPE_ADD_THEN_EDIT = 104; 9const ACTION_SUBMIT_TYPE_EDIT_APPLY = 201; 10const ACTION_SUBMIT_TYPE_EDIT_NEXT = 202; 11const ACTION_SUBMIT_TYPE_EDIT_RETURN_SECTION = 203; 12 13const _COMMON_LANGS = { 14 'ru' : {"fileFailure" : "ÐÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ ÑказаÑÑ Ñайл","connectionError" : "ÐзвиниÑе, пÑоизоÑла оÑибка пÑи Ñоединении Ñ ÑиÑÑемой","unexpectedError" : "ÐзвиниÑе, пÑоизоÑла Ð½ÐµÐ¾Ð¶Ð¸Ð´Ð°Ð½Ð½Ð°Ñ Ð¾Ñибка. ÐбÑаÑиÑеÑÑ Ðº ÑазÑабоÑÑикам","emptyAnswerError" : "СеÑÐ²ÐµÑ Ð²ÐµÑнÑл пÑÑÑой оÑвеÑ. ÐбÑаÑиÑеÑÑ Ðº ÑазÑабоÑÑикам","requestErno" : "ÐзвиниÑе, пÑоизоÑла оÑибка. Ðод : %CODE","requestError" : "ÐзвиниÑе, пÑоизоÑла оÑибка!","submit" : "ÐÑпÑавиÑÑ","cancel" : "ÐÑмениÑÑ","search" : "ÐоиÑк","back" : "ÐеÑнÑÑÑÑÑ","prev" : "пÑед.","next" : "Ñлед.","ok" : "OK","yes" : "Ðа","no" : "ÐеÑ","loading" : "ÐдÑÑ Ð¾Ð±Ð¼ÐµÐ½ даннÑми Ñ ÑеÑвеÑом. ÐодождиÑе..","update" : "ÐбновиÑÑ","update_and_close" : "ÐбновиÑÑ Ð¸ закÑÑÑÑ","record_editor_title" : "РедакÑÐ¾Ñ Ð·Ð°Ð¿Ð¸Ñи обÑекÑа %OBJECT_ID% запиÑи â%RECORD_ID%","submit" : "ÐÑпÑавиÑÑ","error" : "ÐÑибка","error_query" : "ÐÑибка запÑоÑа","close" : "ÐакÑÑÑÑ","need_confirm" : "ÐÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ подÑвеÑждение","no_default_action_warning" : "Ðнимание, дейÑÑвие не назнаÑено! ÐбÑаÑиÑеÑÑ Ðº ÑазÑабоÑÑикам!","error_happened" : 'ÐзвиниÑе, пÑоизоÑла непÑÐµÐ´Ð²Ð¸Ð´ÐµÐ½Ð½Ð°Ñ Ð¾Ñибка!',"EMr" : 'ÐзвиниÑе, пÑоизоÑла оÑибка c оÑпÑавкой запÑоÑа!',"EMn" : 'ÐзвиниÑе, пÑоизоÑла оÑибка. (Ðод оÑибки : ',"EM" : 'ÐзвиниÑе, пÑоизоÑла оÑибка.','sending' : "ÐдÑÑ Ð¾ÑпÑавка запÑоÑа...",'response_error' : "ÐÑибка оÑвеÑа ÑеÑвеÑа",'select' : 'ÐÑбÑаÑÑ','confirm' : "ÐодÑвеÑдиÑе дейÑÑвие",'confirm_remove' : "УдалиÑÑ Ð·Ð°Ð¿Ð¸ÑÑ N=%RECORD_ID%?",'clipboard_success': 'СкопиÑовано в бÑÑеÑ','clipboard_failed': 'Ðе ÑдалоÑÑ ÑкопиÑоваÑÑ'}, 15 'en' : {"fileFailure" : "File not selected","connectionError" : "Sorry. Connection error","unexpectedError" : "Sorry. Unexpected error","emptyAnswerError" : "Sorry. Error. Answer from server is empty","requestErno" : "Sorry. Error happened. Code : %CODE","requestError" : "Sorry. Error happened!","submit" : "Submit","cancel" : "Cancel","search" : "Search","back" : "Go back","prev" : "prev.","next" : "next.","ok" : "OK","yes" : "Yes","no" : "No","loading" : "Transferring data with server.. Please, wait","update" : "Refresh","update_and_close" : "Update & close","record_editor_title" : "Record`s editor for object %OBJECT_ID% of record â%RECORD_ID%","error" : "Error","error_query" : "Error in query","close" : "Close","need_confirm" : "Confirmation needed","no_default_action_warning" : "Warning! Action isn`t assigned!","error_happened" : 'Sorry. We have an unexpected error!',"EMr" : 'Sorry. We have an error with request!',"EMn" : 'Sorrt. We have an error.(Code : ',"EM" : 'Sorry. We have an error.','sending' : "Sending request to server...",'response_error' : "Response error",'select' : 'Select','confirm' : "Confirm action",'confirm_remove' : "Are you sure to delete record N=%RECORD_ID%?",'clipboard_success': 'Copied to clipboard','clipboard_failed': 'Failed to copy to clipboard'} 16} 17 18 19// JDOM debug mode: set to 1 to throw exceptions on warnings/errors (for development) 20const DEBUG_JDOM = 1; 21
22// A small normalization layer that converts any DOM-related input (selectors, IDs, Elements, arrays, jQuery objects) into native Element or Element[] 23class JDOM { 24 static generate_new_unique_dom_id(dom_element){let el=null;if(dom_element instanceof Element)el=dom_element;else if(dom_element&&typeof dom_element==="object"&&dom_element.jquery){if(dom_element.length===1)el=dom_element[0];else return false;}else if(dom_element!==undefined){console.warn("Expected DOM element or jQuery object");return false;}if(el&&el.id)return el.id;const A="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";let t=25,id="";while(t--){id="generated_id_";for(let i=0;i<20;i++)id+=A[Math.floor(Math.random()*A.length)];if(!document.getElementById(id))break;id="";}if(!id)return false;if(el)el.id=id;return id;} 25 static get_dom_element(something,if_multiple_get_first_or_root_element=true){if(!something)return false;if(something instanceof Element)return something;if(typeof something==="string"){if(if_multiple_get_first_or_root_element instanceof Element||if_multiple_get_first_or_root_element instanceof NodeList||if_multiple_get_first_or_root_element instanceof HTMLCollection||(typeof if_multiple_get_first_or_root_element==="object"&&if_multiple_get_first_or_root_element.jquery))return this.find_dom_element(something,if_multiple_get_first_or_root_element);if(/^[A-Za-z_]/.test(something)){const e=document.getElementById(something);if(e)return e}const l=document.querySelectorAll(something);return l.length===1?l[0]:l.length>1?(if_multiple_get_first_or_root_element?l[0]:false):false}if(typeof something==="object"&&something.jquery)return something.length===1?something[0]:something.length>1?(if_multiple_get_first_or_root_element?something[0]:false):false;if(typeof something==="object"&&typeof something.length==="number")return something.length===1&&something[0] instanceof Element?something[0]:something.length>1&&something[0] instanceof Element?(if_multiple_get_first_or_root_element?something[0]:false):false;return false;} 26 static get_dom_array_elements(something){if(!something)return[];if(typeof something==="string")return Array.from(document.querySelectorAll(something));if(typeof something==="object"&&something.jquery)return something.length?Array.from(something):[];if(something instanceof Element)return[something];if(something instanceof NodeList||something instanceof HTMLCollection)return something.length?Array.from(something):[];if(Array.isArray(something))return something.every(el=>el instanceof Element)?something:(console.warn("get_dom_array_elements: array contains non-Element items"),DEBUG_JDOM?[]:[]);console.warn("get_dom_array_elements: invalid input type");if(DEBUG_JDOM)throw new Error("get_dom_array_elements: invalid input type (got: "+(typeof something)+")");return[];} 27 static multiQuery(selector,dom_root){if(!selector)return[];if(dom_root instanceof Element)return Array.from(dom_root.querySelectorAll(selector));if(!dom_root)return Array.from(document.querySelectorAll(selector));const roots=this.get_dom_array_elements(dom_root),out=[];for(const r of roots)out.push(...r.querySelectorAll(selector));return Array.from(new Set(out));} 28 static get_id(something, if_multiple_get_first = false, allow_add_id = true) { const e = el => el ? (el.id || (allow_add_id ? JDOM.generate_new_unique_dom_id(el) : false)) : false; if (something instanceof Element) return e(something); if (something && typeof something === "object" && something.jquery) return something.length === 1 ? e(something[0]) : (something.length > 1 ? (if_multiple_get_first ? (console.warn("JDOM.get_id: multiple elements, using first"), e(something[0])) : false) : false); if (typeof something === "object" && typeof something.length === "number") return something.length === 1 && something[0] instanceof Element ? e(something[0]) : (something.length > 1 && something[0] instanceof Element ? (if_multiple_get_first ? (console.warn("JDOM.get_id: multiple elements, using first"), e(something[0])) : false) : false); if (typeof something === "string") { if (/^[A-Za-z_]/.test(something)) { const el = document.getElementById(something); if (el) return e(el); } const list = document.querySelectorAll(something); return list.length === 1 ? e(list[0]) : (list.length > 1 ? (if_multiple_get_first ? (console.warn("JDOM.get_id: multiple elements, using first"), e(list[0])) : false) : false); } return false; } 29 static closest(dom_elements, css_selector) { if (typeof css_selector !== "string") { console.error("JDOM.closest: css_selector must be a string"); return []; } const elements = this.get_dom_array_elements(dom_elements); if (!elements.length) { console.error("JDOM.closest: invalid dom_elements input"); return []; } const tmp = []; for (const el of elements) { if (!(el instanceof Element)) continue; let found = null; if (el.closest) { found = el.closest(css_selector); } else { if (el.matches && el.matches(css_selector)) { found = el; } else { let parent = el.parentNode; while (parent && parent.nodeType === 1) { if (parent.matches && parent.matches(css_selector)) { found = parent; break; } parent = parent.parentNode; } } } if (found) tmp.push(found); } return tmp; }
30 static find_dom_element(css_selector, root_element = null) { if (typeof css_selector !== "string" || !css_selector) { console.error("JDOM.find_dom_element: css_selector must be a non-empty string"); return false; } let root = null; if (root_element === null) { root = document; } else if (root_element instanceof Element) { root = root_element; } else if (root_element && typeof root_element === "object" && root_element.jquery) { root = root_element.length > 0 ? root_element[0] : null; } else { console.error("JDOM.find_dom_element: root_element must be Element, jQuery object, or null"); return false; } if (!root) return false; const results = root.querySelectorAll(css_selector); if (results.length === 0) return false; if (results.length > 1) { console.warn("JDOM.find_dom_element: multiple elements found for selector '" + css_selector + "', returning first"); if (DEBUG_JDOM) throw new Error("JDOM.find_dom_element: multiple elements found for selector '" + css_selector + "'"); } return results[0]; } 31 static load_scripts(html){if(typeof html!=="string"||!html)return 0;let t=document.createElement("div");t.innerHTML=html;let s=t.querySelectorAll("script,link"),c=0;for(let i=0;i<s.length;i++){let n=document.createElement(s[i].tagName);if(s[i].href)n.href=s[i].href;if(s[i].src)n.src=s[i].src;if(s[i].textContent)n.textContent=s[i].textContent;if(s[i].type)n.type=s[i].type;if(s[i].rel)n.rel=s[i].rel;if(s[i].media)n.media=s[i].media;document.body.appendChild(n);c++;}return c;} 32} 33 34Object.freeze(JDOM); 35 36// jquery alternative for fadeIn, fadeOut, slideUp, slideDown, plugins etc. 37class JQ { 38 static fadeIn(el, duration = 400){el.style.opacity = 0;el.style.display = '';el.style.transition = `opacity ${duration}ms`;requestAnimationFrame(() => {el.style.opacity = 1;});} 39 static fadeOut(el, duration = 400){el.style.transition = `opacity ${duration}ms`;el.style.opacity = 1;requestAnimationFrame(() => {el.style.opacity = 0;});setTimeout(() => {el.style.display = 'none';}, duration);} 40 static slideUp(element, duration = 400, callback){element.style.overflow = 'hidden';let height = element.scrollHeight;let start = Date.now();const animate = () => {const progress = Math.min((Date.now() - start) / duration, 1);element.style.height = (height * (1 - progress)) + 'px';element.style.opacity = 1 - progress;progress < 1 ? requestAnimationFrame(animate) : (element.style.display = 'none', element.style.height = '', element.style.opacity = '', callback && callback());};animate();} 41 static slideDown(element, duration = 400){element.style.display = 'block';let height = element.scrollHeight;element.style.height = '0';element.style.opacity = '0';element.style.overflow = 'hidden';let start = Date.now();const animate = () => {const progress = Math.min((Date.now() - start) / duration, 1);element.style.height = (height * progress) + 'px';element.style.opacity = progress;progress < 1 ? requestAnimationFrame(animate) : (element.style.height = '', element.style.opacity = '', element.style.overflow = '');};animate();} 42} 43 44Object.freeze(JQ); 45 46 47// frequently used functions 48function stdcheck(result,callback,return_false_if_failed){ 49 if (result !== null && (typeof result == 'object') && (typeof result.passed != 'undefined') && result.passed) return result; 50 51 var messages = []; 52 var msg=''; 53 var error_id = 0; 54 if (result === null || typeof result != 'object'){ 55 messages.push(Env.lang.error_query); 56 } else if (typeof result.passed != 'undefined'){ 57 if (!result.passed){ 58 if (result.error){ 59 error_id = result.error; 60 if (result.error_message){ 61 messages.push(result.error_message); 62 console.log('Error check: '+result.error_message); 63 } 64 if (typeof result.errors != 'undefined' && result.errors){ 65 for (var key in result.errors){ 66 messages.push(result.errors[key]); 67 console.log('Error check: '+result.errors[key]); 68 } 69 } 70 if (!messages && result.error) { 71 msg = Env.lang.EMn+result.error+')'; 72 messages.push(msg); 73 } 74 } else { 75 messages.push(Env.lang.unexpectedError); 76 } 77 } 78 } else if(typeof result.passed == 'undefined'){ 79 msg = Env.lang.EMr; 80 messages.push(Env.lang.EMr); 81 82 } 83 if (!messages){ 84 messages.push(Env.lang.unexpectedError); 85 } 86 87 88 if (typeof callback == 'function'){ 89 if (return_false_if_failed){ 90 callback(result,messages); 91 return false; 92 } else { 93 return callback(result,messages); 94 } 95 } else { 96 if (return_false_if_failed){return false;} 97 if (typeof fDialogs._function_alert == 'function'){ 98 //result,context_data,a,handler,error_message,connector 99 fDialogs._function_alert(messages,null,result); 100 } else { 101 alert(messages); 102 } 103 return result; 104 } 105 106} 107function simpleCheck(result){return stdcheck(result,false,true);} 108 109// constructor of Connector 110function cms_connector(module, onloading_start, onloading_finish, onloading_failed,onloading_system_failed) { 111 112 this.loading = false; 113 this.result = {}; 114 this.cache_keys = []; 115 this.module = '_common'; 116 this.cache_values = []; 117 this.queue = []; 118 this.queue_index = -1; 119 this.modal =0; 120 this.admin=0; 121 this._onloading_start = (typeof onloading_start == 'function') ? onloading_start : (onloading_start === false ? false : fDialogs._onloading_start); 122 this._onloading_finish = (typeof onloading_finish == 'function') ? onloading_finish : (onloading_finish === false ? false : fDialogs._onloading_finish); 123 this._onloading_failed = (typeof onloading_failed == 'function') ? onloading_failed : (onloading_failed === false ? false : fDialogs._onloading_failed); 124 this._onloading_system_failed = (typeof onloading_system_failed == 'function') ? onloading_system_failed : null; 125 126 if (typeof module == 'string') { 127 this.module = module; 128 } else if (typeof module == 'number') { 129 this.module = 'object_' + module; 130 } 131 132 this._queue_process = function(){ 133 var keys = Object.keys(this.queue); 134 if (this.loading || !keys.length) return true; 135 this.loading = true; 136 var request_id = keys[0]; 137 var request = this.queue[request_id]; 138 return this._send_async(request); 139 }, 140 141 this._send_async = function(request){ 142 this.result={}; 143 let xhr = new XMLHttpRequest(); 144 if (Env._can_parse_json){ 145 xhr.responseType = 'json'; 146 } else { 147 xhr.onloadstart = function(){ /* ie 11 bug fix */ this.responseType = "json"; } 148 } 149 xhr.open("POST",request.url,true); 150 xhr.context = this; 151 xhr.request_id = request.id; 152 xhr.request_data = request; 153 xhr.onreadystatechange = this._callback_on_response; 154 if (typeof request.onloading_start == 'function'){ 155 if (typeof request.context == 'object'){ 156 (request.onloading_start).apply(request.context,[request.context_data,request,xhr]); 157 } else { 158 request.onloading_start(request.context_data,request,xhr); 159 } 160 } 161 try { 162 xhr.send(request.data); 163 } catch(err) { 164 console.log('XHR error on sending request ID='+request.id); 165 if (typeof request.onloading_failed == 'function'){ 166 if (typeof request.context == 'object'){ 167 return (request.onloading_failed).apply(request.context,[null,context_data,request,xhr,err,connector]); 168 } else { 169 return (request.onloading_failed).apply(connector,[null,context_data,request,xhr,err,connector]); 170 } 171 } else { 172 if (typeof request.context == 'object'){ 173 return (request.callback).apply(request.context,[null,context_data,request,xhr,err,connector]); 174 } else { 175 request.callback(null,context_data,request,xhr,err,connector); 176 } 177 } 178 return false; 179 } 180 return false; 181 }, 182 183 this._send_sync = function(request){ 184 var xhr = new XMLHttpRequest(); 185 xhr.open("POST",request.url,false); 186 if (typeof request.onloading_start == 'function'){ 187 if (typeof request.context == 'object'){ 188 (request.onloading_start).apply(request.context,[request.context_data,request,xhr]); 189 } else { 190 request.onloading_start(request.context_data,request,xhr); 191 } 192 } 193 var result = null; 194 var error=false; 195 this.result = {}; 196 try { 197 xhr.send(request.data); 198 if (xhr.readyState !== XMLHttpRequest.DONE){ 199 console.log('Request failed. Status != DONE'); 200 error=true; 201 } 202 if (xhr.status != 200){ 203 error = xhr.status; 204 } 205 // getting result 206 if (!error){ 207 result = JSON.parse(xhr.responseText); 208 } else { 209 if (xhr.responseText){ 210 result = JSON.parse(xhr.responseText); 211 if (typeof result != 'object'){ 212 result = {'passed':0,'error':-9999,'error_message':xhr.responseText,'http_status':xhr.status} 213 } 214 } 215 } 216 if (typeof result == 'undefined' || result === null || result === false){ 217 error = true; 218 } else{ 219 if(typeof request.context_data == 'object' && request.context_data !== null){ 220 result['_context']=request.context_data; 221 } 222 } 223 this.result = result; 224 if (typeof request.onloading_finish == 'function'){ 225 if (typeof request.context == 'object'){ 226 (request.onloading_finish).apply(request.context,[result,request.context_data,request,this]); 227 } else { 228 request.onloading_finish(result,request.context_data,request,this); 229 } 230 } 231 if (!error){ 232 if (typeof result == 'undefined' || result === null){ 233 // bad output format or php errors. json not parsed 234 error=true; 235 if (typeof request.onloading_failed == 'function'){ 236 // custom function exists 237 if (typeof request.context == 'object'){ 238 (request.onloading_failed).apply(request.context,[result,request.context_data,null,xhr,'Response parse error',this]); 239 } else { 240 request.onloading_failed(result,request.context_data,null,xhr,'Response parse error',this); 241 } 242 } else { 243 // use standart callback 244 if (typeof request.context == 'object'){ 245 (request.callback).apply(request.context,[result,request.context_data,request,this]); 246 } else { 247 request.callback(result,request.context_data,request,this); 248 } 249 } 250 } 251 } 252 if (request.cache_index !== null){ 253 this.cache_values[request.cache_index]=result; 254 } 255 } catch(err) { 256 console.log('XHR error on sending request ID='+request.id); 257 if (typeof request.onloading_finish == 'function'){ 258 if (typeof request.context == 'object'){ 259 (request.onloading_finish).apply(request.context,[result,request.context_data,request,this]); 260 } else { 261 request.onloading_finish(result,request.context_data,request,this); 262 } 263 } 264 if (typeof request.onloading_failed == 'function'){ 265 if (typeof request.context == 'object'){ 266 (request.onloading_failed).apply(request.context,[null,request.context_data,request,xhr,err,this]); 267 } else { 268 request.onloading_failed(null,request.context_data,request,xhr,err,this); 269 } 270 } 271 } 272 return result; 273 }, 274 275 this._callback_on_response = function(){ 276 if (this.readyState !== XMLHttpRequest.DONE) { 277 return true; 278 } 279 let result = this.response; 280 let request = this.request_data; 281 let request_id = request.id; 282 let context_data = request.context_data; 283 let current_connector = request.connector; 284 let is_modal = request.modal; 285 delete current_connector.queue[request_id]; 286 current_connector.loading=false; 287 if (is_modal){ 288 if (typeof xDialogs.show_modal_loading == 'function'){ 289 xDialogs.hide_modal_loading(); 290 } else { 291 fDialogs.hide_loading(); 292 } 293 } 294 if (typeof request.onloading_finish == 'function'){ 295 if (typeof request.context == 'object'){ 296 (request.onloading_finish).apply(request.context,[result,context_data,request,this]); 297 } else { 298 (request.onloading_finish).apply(current_connector,[result,context_data,request,this]); 299 } 300 } 301 if (typeof result == 'undefined' || result === null){ 302 // bad output format or php errors. json not parsed 303 if (typeof request.onloading_failed == 'function'){ 304 // custom function exists 305 if (typeof request.context == 'object'){ 306 (request.onloading_failed).apply(request.context,[result,context_data,null,this,'Response parse error',current_connector]); 307 } else { 308 (request.onloading_failed).apply(current_connector,[result,context_data,null,this,'Response parse error',current_connector]); 309 } 310 } else { 311 // use standart callback 312 if (typeof request.context == 'object'){ 313 (request.callback).apply(request.context,[result,context_data,request,this]); 314 } else { 315 (request.callback).apply(current_connector,[result,context_data,request,this]); 316 } 317 } 318 } else { 319 if (typeof request.context_data == 'object' && request.context_data !== null){ 320 result['_context']=request.context_data; 321 } 322 current_connector.result = result; 323 // Check for system error (negative error code) 324 if (typeof result === 'object' && result !== null && typeof result.error === 'number' && result.error < 0) { 325 // Check for fatal error (error code -1000 = Fatal PHP Error) 326 if (result.error === -1000) { 327 if (typeof current_connector._onloading_failed === 'function') { 328 current_connector._onloading_failed(result, context_data, null, this, 'Fatal PHP Error', current_connector); 329 } 330 } else { 331 // Call system failed for other negative errors 332 if (typeof current_connector._onloading_system_failed === 'function') { 333 current_connector._onloading_system_failed(result, context_data, request, this); 334 } 335 } 336 } 337 if (this.status != 200 ){ 338 if (this.status == 401 && typeof result.http_status != 'undefined' && typeof fDialogs.__onloading_unauthorize_response == 'function'){ 339 if (typeof request.context == 'object'){ 340 (fDialogs.__onloading_unauth
340orize_response).apply(request.context,[result.http_status,result.login_url,result,context_data,null,this]); 341 } else { 342 (fDialogs.__onloading_unauthorize_response).apply(this,[result.http_status,result.login_url,result,context_data,null,this]); 343 } 344 } 345 } else { 346 if (typeof request.context == 'object'){ 347 (request.callback).apply(request.context,[result,context_data,request,this]); 348 } else { 349 (request.callback).apply(current_connector,[result,context_data,request,this]); 350 } 351 } 352 } 353 if (request.cache_index !== null){ 354 current_connector.cache_values[request.cache_index]=result; 355 } 356 return current_connector._queue_process(); 357 }, 358 359 this._parse_request_to_formdata = function(request,try_use_cache){ 360 361 let old_browser_formdata_function=false; 362 let params_count=0; 363 let request_formdata = new FormData(); 364 let can_cache=true; 365 let cache_key=[]; 366 let context_data = null; 367 let funclist = []; 368 let funconly = []; 369 370 371 for (var funcname in request){ 372 if (funcname == '_context'){ 373 context_data = request[funcname]; 374 } 375 var request_cache_key = []; 376 funclist.push(funcname); 377 var funcparams = request[funcname]; 378 var t = typeof funcparams; 379 if (t == 'string' && /^#.+$/.test(funcparams)){ 380 funcparams = Toolbox.form_export_formdata(funcparams.slice(1)); 381 t = typeof funcparams; 382 } 383 var ts = funcparams.toString(); 384 if (t == 'object'){ 385 if (ts == '[object FormData]'){ 386 // formData object 387 var tmp = this._parse_formdata_to_object(funcparams); 388 if (tmp === false){ 389 // false = browser not support iteration by FormData 390 if (!old_browser_formdata_function && !params_count){ 391 // add only if first and mark its method 392 request_formdata = funcparams; 393 old_browser_formdata_function = funcname; 394 request_formdata.append('_old_browser_method',funcname); 395 can_cache=false; 396 cache_key=null; 397 } else { 398 var msg = 'Error: old browser not support FormData methods'; 399 console.log(msg); 400 alert(msg); 401 return null; 402 } 403 } else { 404 var keys = Object.keys(tmp); 405 for (var i=0;i<keys.length;i++){ 406 var key = keys[i]; 407 if (typeof tmp[key] == 'object'){ 408 var its_key_is_array = (key.indexOf('[]') == -1) ? false : true; 409 if (!Array.isArray(tmp[key])){ 410 // system object 411 if (its_key_is_array){ 412 request_formdata.append(funcname+'___'+key,tmp[key]); 413 } else { 414 var ttf = tmp[key].toString(); 415 if (ttf == '[object File]'){ 416 request_formdata.append(funcname+'___'+key,tmp[key]); 417 } else { 418 request_formdata.append(funcname+'___'+key+'[]',tmp[key]); 419 } 420 } 421 } else { 422 // array 423 var kk = Object.keys(tmp[key]); 424 for (var k in kk){ 425 if (its_key_is_array){ 426 request_formdata.append(funcname+'___'+key,tmp[key][k]); 427 } else { 428 request_formdata.append(funcname+'___'+key+'[]',tmp[key][k]); 429 } 430 } 431 } 432 } else { 433 request_formdata.append(funcname+'___'+key,tmp[key]); 434 } 435 params_count++; 436 if (try_use_cache && can_cache){ 437 var t = Toolbox.generate_cache_key(tmp[key]); 438 if (t === null){ 439 can_cache=false; 440 cache_key=null; 441 } else { 442 if (t.length){ 443 request_cache_key.push(key+'='+t); 444 } 445 } 446 } 447 } 448 } 449 } else { 450 // ordinary object=array 451 var keys = Object.keys(funcparams); 452 for (var i=0;i<keys.length;i++){ 453 var key = keys[i]; 454 // walk by keys 455 var type_of_val = typeof funcparams[key]; 456 if (type_of_val == 'object'){ 457 if (Array.isArray(funcparams[key])){ 458 var val = '___json___'+JSON.stringify(funcparams[key]) 459 request_formdata.append(funcname+'___'+key,val); 460 } else { 461 // object but not array = system dom object 462 var its_key_is_array = (key.indexOf('[]') == -1) ? false : true; 463 if (funcparams[key] === null){ 464 var val = '___json___'+JSON.stringify(funcparams[key]) 465 request_formdata.append(funcname+'___'+key,val); 466 } else { 467 var tx = funcparams[key].toString(); 468 if (tx == '[object FileList]'){ 469 var file_l = funcparams[key].length; 470 if (file_l == 1){ 471 request_formdata.append(funcname+'___'+key,funcparams[key][0]); 472 } else { 473 if (file_l > 1){ 474 for (var file_i=0;file_i<file_l;file_i++){ 475 var f = funcparams[key][file_i]; 476 if (its_key_is_array){ 477 request_formdata.append(funcname+'___'+key,f); 478 } else { 479 request_formdata.append(funcname+'___'+key+'[]',f); 480 } 481 } 482 } 483 } 484 } else { 485 if (tx == '[object File]'){ 486 //ccnsole.log('single file added!!!'); 487 request_formdata.append(funcname+'___'+key,funcparams[key]); 488 } else { 489 if (type_of_val == 'string'){ 490 request_formdata.append(funcname+'___'+key,funcparams[key]); 491 } else { 492 var val = '___json___'+JSON.stringify(funcparams[key]); 493 request_formdata.append(funcname+'___'+key,val); 494 } 495 } 496 } 497 } 498 } 499 } else { 500 if (type_of_val == 'string'){ 501 request_formdata.append(funcname+'___'+key,funcparams[key]); 502 } else { 503 var val = '___json___'+JSON.stringify(funcparams[key]); 504 request_formdata.append(funcname+'___'+key,val); 505 } 506 } 507 508 params_count++; 509 if (try_use_cache && can_cache){ 510 var t = Toolbox.generate_cache_key(funcparams[key]); 511 if (t === null){ 512 can_cache=false; 513 cache_key=null; 514 } else { 515 if (t.length){ 516 request_cache_key.push(key+'='+t); 517 } 518 } 519 } 520 } 521 } 522 523 if (can_cache && request_cache_key && try_use_cache){ 524 cache_key.push(funcname+'=|'+request_cache_key.join('&')+'|') 525 } 526 } else { 527 if (t != 'undefined'){ 528 params_count++; 529 var val = '___json___'+JSON.stringify(funcparams); 530 request_formdata.append(funcname+'___params',val); 531 } 532 } 533 } 534 for (var i=0;i<funclist.length;i++){ 535 if (funclist[i] != '_context') funconly.push(funclist[i]); 536 } 537 return [request_formdata,can_cache,cache_key,context_data,funclist,funconly]; 538 }, 539 540 this._parse_formdata_to_object = function(fd ){ 541 if (typeof fd.keys == 'undefined'){ 542 console.log('Old browser!'); 543 return false; 544 } 545 var tmp = {} 546 var keys = fd.keys(); 547 var item = keys.next(); 548 while (!item.done){ 549 var val = fd.getAll(item.value); 550 if (val.length == 1){ 551 tmp[item.value]=val[0]; 552 } else { 553 if (val.length > 1){ 554 tmp[item.value]=val; 555 } else { 556 tmp[item.value]=null; 557 } 558 } 559 item = keys.next(); 560 } 561 return tmp; 562 } 563 564 this.execute = function (request, callback, context_object, try_use_cache) { 565 if (typeof request != 'object' || request === null) { 566 console.log('Connector error : empty request'); 567 return false; 568 } 569 let time_start = new Date(); 570 let [request_data, can_cache, cache_key,context_data,funclist,funconly] = this._parse_request_to_formdata(request,try_use_cache); 571 let cache_index = null; 572 let cache_using = 0; 573 574 request_data.append('__methods_list', funclist.join(',')); 575 request_data.append('__EPC', __EPC); 576 577 578 579 if ((try_use_cache ?? false) && can_cache && cache_key.length) { 580 cache_key = (cache_key.length == 1) ? cache_key[0] : cache_key.join('&'); 581 cache_index = this.cache_keys.indexOf(cache_key); 582 if (cache_index === -1) { 583 cache_index = this.cache_keys.length; 584 this.cache_keys[cache_index] = cache_key; 585 } else { 586 if (typeof this.cache_values[cache_index] != 'undefined') { 587 console.log('Result was founded in cache'); 588 var result = this.cache_values[cache_index]; 589 this.result = result; 590 if (typeof callback == 'function') { 591 if (typeof context_object == 'object') { 592 return (callback).apply(context_object, [result, context_data]); 593 } else { 594 return (callback).apply(this, [result, context_data]); 595 } 596 } else { 597 return result; 598 } 599 } 600 } 601 } 602 var async = ((typeof callback == 'function') ? true : false); 603 var urlparams = []; 604 if (this.module != '_common') { 605 urlparams.push("__modname=" + encodeURIComponent(this.module)); 606 } 607 var connector_request = { 608 'comment' : this.module + ' -> '+funconly.join(','), 609 'url': document.location.protocol + '//' + document.location.host + '/_connector/' + (urlparams ? "?" + urlparams.join('&') : ''), 610 'module': this.module, 611 'modal': this.modal, 612 'cache_index': cache_index, 613 'data': request_data, 614 'connector': this, 615 'context_data': context_data, 616 'context': context_object, 617 'onloading_start': this._onloading_start, 618 'onloading_finish': this._onloading_finish, 619 'onloading_failed': this._onloading_failed 620 }; 621 this.modal = 0; 622 console.log('Connector:: '+(async ? 'async' : 'sync')+(this.admin ? ' admin' : '')+(cache_using ? ' cached' : '') + ' request to: '+connector_request.module+ ' -> '+funconly.join(', ')); 623 if (async) { 624 connector_request['callback'] = callback; 625 this.queue_index++; 626 var request_id = this.queue_index; 627 connector_request['id'] = request_id; 628 this.queue[request_id] = connector_request; 629 this._queue_process(); 630 return true; 631 } else { 632 return this._send_sync(connector_request); 633 } 634 }; 635 636 this.ajax_module = function (modulename,request) { 637 let self = this; 638 modulename = (typeof modulename =='string' && modulename.trim()) ? modulename.trim() : this.module; 639 return new Promise((resolve, reject) => { 640 641 // Prepare FormData 642 643 let [request_data, can_cache, cache_key,context_data,funclist,funconly] = this._parse_request_to_formdata(request); 644 request_data.append('__methods_list', funclist.join(',')); 645 request_data.append('__EPC', __EPC); 646 647 // Create XHR 648 var xhr = new XMLHttpRequest(); 649 var urlparams = []; 650 if (typeof modulename == 'string') modulename = modulename.trim(); 651 652 if (typeof modulename == 'string' && modulename.length){ 653 urlparams.push("__modname=" + encodeURIComponent(modulename.trim())); 654 } else if (self.module !== '_common') { 655 urlparams.push("__modname=" + encodeURIComponent(self.module)); 656 } 657 658 var url = document.location.protocol + '//' + document.location.host + '/_connector/' + 659 (urlparams ? "?" + urlparams.join('&') : ''); 660 661 xhr.open("POST", url, true); 662 663 xhr.onload = function () { 664 665 let errorObj = {status: xhr.status,response: xhr.response,statusText: xhr.statusText}; 666 667 if (xhr.status === 200) { 668 var response = xhr.response; 669 let failed=false; 670 // JSON response ONLY allowed 671 if (typeof response === 'string') { 672 if (!response.length){ 673 failed = true; 674 c
674onsole.error('Connector:: Error JSON response is empty:', errorObj); 675 } else { 676 try { 677 response = JSON.parse(response); 678 } catch (e) { 679 failed = true; 680 const cleaned = response 681 .replace(/<[^>]*>/g, '') // ÑбиÑаем Ñеги 682 .replace(/"/g, '"') // декодиÑÑем ÑаÑÑÑе HTML-ÑÑÑноÑÑи 683 .replace(/&/g, '&') 684 .replace(/</g, '<') 685 .replace(/>/g, '>') 686 .trim() 687 ; 688 if (cleaned.length > 0 && cleaned.length <= 200) { 689 console.error('Connector:: Server returned non-JSON response:\n' + cleaned); 690 } else { 691 console.error('Connector:: Error parsing JSON response:', errorObj); 692 } 693 694 } 695 } 696 697 } else if (typeof response !== 'object' || response === null){ 698 console.error('Connector:: Error with JSON response:', errorObj); 699 failed = true; 700 } 701 702 if (failed){ 703 response = {}; 704 if (typeof self._onloading_finish === 'function') { 705 self._onloading_finish(response, context_data,xhr,this); 706 } 707 if (typeof self._onloading_failed === 'function') { 708 self._onloading_failed(null, request, xhr, errorObj); 709 } 710 resolve(response); 711 return; 712 } 713 714 // Add context to response 715 if (typeof context_data === 'object' && context_data !== null) { 716 response._context = context_data; 717 } 718 719 self.result = response; 720 721 if (typeof self._onloading_finish === 'function') { 722 self._onloading_finish(response, context_data); 723 } 724 725 // Check for system error (negative error code) 726 if (typeof response === 'object' && response !== null && typeof response.error === 'number' && response.error < 0) { 727 // Check for fatal error (error code -1000 = Fatal PHP Error) 728 if (response.error === -1000) { 729 if (typeof self._onloading_failed === 'function') { 730 self._onloading_failed(response, request, xhr, {status: xhr.status, response: xhr.response, statusText: xhr.statusText, error: 'Fatal PHP Error'}); 731 } 732 } else { 733 // Call system failed for other negative errors 734 if (typeof self._onloading_system_failed === 'function') { 735 self._onloading_system_failed(response, request, xhr, {status: xhr.status, response: xhr.response, statusText: xhr.statusText}); 736 } 737 } 738 } 739 740 resolve(response); 741 } else { 742 if (typeof self._onloading_failed === 'function') { 743 self._onloading_failed(null, request, xhr, errorObj); 744 } 745 reject(errorObj); 746 } 747 }; 748 749 xhr.onerror = function () { 750 var errorObj = { 751 status: xhr.status, 752 error: 'Network error', 753 xhr: xhr 754 }; 755 756 if (typeof self._onloading_failed === 'function') { 757 self._onloading_failed(null, request, xhr, errorObj); 758 } 759 760 reject(errorObj); 761 }; 762 763 xhr.ontimeout = function () { 764 var errorObj = { 765 error: 'Request timeout', 766 xhr: xhr 767 }; 768 769 if (typeof self._onloading_failed === 'function') { 770 self._onloading_failed(null, request, xhr, errorObj); 771 } 772 773 reject(errorObj); 774 }; 775 776 if (typeof self._onloading_start === 'function') { 777 self._onloading_start(context_data, null, xhr,this); 778 } 779 console.log('Connector:: await request to: '+this.module+ ' -> '+funconly.join(', ')); 780 xhr.send(request_data); 781 782 }); 783 }; 784 785 // custom short methods 786 this.ajax = function (request,modulename) {return this.ajax_module(modulename,request);}, 787 this.executex = function (request, callback, context_object) { return this.execute(request, callback, context_object, true); }; 788 789}; 790 791// admin panel add-on for Connector`s constructor 792function cms_connector_admin(name) { 793 cms_connector_admin.superclass.call(this, name); 794 this.admin=1; 795 this.run_now_cached =false; 796 this.modal=false; 797 this._onloading_start = function(context_data,request,xhr){ 798 if (request && typeof request.connector == 'object' && typeof request.connector.modal == 'number' && request.connector.modal){ 799 xDialogs.show_modal_loading(); 800 } else { 801 xDialogs.show_loading_connector(); 802 } 803 804 } 805 this._onloading_finish = function(result,context_data,request,xhr){ 806 if (request && typeof request.connector == 'object' && typeof request.connector.modal == 'number' && request.connector.modal){ 807 xDialogs.hide_modal_loading(); 808 } else { 809 xDialogs.hide_loading_connector(); 810 } 811 } 812 813 this._onloading_failed = function(result, request, xhr, errorObj){ 814 xDialogs.stdcheck(result); 815 } 816 817 this.run = function(request,callback,context){ 818 this.modal = false; 819 if (this.run_now_cached){ 820 this.run_now_cached=false; 821 this.executex(request,callback); 822 } else { 823 this.execute(request,callback,context); 824 } 825 return this.result; 826 }; 827 828 this.runx = function(request,callback,raw){ 829 this.run_now_cached =true; 830 return this.run(request,callback,raw); 831 }; 832 833 this.run_modal = function(request,callback,context){ 834 this.modal=true; 835 if (this.run_now_cached){ 836 this.run_now_cached=false; 837 this.executex(request,callback,context); 838 } else { 839 this.execute(request,callback,context); 840 if (typeof callback == 'function'){ 841 return false; 842 } 843 } 844 if (typeof callback == 'function'){ 845 if (typeof context == 'object'){ 846 return (callback).apply(context,[this.result]); 847 } else { 848 callback(this.result); 849 } 850 } 851 return this.result; 852 }; 853 854 this.runx_modal = function(request,callback,raw){ 855 this.run_now_cached =true; 856 return this.run_modal(request,callback,raw); 857 } 858 859} 860Object.assign(cms_connector_admin.prototype, cms_connector.prototype); 861cms_connector_admin.superclass = cms_connector; 862 863// Detected environment vars of cms 864var Env = { 865 866 is_dev_server: false, 867 is_local_scripts_mode: false, 868 is_xfront_mode: false, 869 is_print_version: 0, 870 871 current_gmt :null, 872 current_date : null, 873 current_datetime : null, 874 current_daytime : null, 875 _ms_browser_version : null, 876 877 _can_parse_json : true, 878 path_web_lib : null, 879 path_widgets_lib : null, 880 auth_zone : 'front', 881 language_list : __LANG_LIST, 882 language : __LANG, 883 language_alt : __LANG_ALT, 884 lang : null, 885 886 __loaded_scripts_ids : [], 887 888 get_ms_browser_version: function () { 889 if (Env._ms_browser_version !== null) return Env._ms_browser_version; 890 const ua = navigator.userAgent; 891 let v = false; 892 const msie = ua.indexOf('MSIE '); 893 if (msie > 0) { 894 v = parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10); 895 } else { 896 const trident = ua.indexOf('Trident/'); 897 if (trident > 0) { 898 const rv = ua.indexOf('rv:'); 899 v = parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10); 900 } else { 901 const edge = ua.indexOf('Edge/'); 902 if (edge >
902 0) v = parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10); 903 } 904 } 905 Env._ms_browser_version = v; 906 return v; 907 }, 908 909 init_dates : function(){ 910 var date = new Date(); 911 Env.current_gmt = -date.getTimezoneOffset()/60; 912 Env.current_date = Toolbox.format_date('date',date); 913 Env.current_datetime = Toolbox.format_date('datetime',date); 914 Env.current_daytime = Toolbox.format_date('daytime',date); 915 }, 916 917 init : function(){ 918 919 for (var i=0,c=Env.language_list.length;i<c;i++){ 920 var l = Env.language_list[i]; 921 l = l.toLowerCase(); 922 if (typeof _COMMON_LANGS[l] != 'undefined'){ 923 Env.lang = _COMMON_LANGS[l]; 924 break; 925 } 926 } 927 let iev = Env.get_ms_browser_version(); 928 if (iev && iev < 12){ 929 Env._can_parse_json=false; 930 } 931 Env.path_web_lib = __ALP; 932 Env.path_widgets_lib = __WFLP ; 933 Env.auth_zone = AUTH_ZONE; 934 Env.init_dates(); 935 if (typeof __JSAD == 'string' && __JSAD){ 936 try { 937 let ds = JSON.parse(atob(__JSAD)); 938 Env.is_local_scripts_mode = ds.lsm; 939 Env.is_dev_server = ds.ds; 940 Env.is_xfront_mode = ds.xf; 941 Env.is_print_version = ds.pm; 942 } catch (e) { 943 console.error('WARNING: ext. auth info parse error!', e); 944 } 945 } else { 946 Env.is_dev_server = document.location.hostname == 'localhost' || document.location.hostname.endsWith('.local') ? 1 : 0; 947 Env.is_xfront_mode = AUTH_ZONE == 'xfront' ? 1 : 0; 948 } 949 } 950} 951 952var Stack = { 953 954 _callbacks : {}, 955 _callbacks_last_key : 1, 956 _user_callbacks : {}, 957 _user_callbacks_last_key : 1, 958 959 push : function(callback_data){ 960 var key=this._callbacks_last_key; 961 while (typeof this._callbacks[key] != 'undefined') key++; 962 this._callbacks[key]= (typeof callback_data == 'undefined') ? {} : callback_data; 963 this._callbacks_last_key = key; 964 return key; 965 }, 966 967 pop : function(callback_key){ 968 if (typeof callback_key == 'undefined'){ 969 callback_key = this._callbacks_last_key; 970 } 971 if (typeof this._callbacks[callback_key] != 'undefined'){ 972 var back = this._callbacks[callback_key]; 973 delete this._callbacks[callback_key]; 974 var keys = Object.keys(this._callbacks); 975 if(keys.length){ 976 this._callbacks_last_key = keys[keys.length-1]; 977 } 978 return back; 979 } 980 }, 981 982 get : function(callback_key,delete_key){ 983 if (typeof callback_key == 'undefined'){ 984 console.log('Wrong callback key!'); 985 return false; 986 } 987 if (typeof this._callbacks[callback_key] != 'undefined'){ 988 var t = this._callbacks[callback_key]; 989 if (delete_key) delete this._callbacks[callback_key]; 990 return t; 991 } 992 }, 993 994 custom_push : function(callback_data){ 995 var key=this._user_callbacks_last_key; 996 if (key === null){ 997 key = 1; 998 } else { 999 while (typeof this._user_callbacks[key] != 'undefined'){ 1000 key++; 1001 } 1002 } 1003 if (typeof callback_data == 'undefined'){ 1004 this._user_callbacks[key]={}; 1005 } else { 1006 this._user_callbacks[key]=callback_data; 1007 } 1008 this._user_callbacks_last_key=key; 1009 return key; 1010 }, 1011 1012 custom_pop : function(callback_key){ 1013 if (typeof callback_key == 'undefined'){ 1014 1015 var last_key = null; 1016 var prev_key = null; 1017 for (var key in this._user_callbacks){ 1018 prev_key = last_key; 1019 last_key=key; 1020 } 1021 if (!last_key){ 1022 console.log('callback_pop() failed!. array is empty.'); 1023 return null; 1024 } 1025 callback_key = last_key; 1026 this._user_callbacks_last_key=prev_key; 1027 } 1028 if (typeof this._user_callbacks[callback_key] != 'undefined'){ 1029 var back = this._user_callbacks[callback_key]; 1030 delete this._user_callbacks[callback_key]; 1031 return back; 1032 } 1033 }, 1034 1035 custom_get : function(callback_key){ 1036 if (typeof callback_key == 'undefined'){ 1037 var last_key = null; 1038 for (var key in this._user_callbacks){ 1039 last_key=key; 1040 } 1041 if (!last_key){ 1042 console.log('callback_pop() failed!. array is empty.'); 1043 return null; 1044 } 1045 callback_key = last_key; 1046 } 1047 if (typeof this._user_callbacks[callback_key] != 'undefined'){ 1048 return this._user_callbacks[callback_key]; 1049 } 1050 } 1051}; 1052 1053var Toolbox = { 1054 1055 loadScriptOnce : function(url, id, force_load = false) { 1056 if (!force_load && Env.__loaded_scripts_ids.includes(id)) { 1057 return; 1058 } 1059 if (force_load) { 1060 const old = document.getElementById(id); 1061 if (old) old.remove(); 1062 } 1063 const s = document.createElement('script'); 1064 s.id = id; 1065 s.src = url; 1066 s.type = 'text/javascript'; 1067 Env.__loaded_scripts_ids.push(id); 1068 document.head.appendChild(s); 1069 }, 1070 1071 convert_coord_to_array : function(str_coords){ 1072 if (typeof str_coords != 'string') return null; 1073 let coords = (str_coords.indexOf('[') != -1) ? str_coords.slice(1,-1) : str_coords; 1074 coords=coords.split(','); 1075 return [parseFloat(coords[0]),parseFloat(coords[1])]; 1076 }, 1077 1078 copyToClipboard : function(message) { 1079 let textArea = document.createElement("textarea"); 1080 textArea.value = message; 1081 textArea.style.opacity = "0"; 1082 document.body.appendChild(textArea); 1083 textArea.focus(); 1084 textArea.select(); 1085 try { 1086 let successfull = document.execCommand('copy'); 1087 alert(successfull ? Env.lang.clipboard_success : Env.lang.clipboard_failed); 1088 } catch (err) { 1089 alert('Unable to copy value , error : ' + err.message); 1090 } 1091 document.body.removeChild(textArea); 1092 }, 1093 1094 get_url_param : function(param){return new URLSearchParams(window.location.search).get(param);}, 1095 1096 get_url_all_params : function(url) { 1097 var queryString = url ? url.split('?')[1] : window.location.search.slice(1); 1098 var obj = {}; 1099 if (queryString) { 1100 queryString = queryString.split('#')[0]; 1101 var arr = queryString.split('&'); 1102 for (var i = 0; i < arr.length; i++) { 1103 var a = arr[i].split('='); 1104 var paramName = a[0]; 1105 var paramValue = typeof (a[1]) === 'undefined' ? true : a[1]; 1106 paramName = paramName.toLowerCase(); 1107 if (typeof paramValue === 'string') paramValue = paramValue.toLowerCase(); 1108 if (paramName.match(/\[(\d+)?\]$/)) { 1109 var key = paramName.replace(/\[(\d+)?\]/, ''); 1110 if (!obj[key]) obj[key] = []; 1111 if (paramName.match(/\[\d+\]$/)) { 1112 var index = /\[(\d+)\]/.exec(paramName)[1]; 1113 obj[key][index] = paramValue; 1114 } else { 1115 obj[key].push(paramValue); 1116 } 1117 } else { 1118 if (!obj[paramName]) { 1119 obj[paramName] = paramValue; 1120 } else if (obj[paramName] && typeof obj[paramName] === 'string') { 1121 obj[paramName] = [obj[paramName]]; 1122 obj[paramName].push(paramValue); 1123 } else { 1124 obj[paramName].push(paramValue); 1125 } 1126 } 1127 } 1128 } 1129 return obj;
1130 }, 1131 1132 get_browser_time : function(server_time,server_event_time,server_next_event_date){ 1133 let now_microtime = Date.now(); 1134 let t = Math.floor(now_microtime/1000); 1135 let diff = t - server_time; 1136 let hours_diff = Math.round(diff / 3600); 1137 if (hours_diff){ 1138 diff = diff - 3600*hours_diff; 1139 } 1140 let new_time = (server_event_time + 3600*hours_diff); 1141 let new_microtime = 1000*new_time; 1142 let sdate = fDialogs.datetime_format(new_time); 1143 return { 1144 'diff' : {'hours':hours_diff,'seconds':diff}, 1145 'msec_left' : (new_microtime - now_microtime), 1146 'sec_left' : (new_time - t), 1147 'time':new_time, 1148 'microtime':new_microtime, 1149 'datetime_server' : server_next_event_date, 1150 'datetime_browser' : sdate 1151 } 1152 }, 1153 1154 form_export_object : function (form_dom_or_id, remove_prefix, checkbox_to_zero){ 1155 let form = null; 1156 1157 if (form_dom_or_id && form_dom_or_id.jquery){ 1158 const id = JDOM.generate_new_unique_dom_id(form_dom_or_id); 1159 form = document.getElementById(id); 1160 } else if (typeof form_dom_or_id === 'string'){ 1161 form = document.getElementById(form_dom_or_id.trim()); 1162 } else if (form_dom_or_id instanceof Element){ 1163 form = form_dom_or_id; 1164 } else { 1165 console.log('Invalid parameter: must be ID, DOM element, or jQuery object'); 1166 return null; 1167 } 1168 1169 if (!form || !form.elements) return null; 1170 1171 remove_prefix = remove_prefix || ''; 1172 checkbox_to_zero = (typeof checkbox_to_zero === 'undefined') ? true : checkbox_to_zero; 1173 1174 const formData = {}; 1175 1176 for (let i = 0; i < form.elements.length; i++){ 1177 const el = form.elements[i]; 1178 if (el.disabled) continue; 1179 1180 const tag = el.tagName.toLowerCase(); 1181 let name = el.name || el.id || null; 1182 if (!name) continue; 1183 1184 let val = null; 1185 1186 if (tag === 'input'){ 1187 if (['text','email','date','password','button','submit','hidden','tel'].includes(el.type)){ 1188 val = el.value; 1189 } else if (el.type === 'number'){ 1190 val = el.step ? parseFloat(el.value) : parseInt(el.value); 1191 } else if (el.type === 'checkbox'){ 1192 if (el.checked){ 1193 val = (el.value === '1') ? 1 : el.value; 1194 } else if (checkbox_to_zero){ 1195 val = el.checked; 1196 } 1197 } else if (el.type === 'radio'){ 1198 if (el.checked){ 1199 val = el.value; 1200 } else { 1201 try { 1202 if (typeof eval('formData.' + name) !== 'undefined') continue; 1203 } catch(e){ continue; } 1204 } 1205 } else if (el.type === 'file'){ 1206 val = el.files; 1207 } 1208 1209 } else if (tag === 'select'){ 1210 if (el.options.length){ 1211 if (el.multiple){ 1212 name = name.replace(/\[\]$/,''); 1213 val = []; 1214 for (let o = 0; o < el.options.length; o++){ 1215 const opt = el.options[o]; 1216 if (el.getAttribute('fullselect')){ 1217 val[opt.value] = opt.text; 1218 } else if (opt.selected){ 1219 val.push(opt.value); 1220 } 1221 } 1222 } else if (el.selectedIndex >= 0){ 1223 val = el.options[el.selectedIndex].value; 1224 } 1225 } 1226 1227 } else if (tag === 'textarea'){ 1228 val = el.value; 1229 } 1230 1231 try { 1232 if (remove_prefix){ 1233 const len = remove_prefix.length; 1234 if (name.slice(0,len) === remove_prefix) name = name.slice(len); 1235 } 1236 1237 if (/^(\w+)$/.test(el.name)){ 1238 const tpl = 'formData["' + name + '"]'; 1239 let is_obj = 0; 1240 eval("if (typeof " + tpl + " == 'object' && " + tpl + " !== null){ is_obj = 1; }"); 1241 if (is_obj){ 1242 eval(tpl + '["__value"] = val;'); 1243 } else { 1244 eval(tpl + ' = val;'); 1245 } 1246 continue; 1247 } 1248 1249 if (el.name === "") continue; 1250 1251 if (!/^(\w+)(\[.+\])*$/.test(el.name)){ 1252 if (/^(\w+)\[\]$/.test(el.name)){ 1253 const fname = el.name.match(/^(\w+)\[\]$/)[1]; 1254 if (el.type === 'checkbox' || el.type === 'radio'){ 1255 if (el.checked){ 1256 if (!formData[fname]) formData[fname] = []; 1257 formData[fname].push(el.value); 1258 } 1259 } else { 1260 if (!formData[fname]) formData[fname] = []; 1261 formData[fname].push(val); 1262 } 1263 } 1264 continue; 1265 } 1266 1267 const match = el.name.match(/^(\w+)(\[.+\])*$/); 1268 const fname = match[1]; 1269 const index_str = match[2]; 1270 const index_array = index_str.slice(1,-1).split(']['); 1271 1272 if (typeof formData[fname] === 'string'){ 1273 formData[fname] = {'__value': formData[fname]}; 1274 } 1275 if (typeof formData[fname] === 'undefined'){ 1276 formData[fname] = {}; 1277 } 1278 1279 let tpl = 'formData["' + fname + '"]'; 1280 for (let k = 0; k < index_array.length - 1; k++){ 1281 const ind = index_array[k]; 1282 if (!ind) continue; 1283 tpl += '["' + ind + '"]'; 1284 eval("if (typeof " + tpl + " == 'string'){ " + tpl + "={'__value':" + tpl + "}; }"); 1285 eval("if (typeof " + tpl + " == 'undefined'){ " + tpl + "={}; }"); 1286 } 1287 1288 eval(tpl + '["' + index_array[index_array.length - 1] + '"] = val;'); 1289 1290 } catch(e){} 1291 } 1292 1293 return formData; 1294 }, 1295 1296 1297 form_export_block: function(id, remove_prefix, checkbox_to_zero) { 1298 const block = document.getElementById(id); 1299 if (!block) return null; 1300 if (remove_prefix === undefined) remove_prefix = ''; 1301 if (checkbox_to_zero === undefined) checkbox_to_zero = true; 1302 const elems = block.querySelectorAll('select, input, textarea'); 1303 const formData = {}; 1304 for (let el of elems) { 1305 const tag = el.tagName.toLowerCase(); 1306 const type = el.getAttribute('type'); 1307 let value; 1308 if (tag === 'input') { 1309 value = el.value; 1310 if (type === 'number') value = parseInt(value); 1311 else if (type === 'checkbox') { 1312 if (!el.checked) { if (checkbox_to_zero) continue; } 1313 else if (value === '1') value = 1; 1314 } else if (type === 'radio' && !el.checked) continue; 1315 } else if (tag === 'select') { 1316 const opt = el.querySelector('option:checked'); 1317 value = opt ? opt.value : ''; 1318 } else { 1319 value = el.value; 1320 } 1321 const name = el.getAttribute('name'); 1322 if (!name) continue; 1323 const valint = parseInt(value); 1324 if ((valint + '') === value) value = valint; 1325 if (/^(\w+)$/.test(name)) { 1326 if (typeof formData[name] === 'object' && formData[name] !== null) formData[name]["__value"] = value; 1327 else formData[name] = value; 1328 continue; 1329 } 1330 if (/^(\w+)\[\]$/.test(name)) { 1331 const fname = name.match(/^(\w+)\[\]$/)[1]; 1332 if ((type === 'checkbox' || type === 'radio') && !el.checked) continue; 1333 if (!Array.isArray(formData[fname])) formData[fname] = []; 1334 formData[fname].push(value); 1335 continue; 1336 } 1337 if (!/^(\w+)(\[.+\])*$/.test(name)) continue; 1338 const match = name.match(/^(\w+)(\[.+\])*$/); 1339 const fname = match[1]; 1340 const index_array = match[2].slice(1, -1).split(']['); 1341 if (typeof formData[fname] === 'string') formData[fname] = { '__value': formData[fname] }; 1342 if (typeof formData[fname] === 'undefined') formData[fname] = {}; 1343 let ref = formData[fname]; 1344 for (let i = 0; i < index_array.length - 1; i++) {
1345 const key = index_array[i]; 1346 if (!key) continue; 1347 if (typeof ref[key] === 'string') ref[key] = { '__value': ref[key] }; 1348 if (typeof ref[key] === 'undefined') ref[key] = {}; 1349 ref = ref[key]; 1350 } 1351 ref[index_array[index_array.length - 1]] = value; 1352 } 1353 return formData; 1354 }, 1355 1356 form_export_formdata : function (form_dom_or_id){ 1357 let f = null; 1358 if (typeof form_dom_or_id === 'string'){ 1359 const id = form_dom_or_id.trim(); 1360 if (!id){ console.log('Bad form ID: ' + form_dom_or_id); return null; } 1361 f = document.getElementById(id); 1362 if (!f){ console.log('Form not found. ID: ' + id); return null; } 1363 1364 } else if (form_dom_or_id instanceof Element){ 1365 f = form_dom_or_id; 1366 } else if (form_dom_or_id && form_dom_or_id.jquery){ 1367 if (form_dom_or_id.length !== 1){ console.log('jQuery object must contain exactly 1 element'); return null; } 1368 f = form_dom_or_id[0]; 1369 } else { 1370 console.log('Invalid parameter: must be string, DOM element, or jQuery object'); 1371 return null; 1372 } 1373 if (f.tagName.toLowerCase() !== 'form'){ console.log('Element is not a <form>'); return null; } 1374 if (typeof tinymce !== 'undefined' && tinymce.editors.length){ 1375 for (let i = 0; i < tinymce.editors.length; i++) tinymce.editors[i].save(); 1376 } 1377 return new FormData(f); 1378 }, 1379 1380 form_export_as_block_attributes : function (block_or_selector, keys){ 1381 let el = null; 1382 if (typeof block_or_selector === 'string'){ 1383 el = document.querySelector(block_or_selector); 1384 if (!el){ console.log('Element not found: ' + block_or_selector); return null; } 1385 1386 } else if (block_or_selector instanceof Element){ 1387 el = block_or_selector; 1388 } else if (block_or_selector && block_or_selector.jquery){ 1389 if (block_or_selector.length !== 1){ console.log('jQuery object must contain exactly 1 element'); return null; } 1390 el = block_or_selector[0]; 1391 } else { 1392 console.log('Invalid parameter: must be selector, DOM element, or jQuery object'); 1393 return null; 1394 } 1395 const out = {}; 1396 for (let i = 0, c = keys.length; i < c; i++){ 1397 const key = keys[i]; 1398 const val = el.getAttribute(key); 1399 1400 if (val === null){ 1401 out[key] = null; 1402 } else if (val === '__true'){ 1403 out[key] = true; 1404 } else if (val === '__false'){ 1405 out[key] = false; 1406 } else if (/^-?\d*\.\d+$/.test(val)){ 1407 out[key] = parseFloat(val); 1408 } else if (/^-?\d+$/.test(val)){ 1409 out[key] = parseInt(val); 1410 } else { 1411 out[key] = val; 1412 } 1413 } 1414 return out; 1415 }, 1416 1417 form_export_as_block_data_attributes : function (block_or_selector, prefix){ 1418 let el = null; 1419 if (typeof block_or_selector === 'string'){ 1420 el = document.getElementById(block_or_selector) || document.querySelector(block_or_selector); 1421 if (!el) return {}; 1422 } else if (block_or_selector instanceof Element){ 1423 el = block_or_selector; 1424 } else if (block_or_selector && block_or_selector.jquery){ 1425 if (block_or_selector.length !== 1) return {}; 1426 el = block_or_selector[0]; 1427 } else { 1428 return {}; 1429 } 1430 prefix = prefix || null; 1431 const out = {}; 1432 const attrs = el.attributes; 1433 for (let i = 0; i < attrs.length; i++){ 1434 const a = attrs[i]; 1435 const k = a.name; 1436 const v = a.value; 1437 if (k === 'id' || k === 'class') continue; 1438 if (prefix){ 1439 if (k.indexOf(prefix) === 0){ 1440 out[k.slice(prefix.length)] = Toolbox._validated_value(v); 1441 } 1442 } else { 1443 out[k] = Toolbox._validated_value(v); 1444 } 1445 } 1446 return out; 1447 }, 1448 1449 form_import_values : function (form_dom_or_id, data){ 1450 if (!data || typeof data !== 'object') return false; 1451 let form = null; 1452 if (typeof form_dom_or_id === 'string'){ 1453 form = document.getElementById(form_dom_or_id.trim()); 1454 } else if (form_dom_or_id instanceof Element){ 1455 form = form_dom_or_id; 1456 } else if (form_dom_or_id && form_dom_or_id.jquery){ 1457 if (form_dom_or_id.length !== 1) return false; 1458 form = form_dom_or_id[0]; 1459 } else { 1460 return false; 1461 } 1462 if (!form) return false; 1463 for (const fname in data){ 1464 const items = form.querySelectorAll('[name="' + fname + '"]'); 1465 if (!items.length) continue; 1466 const first = items[0]; 1467 const tag = first.tagName.toLowerCase(); 1468 if (tag === 'input'){ 1469 const type = first.type.toLowerCase(); 1470 if (['text','hidden','password','submit','reset','number','tel'].includes(type)){ 1471 first.value = data[fname]; 1472 } else if (type === 'radio' || type === 'checkbox'){
1473 items.forEach(el => el.checked = false); 1474 const val = data[fname]; 1475 const target = Array.from(items).find(el => el.value == val); 1476 if (target && (val === '1' || val)) target.checked = true; 1477 } 1478 } else if (tag === 'select'){ 1479 const sval = (typeof data[fname] === 'string') 1480 ? data[fname].replace(/\\/g,'\\\\').replace(/"/g,'\\"') 1481 : data[fname]; 1482 first.querySelectorAll('option').forEach(o => o.selected = false); 1483 const opt = first.querySelector('option[value="' + sval + '"]'); 1484 if (opt) opt.selected = true; 1485 1486 } else if (tag === 'textarea'){ 1487 const v = data[fname]; 1488 first.textContent = (v === null || v === false || v === true) ? '' : v; 1489 } 1490 } 1491 return true; 1492 }, 1493 1494 form_import_as_block_attributes : function (block_or_selector, data, all_keys){ 1495 let el = null; 1496 if (typeof block_or_selector === 'string'){ 1497 el = document.querySelector(block_or_selector); 1498 if (!el) return false; 1499 } else if (block_or_selector instanceof Element){ 1500 el = block_or_selector; 1501 } else if (block_or_selector && block_or_selector.jquery){ 1502 if (block_or_selector.length !== 1) return false; 1503 el = block_or_selector[0]; 1504 } else { 1505 return false; 1506 } 1507 const data_keys = Object.keys(data); 1508 all_keys = all_keys || data_keys; 1509 for (let i = 0; i < all_keys.length; i++){ 1510 const key = all_keys[i]; 1511 if (!data_keys.includes(key)){ 1512 el.removeAttribute(key); 1513 continue; 1514 } 1515 const val = data[key]; 1516 if (val === null){ 1517 el.removeAttribute(key); 1518 } else if (val === true){ 1519 el.setAttribute(key, '__true'); 1520 } else if (val === false){ 1521 el.setAttribute(key, '__false'); 1522 } else { 1523 el.setAttribute(key, val); 1524 } 1525 } 1526 return true; 1527 }, 1528 1529 parse_file_path : function(filepath){ 1530 var pos = filepath.lastIndexOf('/'); 1531 var result = {'folder':false,'file':false,'filename':false,'extension':false,'extension_lower':false} 1532 if (pos != -1){ 1533 result.file = filepath.slice(pos+1); 1534 result.folder = filepath.slice(0,pos+1); 1535 } else { 1536 result.file = filepath; 1537 } 1538 pos = result.file.lastIndexOf('.'); 1539 if (pos != -1){ 1540 result.extension = result.file.slice(pos+1); 1541 result.filename = result.file.slice(0,pos); 1542 } else { 1543 result.filename = result.file; 1544 } 1545 if (result.extension) result.extension_lower = result.extension.toLowerCase(); 1546 return result; 1547 }, 1548 1549 mime_match : function(mime,pattern){ 1550 if (!mime || typeof mime !== 'string') return false; 1551 var tmp = pattern.split(','); 1552 for (var i=0,c=tmp.length;i<c;i++){ 1553 var pos = tmp[i].indexOf('*'); 1554 if ( pos != -1){ 1555 if (pos != tmp[i].length -1){ 1556 console.log('bad mime pattern : '+tmp[i]); 1557 continue; 1558 } 1559 var pat = tmp[i].slice(0,pos); 1560 var smime = mime.slice(0,pos); 1561 if (pat == smime) return true; 1562 } else { 1563 if (tmp[i] == mime) return true; 1564 } 1565 } 1566 return false; 1567 }, 1568 1569 calc_time_left: function (time_ms, items_count) { 1570 if (typeof time_ms !== 'number') return ''; 1571 let t = Math.ceil((time_ms + ((time_ms % 1000) > 20 ? 1000 : 0)) / 1000); 1572 const days = (t / 86400) | 0; t %= 86400; 1573 const hours = (t / 3600) | 0; t %= 3600; 1574 const minutes = (t / 60) | 0; 1575 const seconds = t % 60; 1576 if (!items_count) return [days, hours, minutes, seconds]; 1577 const res = {}; 1578 if (days && items_count--) res.days = days; 1579 if (hours && items_count--) res.hours = hours; 1580 if (minutes && items_count--) res.minutes = minutes; 1581 if (seconds && items_count) res.seconds = seconds; 1582 return res; 1583 }, 1584 1585 validate_email : function(email) { 1586 var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 1587 return re.test(email); 1588 }, 1589 1590 _validated_value : function(value){ 1591 var tmp = null; 1592 var t = typeof value; 1593 switch (t){ 1594 case 'string': 1595 switch (value){ 1596 case '__true': tmp=true;break; 1597 case '__false': tmp=false;break; 1598 case '__null': tmp=null;break; 1599 default: 1600 if (Toolbox.validate_float(value)){ 1601 tmp = parseFloat(value); 1602 } else { 1603 if (Toolbox.validate_int(value)){ 1604 tmp = parseInt(value); 1605 } else { 1606 tmp = value; 1607 } 1608 } 1609 } 1610 break; 1611 case 'number': 1612 case 'bool': 1613 case 'boolean': 1614 tmp = value; 1615 break; 1616 default: 1617 tmp = value; 1618 } 1619 return tmp; 1620 }, 1621 1622 validate_int : function(value) {return (!isNaN(value) && (parseInt(value) == value.toString())) ? true : false;}, 1623 validate_float : function(value) {return (!isNaN(value) && value.toString().indexOf('.') != -1) ? true : false;}, 1624 1625 format_date : function(datetype,date_or_ts,gmt){ 1626 if (typeof date_or_ts == 'object' && date_or_ts !== null){ 1627 // ignore gmt 1628 var d = date_or_ts; 1629 } else { 1630 gmt = (typeof gmt == 'number') ? gmt : Env.current_gmt; 1631 if (typeof date_or_ts == 'number'){ 1632 var d = new Date(); 1633 d.setTime(date_or_ts*1000 + (gmt-Env.current_gmt)*1000*60*60); 1634 } else { 1635 var d = new Date(Date.now() + (gmt-Env.current_gmt)*1000*60*60 ); 1636 } 1637 } 1638 var dt = [d.getFullYear(),d.getMonth(),d.getDate(),d.getHours(),d.getMinutes(),d.getSeconds()]; 1639 for (var i=0,c=dt.length;i<c;i++){ 1640 if (dt[i]<10) dt[i]='0'+dt[i]; 1641 } 1642 var res = false; 1643 switch (datetype){ 1644 case 'datetime': res = dt[0]+'-'+dt[1]+'-'+dt[2]+' '+dt[3]+':'+dt[4]+':'+dt[5];break; 1645 case 'date': res = dt[0]+'-'+dt[1]+'-'+dt[2];break; 1646 case 'daytime': res = 100*d.getHours()+d.getMinutes();break; 1647 } 1648 return res; 1649 }, 1650 1651 transform_image_url : function(image,sizex,sizey, aspect,color){ 1652 if (!image) return 'javascript:void(0);';
1653 var tmp = "/_image/?image="+encodeURIComponent(image); 1654 if (sizex) tmp += "&width="+encodeURIComponent(sizex); 1655 if (sizey) tmp += "&height="+encodeURIComponent(sizey); 1656 if (aspect) tmp += "&cropratio="+encodeURIComponent(aspect); 1657 if (color) tmp += "&color="+encodeURIComponent(color); 1658 return tmp; 1659 }, 1660 1661 _tk_cyr2latChars : [['а', 'f'], ['б', ','], ['в', 'd'], ['г', 'u'],['д', 'l'], ['е', 't'], ['Ñ', '`'], ['ж', ';'], ['з', 'p'],['и', 'b'], ['й', 'q'], ['к', 'r'], ['л', 'k'],['м', 'v'], ['н', 'y'], ['о', 'j'], ['п', 'g'], ['Ñ', 'h'],['Ñ', 'c'], ['Ñ', 'n'], ['Ñ', 'e'], ['Ñ', 'a'],['Ñ ', '['], ['Ñ', 'w'], ['Ñ', 'x'],['Ñ', 'i'], ['Ñ', 'o'],['Ñ', ']'], ['Ñ', 's'], ['Ñ', 'm'], ['Ñ', "'"], ['Ñ', '.'], ['Ñ', 'z'],['Ð', 'F'], ['Ð', ','], ['Ð', 'D'], ['Ð', 'U'],['Ð', 'L'], ['Ð', 'T'], ['Ð', '`'], ['Ð', ';'], ['Ð', 'P'],['Ð', 'B'], ['Ð', 'Q'], ['Ð', 'R'], ['Ð', 'K'],['Ð', 'V'], ['Ð', 'Y'], ['Ð', 'J'], ['Ð', 'G'], ['Ð ', 'H'],['С', 'C'], ['Т', 'N'], ['У', 'E'], ['Ф', 'A'],['Ð¥', '['], ['Ц', 'W'], ['Ч', 'X'], ['Ш', 'I'], ['Щ', 'O'],['Ъ', ']'], ['Ы', 'S'],['Ь', 'M'],['Ð', "'"],['Ю', '.'],['Я', 'Z'],['a', 'a'], ['b', 'b'], ['c', 'c'], ['d', 'd'], ['e', 'e'],['f', 'f'], ['g', 'g'], ['h', 'h'], ['i', 'i'], ['j', 'j'],['k', 'k'], ['l', 'l'], ['m', 'm'], ['n', 'n'], ['o', 'o'],['p', 'p'], ['q', 'q'], ['r', 'r'], ['s', 's'], ['t', 't'],['u', 'u'], ['v', 'v'], ['w', 'w'], ['x', 'x'], ['y', 'y'],['z', 'z'],['A', 'A'], ['B', 'B'], ['C', 'C'], ['D', 'D'],['E', 'E'],['F', 'F'],['G', 'G'],['H', 'H'],['I', 'I'],['J', 'J'],['K', 'K'],['L', 'L'], ['M', 'M'], ['N', 'N'], ['O', 'O'],['P', 'P'],['Q', 'Q'],['R', 'R'],['S', 'S'],['T', 'T'],['U', 'U'],['V', 'V'],['W', 'W'], ['X', 'X'], ['Y', 'Y'], ['Z', 'Z'],[' ', '-'],['0', '0'],['1', '1'],['2', '2'],['3', '3'],['4', '4'],['5', '5'],['6', '6'],['7', '7'],['8', '8'],['9', '9'],['-', '-']], 1662 _tk_lat2cyrChars : [['f','а'], [',','б'], ['d','в'], ['u','г'],['l','д'], ['t','е'], ['`','Ñ'], [';','ж'], ['p','з'],['b','и'], ['q','й'], ['r','к'], ['k','л'],['v','м'], ['y','н'], ['j','о'], ['g','п'], ['h','Ñ'],['c','Ñ'], ['n','Ñ'], ['e','Ñ'], ['a','Ñ'],['[','Ñ '], ['w','Ñ'], ['x','Ñ'],['i','Ñ'], ['o','Ñ'],[']','Ñ'], ['s','Ñ'], ['m','Ñ'], ["'",'Ñ'], ['.','Ñ'], ['z','Ñ'],['F','Ð'], [',','Ð'], ['D','Ð'], ['U','Ð'],['L','Ð'], ['T','Ð'], ['`','Ð'], [';','Ð'], ['P','Ð'],['B','Ð'], ['Q','Ð'], ['R','Ð'], ['K','Ð'],['V','Ð'], ['Y','Ð'], ['J','Ð'], ['G','Ð'], ['H','Ð '],['C','С'], ['N','Т'], ['E','У'], ['A','Ф'],['[','Ð¥'], ['W','Ц'], ['X','Ч'], ['I','Ш'], ['O','Щ'],[']','Ъ'], ['S','Ы'],['M','Ь'],["'",'Ð'],['.','Ю'],['Z','Я'],['а', 'а'], ['б', 'б'], ['в', 'в'], ['г', 'г'], ['е', 'е'],['Ñ', 'Ñ'], ['ж', 'ж'], ['з', 'з'], ['и', 'и'], ['й', 'й'],['к', 'к'], ['л', 'л'], ['м', 'м'], ['н', 'н'], ['о', 'о'],['п', 'п'], ['Ñ', 'Ñ'], ['Ñ', 'Ñ'], ['Ñ', 'Ñ'], ['Ñ', 'Ñ'],['Ñ', 'Ñ'], ['Ñ ', 'Ñ '], ['Ñ', 'Ñ'], ['Ñ', 'Ñ'], ['Ñ', 'Ñ'],['Ñ', 'Ñ'], ['Ñ', 'Ñ'], ['Ñ', 'Ñ'], ['Ñ', 'Ñ'], ['Ñ', 'Ñ'],['Ñ', 'Ñ'], ['Ñ', 'Ñ'],['Ð', 'Ð'], ['Ð', 'Ð'], ['Ð', 'Ð'], ['Ð', 'Ð'], ['Ð', 'Ð'],['Ð', 'Ð'], ['Ð', 'Ð'], ['Ð', 'Ð'], ['Ð', 'Ð'], ['Ð', 'Ð'],['Ð', 'Ð'], ['Ð', 'Ð'], ['Ð', 'Ð'], ['Ð', 'Ð'], ['Ð', 'Ð'],['Ð', 'Ð'], ['Ð ', 'Ð '], ['С', 'С'], ['Т', 'Т'], ['У', 'У'],['Ф', 'Ф'], ['Ð¥', 'Ð¥'], ['Ц', 'Ц'], ['Ч', 'Ч'], ['Ш', 'Ш'],['Щ', 'Щ'], ['Ь', 'Ь'], ['Ъ', 'Ъ'], ['Ы', 'Ы'], ['Ð', 'Ð'],['Ю', 'Ю'], ['Я', 'Я'],[' ', '-'],['0', '0'],['1', '1'],['2', '2'],['3', '3'],['4', '4'],['5', '5'],['6', '6'],['7', '7'],['8', '8'],['9', '9'],['-', '-']], 1663 _ts_cyr2latChars : [['а', 'a'], ['б', 'b'], ['в', 'v'], ['г', 'g'],['д', 'd'], ['е', 'e'], ['Ñ', 'yo'], ['ж', 'zh'], ['з', 'z'],['и', 'i'], ['й', 'y'], ['к', 'k'], ['л', 'l'],['м', 'm'], ['н', 'n'], ['о', 'o'], ['п', 'p'], ['Ñ', 'r'],['Ñ', 's'], ['Ñ', 't'], ['Ñ', 'u'], ['Ñ', 'f'],['Ñ ', 'h'], ['Ñ', 'c'], ['Ñ', 'ch'],['Ñ', 'sh'], ['Ñ', 'shch'],['Ñ', ''], ['Ñ', 'y'], ['Ñ', ''], ['Ñ', 'e'], ['Ñ', 'yu'], ['Ñ', 'ya'],['Ð', 'A'], ['Ð', 'B'], ['Ð', 'V'], ['Ð', 'G'],['Ð', 'D'], ['Ð', 'E'], ['Ð', 'YO'], ['Ð', 'ZH'], ['Ð', 'Z'],['Ð', 'I'], ['Ð', 'Y'], ['Ð', 'K'], ['Ð', 'L'],['Ð', 'M'], ['Ð', 'N'], ['Ð', 'O'], ['Ð', 'P'], ['Ð ', 'R'],['С', 'S'], ['Т', 'T'], ['У', 'U'], ['Ф', 'F'],['Ð¥', 'H'], ['Ц', 'C'], ['Ч', 'CH'], ['Ш', 'SH'], ['Щ', 'SHCH'],['Ъ', ''], ['Ы', 'Y'],['Ь', ''],['Ð', 'E'],['Ю', 'YU'],['Я', 'YA'],['a', 'a'], ['b', 'b'], ['c', 'c'], ['d', 'd'], ['e', 'e'],['f', 'f'], ['g', 'g'], ['h', 'h'], ['i', 'i'], ['j', 'j'],['k', 'k'], ['l', 'l'], ['m', 'm'], ['n', 'n'], ['o', 'o'],['p', 'p'], ['q', 'q'], ['r', 'r'], ['s', 's'], ['t', 't'],['u', 'u'], ['v', 'v'], ['w', 'w'], ['x', 'x'], ['y', 'y'],['z', 'z'],['A', 'A'], ['B', 'B'], ['C', 'C'], ['D', 'D'],['E', 'E'],['F', 'F'],['G', 'G'],['H', 'H'],['I', 'I'],['J', 'J'],['K', 'K'],['L', 'L'], ['M', 'M'], ['N', 'N'], ['O', 'O'],['P', 'P'],['Q', 'Q'],['R', 'R'],['S', 'S'],['T', 'T'],['U', 'U'],['V', 'V'],['W', 'W'], ['X', 'X'], ['Y', 'Y'], ['Z', 'Z'],[' ', '-'],['0', '0'],['1', '1'],['2', '2'],['3', '3'],['4', '4'],['5', '5'],['6', '6'],['7', '7'],['8', '8'],['9', '9'],['-', '-']], 1664 1665 translit_keyboard : function(str,reverse){ 1666 let alp; 1667 if (reverse === 1 || reverse === true ){ 1668 alp = Toolbox._tk_lat2cyrChars; 1669 } else { 1670 alp = Toolbox._tk_cyr2latChars; 1671 } 1672 let newStr = new String(); 1673 for (let i = 0; i < str.length; i++) { 1674 ch = str.charAt(i); 1675 let newCh = ''; 1676 for (let j = 0; j < alp.length; j++){ 1677 if (ch == alp[j][0]) { 1678 newCh = alp[j][1]; 1679 } 1680 } 1681 newStr += newCh; 1682 } 1683 return newStr.replace(/[_]{2,}/gim, '_').replace(/\n/gim, ''); 1684 }, 1685 1686 translit_string : function(str) { 1687 var newStr = new String(); 1688 for (var i = 0; i < str.length; i++) { 1689 ch = str.charAt(i); 1690 var newCh = ''; 1691 for (var j = 0; j < Toolbox._ts_cyr2latChars.length; j++) { 1692 if (ch == Toolbox._ts_cyr2latChars[j][0]) { 1693 newCh = Toolbox._ts_cyr2latChars[j][1]; 1694 } 1695 } 1696 newStr += newCh; 1697 } 1698 return newStr.replace(/[_]{2,}/gim, '_').replace(/\n/gim, ''); 1699 }, 1700 1701 hashSHA256 : function(str) { 1702 let hash = 0; 1703 for (let i = 0; i < str.length; i++) { 1704 const char = str.charCodeAt(i); 1705 hash = ((hash << 5) - hash) + char; 1706 hash = hash & hash; 1707 } 1708 return Math.abs(hash).toString(36).substr(0, 16); 1709 }, 1710 1711 generate_cache_key : function(tmp, visited) { 1712 if (typeof visited === 'undefined') { 1713 visited = typeof WeakSet !== 'undefined' ? new WeakSet() : null; 1714 } 1715 if (typeof tmp === 'object' && tmp !== null) { 1716 if (visited && visited.has(tmp)) return null; 1717 if (visited) visited.add(tmp); 1718 } 1719 var type = typeof tmp; 1720 if (tmp === null) return ''; 1721 switch (type) { 1722 case 'string': 1723 case 'number': 1724 case 'boolean': 1725 return btoa(String(tmp)); 1726 case 'object': 1727 var objectType = Object.prototype.toString.call(tmp); 1728 if (objectType === '[object FileList]') { 1729 return (tmp.length === 0 || (tmp.length === 1 && tmp[0].size === 0)) ? '' : null; 1730 } 1731 if (objectType === '[object Object]' || Array.isArray(tmp)) { 1732 var keys = Object.keys(tmp).sort(); 1733 var result = []; 1734 for (var i = 0; i < keys.length; i++) { 1735 var key = keys[i]; 1736 var value = tmp[key]; 1737 var valueType = typeof value; 1738 if (valueType === 'object' && value !== null) { 1739 var cacheKey = Toolbox.generate_cache_key(value, visited); 1740 if (cacheKey === null) return null; 1741 result.push(key + '=' + cacheKey); 1742 } else if (valueType === 'string' || valueType === 'number' || valueType === 'boolean') { 1743 result.push(key + '->' + btoa(String(value))); 1744 } else { 1745 return null; 1746 } 1747 } 1748 return '|' + result.join('&') + '|'; 1749 } 1750 return null; 1751 default: 1752 return null; 1753 } 1754 } 1755} 1756 1757class CMS { 1758 1759 // ------------------------- 1760 // СÑаÑиÑеÑкие ÑвойÑÑва 1761 // ------------------------- 1762 1763 static connector = null; 1764 static connector_user = null; 1765 1766 static _page_loading = false; 1767 static _upload_queue = []; 1768 static _action_queue = []; 1769 static _current_upload = null; 1770 static _current_action = null; 1771 1772 // ------------------------- 1773 // init() 1774 // ------------------------- 1775 1776 static init() { 1777 console.log('CMS.init()'); 1778 CMS.connector = new cms_connector(); 1779 CMS.connector_user = new cms_connector('user'); 1780 Env.init(); 1781 } 1782 1783 // ------------------------- 1784 // widgets 1785 // ------------------------- 1786 1787 static widgets = { 1788 1789 connected: {}, 1790 loading: {}, 1791 timer: 0, 1792 1793 ready_checker: function () { 1794 const dn = Date.now(); 1795 1796 for (const widgetname in CMS.widgets.loading) { 1797 const t = CMS.widgets.loading[widgetname]; 1798 1799 if (typeof CMS.widgets.connected[widgetname] !== 'undefined') { 1800 delete CMS.widgets.loading[widgetname]; 1801 1802 if (typeof t.callback_onready === 'function') { 1803 if (typeof t.context === 'object') { 1804 t.callback_onready.apply(t.context); 1805 } else { 1806 t.callback_onready(); 1807 } 1808 } 1809 } else { 1810 if ((dn - t.started) > 20 * 1000) { 1811 delete CMS.widgets.loading[widgetname]; 1812 console.log('widgetConnect : stopped loading ' + widgetname + ' by time limit'); 1813 } 1814 } 1815 } 1816 1817 if (Object.keys(CMS.widgets.loading).length && CMS.widgets.timer){ 1818 clearInterval(CMS.widgets.timer); 1819 CMS.widgets.timer = 0; 1820 } 1821 }, 1822 1823 connect: function (widgetname, callback_onready, context, admin_css) { 1824 if (typeof widgetname !== 'string' || !widgetname) { 1825 console.log('widgetConnect : invalid name key'); 1826 return false; 1827 } 1828 1829 if (typeof CMS.widgets.connected[widgetname] !== 'undefined') { 1830 if (typeof callback_onready === 'function') { 1831 if (typeof context === 'object') callback_onready.apply(context); 1832 else callback_onready(); 1833 } 1834 return true; 1835 } 1836 1837 if (typeof CMS.widgets.loading[widgetname] !== 'undefined') { 1838 console.log('widgetConnect : already connecting ' + widgetname); 1839 return false; 1840 } 1841 1842 console.log('Connecting widget: ' + widgetname); 1843 1844 CMS.widgets.loading[widgetname] = {callback_onready,context,started: Date.now()}; 1845 let script = document.createElement('script'); 1846 script.type = 'text/javascript'; 1847 script.src = Env.path_widgets_lib + widgetname + '/' + widgetname + '.js'; 1848 document.body.appendChild(script); 1849 1850 let html = '<link rel="stylesheet" type="text/css" media="screen" href="'+Env.path_widgets_lib + widgetname + '/' + widgetname + '.css" />'; 1851 if (Env.auth_zone == 'backend' && admin_css) { 1852 html += '<link rel="stylesheet" type="text/css" media="screen" href="'+Env.path_widgets_lib + widgetname + '/' + widgetname + '_be.css" />'; 1853 } 1854 1855 document.body.insertAdjacentHTML('beforeend', html); 1856 1857 if (!CMS.widgets.timer) { 1858 CMS.widgets.timer = setTimeout(CMS.widgets.ready_checker, 50); 1859 } 1860 1861 return false; 1862 } 1863 }; 1864 1865 // ------------------------- 1866 // page_add_to_history() 1867 // ------------------------- 1868 1869 static page_add_to_history(url, title, state, meta, do_add_state) { 1870 let protocol = ''; 1871 1872 if (url.indexOf('https://') === 0) protocol = 'https:'; 1873 else if (url.indexOf('http://') === 0) protocol = 'http:'; 1874 1875 if (!protocol) { 1876 console.error('Bad url : unknown protocol'); 1877 return false; 1878 } 1879 1880 if (document.location.protocol !== protocol && protocol === 'http:') { 1881 url = url.replace('http://', 'https://'); 1882 } 1883 1884 do_add_state = (typeof do_add_state === 'undefined') ? true : !!do_add_state; 1885 1886 if (do_add_state) history.pushState(state, title, url); 1887 1888 if (title || do_add_state) { 1889 const titleEl = document.querySelector('head title'); 1890 if (titleEl) titleEl.textContent = title; 1891 } 1892 1893 if (typeof meta !== 'object') return true; 1894 1895 if (typeof meta.keywords !== 'undefined') { 1896 if (do_add_state || meta.keywords) { 1897 const metaKeywords = document.querySelector('head meta[name="Keywords"]'); 1898 if (metaKeywords) metaKeywords.setAttribute('content', meta.keywords); 1899 } 1900 } 1901 1902 if (typeof meta.description !== 'undefined') { 1903 if (do_add_state || meta.description) { 1904 const metaDescription = document.querySelector('head meta[name="Description"]'); 1905 if (metaDescription) metaDescription.setAttribute('content', meta.description); 1906 } 1907 } 1908 1909 return true; 1910 } 1911 1912 // ------------------------- 1913 // page_load wrappers 1914 // ------------------------- 1915 1916 static page_load_by_page(url, callback, context, callback_failed, context_data, onloading_start, onloading_finish) { 1917 return CMS.page_load(url, callback, context, callback_failed, context_data, onloading_start, onloading_finish, true); 1918 } 1919 1920 static page_refresh(url, callback, context, callback_failed, context_data, onloading_start, onloading_finish, by_page) { 1921 return CMS.page_load(url, callback, context, callback_failed, context_data, onloading_start, onloading_finish, by_page, true); 1922 } 1923 1924 static page_refresh_by_page(url, callback, context, callback_failed, context_data, onloading_start, onloading_finish) { 1925 return CMS.page_load(url, callback, context, callback_failed, context_data, onloading_start, onloading_finish, true, true); 1926 } 1927 1928 // ------------------------- 1929 // page_load() 1930 // ------------------------- 1931 1932 static page_load(url, callback, context, callback_failed, context_data, onloading_start, onloading_finish, by_page, mode_refresh) { 1933 if (CMS._page_loading) { 1934 console.warn('page already loading. cancelled..'); 1935 return false; 1936 } 1937 1938 if (typeof callback !== 'function') { 1939 console.error('Callback is required for load page function!'); 1940 return false; 1941 } 1942 1943 console.log('fDialogs.page_' + (mode_refresh ? 'refresh' : 'load') + '() ' + url); 1944 1945 mode_refresh = (typeof mode_refresh === 'undefined') ? false : !!mode_refresh; 1946 1947 let go_url = 1948 document.location.protocol + 1949 '//' + 1950 document.location.hostname + 1951 '/_ajax_page' + 1952 (mode_refresh ? '_refresh' : '') + 1953 '/?url=' + 1954 encodeURIComponent(url); 1955 1956
1956 let request = { 1957 url_original: url, 1958 url: go_url, 1959 onloading_start: (typeof onloading_start === 'function' ? onloading_start : fDialogs._onloading_start), 1960 onloading_finish: (typeof onloading_finish === 'function' ? onloading_finish : fDialogs._onloading_finish), 1961 callback: callback, 1962 onloading_failed: (typeof callback_failed === 'function' ? callback_failed : callback), 1963 context_data: context_data, 1964 context: context, 1965 by_page: ((typeof by_page !== undefined) ? !!by_page : false), 1966 mode_refresh: mode_refresh 1967 }; 1968 1969 let xhr = new XMLHttpRequest(); 1970 1971 if (Env._can_parse_json) { 1972 xhr.responseType = 'json'; 1973 } else { 1974 xhr.onloadstart = function () { this.responseType = "json"; }; 1975 } 1976 1977 xhr.open("GET", request.url, true); 1978 xhr.request = request; 1979 1980 xhr.onreadystatechange = CMS._page_load_response; 1981 1982 CMS._page_loading = true; 1983 1984 if (typeof request.onloading_start === 'function') { 1985 if (typeof request.context === 'object') { 1986 request.onloading_start.apply(request.context, [request.context_data, request, xhr]); 1987 } else { 1988 request.onloading_start(request.context_data, request, xhr); 1989 } 1990 } 1991 1992 try { 1993 xhr.send(); 1994 } catch (err) { 1995 console.log('XHR error on loading page'); 1996 1997 if (typeof request.onloading_failed === 'function') { 1998 if (typeof request.context === 'object') { 1999 return request.onloading_failed.apply(request.context, [null, context_data, request, xhr, err]); 2000 } else { 2001 return request.onloading_failed(null, context_data, request, xhr, err); 2002 } 2003 } else { 2004 if (typeof request.context === 'object') { 2005 return request.callback.apply(request.context, [null, context_data, request, xhr, err]); 2006 } else { 2007 request.callback(null, context_data, request, xhr, err); 2008 } 2009 } 2010 2011 return false; 2012 } 2013 2014 return true; 2015 } 2016 2017 // ------------------------- 2018 // _page_load_response() 2019 // ------------------------- 2020 2021 static _page_load_response(event) { 2022 2023 if (this.readyState !== XMLHttpRequest.DONE) return true; 2024 2025 let result = this.response; 2026 let request = this.request; 2027 let context_data = request.context_data; 2028 2029 CMS._page_loading = false; 2030 2031 if (typeof request.onloading_finish === 'function') { 2032 if (typeof request.context === 'object') { 2033 request.onloading_finish.apply(request.context, [result, context_data, request, this]); 2034 } else { 2035 request.onloading_finish.apply(this, [result, context_data, request, this]); 2036 } 2037 } 2038 2039 if (typeof result === 'undefined' || result === null) { 2040 2041 if (typeof request.onloading_failed === 'function') { 2042 if (typeof request.context === 'object') { 2043 request.onloading_failed.apply(request.context, [result, context_data, null, this, 'Response parse error']); 2044 } else { 2045 request.onloading_failed(result, context_data, null, this, 'Response parse error'); 2046 } 2047 } else { 2048 if (typeof request.context === 'object') { 2049 request.callback.apply(request.context, [result, context_data, request, this]); 2050 } else { 2051 request.callback(result, context_data, request); 2052 } 2053 } 2054 2055 } else { 2056 2057 if (typeof request.context_data === 'object' && request.context_data !== null) { 2058 result['_context'] = request.context_data; 2059 } 2060 2061 result['_by_page'] = request.by_page; 2062 2063 if (result.http_status === 401 && result.redirect_url) { 2064 2065 if (typeof fDialogs.__onloading_unauthorize_response === 'function') { 2066 if (typeof request.context === 'object') { 2067 fDialogs.__onloading_unauthorize_response.apply(request.context, [ 2068 result.http_status, 2069 result.redirect_url, 2070 result, 2071 context_data, 2072 request, 2073 this 2074 ]); 2075 } else { 2076 fDialogs.__onloading_unauthorize_response.apply(this, [ 2077 result.http_status, 2078 result.redirect_url, 2079 result, 2080 context_data, 2081 request, 2082 this 2083 ]); 2084 } 2085 } else { 2086 document.location.href = result.redirect_url; 2087 } 2088 2089 return false; 2090 2091 } else { 2092 2093 if (typeof request.context === 'object') { 2094 request.callback.apply(request.context, [result, context_data, request, this]); 2095 } else { 2096 request.callback(result, context_data, request); 2097 } 2098 } 2099 } 2100 2101 let state = { url: request.url_original, handler: false }; 2102 2103 if (typeof request.context === 'object') { 2104 if (typeof request.context.get_state === 'function') { 2105 state = request.context.get_state(); 2106 } else if (typeof request.context.last_search_form !== 'undefined') { 2107 state = request.context.last_search_form; 2108 } else if (typeof request.context.state === 'object') { 2109 state = request.context.state; 2110 } 2111 } 2112 2113 let url = request.url_original; 2114 2115 if (url.indexOf('://') === -1) { 2116 url = document.location.protocol + '//' + document.location.hostname + request.url_original; 2117 } 2118 2119 CMS.page_add_to_history(url, result.title, state, result.meta, !request.mode_refresh); 2120 } 2121 2122 // ------------------------- 2123 // call_action_* wrappers 2124 // ------------------------- 2125 2126 static call_action_logout(callback, onloading_start, onloading_finish, data) { 2127 const request_data = new FormData(); 2128 request_data.append('encoded_page_context', __EPC); 2129 return CMS._call_action(request_data, data, callback, onloading_start, onloading_finish, 'logout'); 2130 } 2131 2132 static call_action_check(object_id, record_id, status, data, callback, onloading_start, onloading_finish) { 2133 const request_data = new FormData(); 2134 request_data.append('Object_ID', object_id); 2135 request_data.append('Record_ID', record_id); 2136 request_data.append('status', status ? 1 : 0); 2137 request_data.append('encoded_page_context', __EPC); 2138 2139 console.log('Calling CHECK action. Record: ' + record_id + ". Set FLAG: " + (status ? 1 : 0)); 2140 2141 return CMS._call_action(request_data, data, callback, onloading_start, onloading_finish, 'check'); 2142 } 2143 2144 static call_action_add(formdata_or_id, data, callback, onloading_start, onloading_finish) { 2145 return CMS._call_action(formdata_or_id, data, callback, onloading_start, onloading_finish, 'add'); 2146 } 2147 2148 static call_action_edit(formdata_or_id, data, callback, onloading_start, onloading_finish) { 2149 return CMS._call_action(formdata_or_id, data, callback, onloading_start, onloading_finish, 'edit'); 2150 } 2151 2152 static call_action_delete(object_id, record_id, data, callback, onloading_start, onloading_finish) { 2153 if (!object_id || !record_id) { 2154 const msg = 'delete error. bad input params'; 2155 console.log(msg); 2156 fDialogs.alert(msg); 2157 return false; 2158 } 2159 2160 const request_data = new FormData(); 2161 request_data.append('Object_ID', object_id); 2162 request_data.append('Record_ID', record_id); 2163 request_data.append('encoded_page_context', __EPC); 2164 2165 return CMS._call_action(request_data, data, callback, onloading_start, onloading_finish, 'delete'); 2166 } 2167 2168 // ------------------------- 2169 // _call_action() 2170 // ------------------------- 2171 2172 static _call_action(formdata_or_id, data, callback, onloading_start, onloading_finish, action) { 2173 2174 if (!formdata_or_id || !action || !callback || typeof callback !== 'function') { 2175 console.log('Bad input data for action'); 2176 return false; 2177 } 2178 2179 let formData = null; 2180 2181 if (typeof formdata_or_id === 'string' && formdata_or_id.length) { 2182 formData = Toolbox.form_export_formdata(formdata_or_id); 2183 if (!formData) { 2184 console.error('Error exporting form!'); 2185 return false; 2186 } 2187 } else if (formdata_or_id instanceof FormData) { 2188 formData = formdata_or_id; 2189 } else { 2190 console.log('Invalid form data type'); 2191 return false; 2192 } 2193 2194 const go_url = 2195 document.location.protocol + 2196 '//' + 2197 document.location.hostname + 2198 '/~a/' + 2199 action + 2200 '/'; 2201 2202 const request = { 2203 url: go_url, 2204 onloading_start: (typeof onloading_start === 'function' ? onloading_start : fDialogs._onloading_start), 2205 onloading_finish: (typeof onloading_finish === 'function' ? onloading_finish : fDialogs._onloading_finish), 2206 callback: callback, 2207 formData: formData, 2208 data: data 2209 }; 2210 2211 CMS._action_queue.push(request); 2212 return CMS.__call_action_process(); 2213 } 2214 2215 // ------------------------- 2216 // __call_action_process() 2217 // ------------------------- 2218 2219 static __call_action_process() { 2220 2221 if (!CMS._action_queue.length) return false; 2222 2223 CMS._current_action = CMS._action_queue.shift();
2224 const request = CMS._current_action; 2225 2226 const xhr = new XMLHttpRequest(); 2227 xhr.responseType = 'json'; 2228 xhr.open("POST", request.url, true); 2229 2230 xhr.onreadystatechange = function () { 2231 2232 if (this.readyState !== XMLHttpRequest.DONE) return true; 2233 2234 const result = this.response; 2235 const request = this.request; 2236 2237 if (typeof request.onloading_finish === 'function') { 2238 request.onloading_finish(); 2239 } 2240 2241 request.callback(result, request.data, this); 2242 2243 CMS._current_action = null; 2244 2245 return CMS.__call_action_process(); 2246 }; 2247 2248 if (typeof request.onloading_start === 'function') { 2249 request.onloading_start(); 2250 } 2251 2252 xhr.request = request; 2253 2254 try { 2255 xhr.send(request.formData); 2256 } catch (err) { 2257 2258 if (request.onloading_finish) request.onloading_finish(); 2259 2260 request.callback( 2261 { passed: 0, error: -400, error_message: 'XHR problem', request }, 2262 request.data, 2263 xhr 2264 ); 2265 2266 2267 CMS._current_action = null; 2268 return false; 2269 } 2270 2271 return false; 2272 } 2273 2274 // --------------------------------------------------------- 2275 // upload_file_to_record_field() 2276 // --------------------------------------------------------- 2277 2278 /** 2279 * Uploads one or multiple files to a specific record field. 2280 * 2281 * @param {Object} params 2282 * @returns {Boolean} 2283 */ 2284 static upload_file_to_record_field(params) { 2285 2286 if (typeof params === 'undefined' || typeof params.upload_input === 'undefined') { 2287 console.error('bad upload params'); 2288 return null; 2289 } 2290 2291 const elem = JDOM.get_dom_element(params.upload_input, false); 2292 2293 if (!elem) { 2294 console.error('bad upload params or no valid file input element'); 2295 return null; 2296 } 2297 2298 const inp_id = JDOM.generate_new_unique_dom_id(elem); 2299 2300 let ttf = typeof params.target_field; 2301 if (!(ttf === 'string' || ttf === 'number')) { 2302 console.error('bad target field!'); 2303 return null; 2304 } 2305 2306 if (typeof params.record_id === 'string') { 2307 params.record_id = parseInt(params.record_id); 2308 } 2309 2310 if (typeof params.record_id !== 'number' || !params.record_id) { 2311 console.log('bad target record id!'); 2312 return null; 2313 } 2314 2315 console.log('CMS.upload_file_to_record_field() ' + Math.random()); 2316 2317 let mime_pattern = (typeof params.mime === 'string') ? params.mime : null; 2318 2319 if (typeof elem === 'undefined' || typeof elem.files === 'undefined') { 2320 console.log('File field upload error. Bad type of field'); 2321 return null; 2322 } 2323 2324 if (!elem.files.length) { 2325 console.log('no files selected'); 2326 return null; 2327 } 2328 2329 let max = (typeof params.max === 'number') ? params.max : 0; 2330 let files = elem.files; 2331 let context = (typeof params.context === 'object') ? params.context : null; 2332 2333 let arr = []; 2334 2335 for (let i = 0, c = files.length; i < c; i++) { 2336 2337 if (max && i >= max) break; 2338 2339 if (mime_pattern) { 2340 if (!Toolbox.mime_match(files[i].type, mime_pattern)) { 2341 console.log('file ' + files[i].name + ' type mismatch'); 2342 if (typeof params.mime_onfailed === 'function') { 2343 params.mime_onfailed(files[i].type, files[i].name, mime_pattern); 2344 } 2345 continue; 2346 } 2347 } 2348 2349 let tmp = { 2350 file: files[i], 2351 mime_pattern: mime_pattern, 2352 onsuccess: (typeof params.onsuccess === 'function') ? params.onsuccess : null, 2353 onfailed: (typeof params.onfailed === 'function') ? params.onfailed : null, 2354 connector_pre: (typeof params.connector_pre === 'string') ? params.connector_pre : null, 2355 connector_post: (typeof params.connector_post === 'string') ? params.connector_post : null, 2356 onprogress: (typeof params.onprogress === 'function') ? params.onprogress : null, 2357 context: context, 2358 onupload_start: (typeof params.onupload_start === 'function') ? params.onupload_start : null, 2359 onupload_end: (typeof params.onupload_end === 'function') ? params.onupload_end : null, 2360 target_field: params.target_field, 2361 last: false, 2362 record_id: params.record_id 2363 }; 2364 2365 console.log('add file upload : ' + files[i].name); 2366 arr.push(tmp); 2367 } 2368 2369 if (!arr.length) { 2370 console.log('upload queue is empty. skipping upload'); 2371 return null; 2372 } 2373 2374 if (typeof params.onupload_queue_start === 'function') { 2375 if (context) params.onupload_queue_start.apply(context, [params]); 2376 else params.onupload_queue_start(params); 2377 } 2378 2379 arr[arr.length - 1].last = true; 2380 2381 if (typeof params.onupload_queue_end === 'function') { 2382 arr[arr.length - 1].onupload_queue_end = params.onupload_queue_end; 2383 } 2384 2385 for (let i = arr.length - 1; i >= 0; i--) { 2386 CMS._upload_queue.push(arr[i]); 2387 } 2388 2389 CMS.__upload_file_to_record_field_start(); 2390 return true; 2391 } 2392 2393 // --------------------------------------------------------- 2394 // __upload_file_to_record_field_start() 2395 // --------------------------------------------------------- 2396 2397 static __upload_file_to_record_field_start() { 2398 2399 if (!CMS._upload_queue.length) return true; 2400 2401 if (CMS._current_upload) { 2402 console.log('already uploading!'); 2403 return false; 2404 } 2405 2406 let upload = CMS._upload_queue.pop();
2407 CMS._current_upload = upload; 2408 2409 let formData = new FormData(); 2410 formData.append("fileToUpload", upload.file); 2411 formData.append("mime_pattern", upload.mime_pattern); 2412 2413 let url = 2414 document.location.protocol + 2415 '//' + 2416 document.location.hostname + 2417 '/_upload/?action=update_record_field' + 2418 '&target_field=' + encodeURIComponent(upload.target_field) + 2419 '&record_id=' + encodeURIComponent(upload.record_id); 2420 2421 if (upload.connector_pre) url += '&connector_pre=' + encodeURIComponent(upload.connector_pre); 2422 if (upload.connector_post) url += '&connector_post=' + encodeURIComponent(upload.connector_post); 2423 if (upload.last) url += '&last=1'; 2424 2425 let xhr = new XMLHttpRequest(); 2426 xhr.responseType = 'json'; 2427 xhr.open("POST", url, true); 2428 2429 xhr.onreadystatechange = function () { 2430 2431 if (this.readyState !== 4) return true; 2432 2433 let upload = CMS._current_upload; 2434 let result = (typeof this.response !== 'undefined') ? this.response : null; 2435 2436 if (upload.onupload_end) { 2437 if (upload.context) upload.onupload_end.apply(upload.context, [upload, result]); 2438 else upload.onupload_end(upload, result); 2439 } 2440 2441 if (result === null || typeof result.passed === 'undefined' || !result.passed) { 2442 2443 if (upload.onfailed) { 2444 if (upload.context) upload.onfailed.apply(upload.context, [result, this]); 2445 else upload.onfailed(result, xhr); 2446 } else { 2447 if (result !== null && typeof result === 'object') stdcheck(result); 2448 else alert('Error while uploading file'); 2449 } 2450 2451 } else { 2452 if (upload.context) upload.onsuccess.apply(upload.context, [result, this]); 2453 else upload.onsuccess(result, this); 2454 } 2455 2456 if (CMS._upload_queue.length) { 2457 delete CMS._current_upload; 2458 CMS.__upload_file_to_record_field_start(); 2459 } else { 2460 2461 if (typeof upload.onupload_queue_end === 'function') { 2462 if (upload.context) upload.onupload_queue_end.apply(upload.context, [upload, result]); 2463 else upload.onupload_queue_end(upload, result); 2464 } 2465 2466 delete CMS._current_upload; 2467 } 2468 2469 return true; 2470 }; 2471 2472 if (upload.onupload_start) { 2473 if (upload.context) upload.onupload_start.apply(upload.context, [upload]); 2474 else upload.onupload_start(upload); 2475 } 2476 2477 try { 2478 xhr.send(formData); 2479 } catch (err) { 2480 2481 if (upload.onupload_end) { 2482 if (upload.context) upload.onupload_end.apply(upload.context, [upload, err]); 2483 else upload.onupload_end(upload, err); 2484 } 2485 2486 console.log('XHR error on sending file'); 2487 2488 if (typeof upload.onfailed === 'function') { 2489 if (upload.context) return upload.onfailed.apply(upload.context, [xhr]); 2490 else upload.onfailed(xhr); 2491 } 2492 2493 return false; 2494 } 2495 2496 return false; 2497 } 2498 2499 static upload_temp_file(field_or_id,mime,onsuccess,onfailed,connector_function_pre,connector_function_post,connector_data,context){ 2500 console.log('CMS.upload_temp_file() '+Math.random()); 2501 let file=null,elem=null; 2502 if (field_or_id instanceof File) file=field_or_id; else { 2503 elem=JDOM.get_dom_element(field_or_id,true); 2504 if (!elem) return console.error('bad file'),false; 2505 if (!elem.id) elem.id=JDOM.generate_new_unique_dom_id(); 2506 } 2507 let myurl='/_upload/?action=upload_file'; 2508 if (connector_function_pre||connector_function_post){ 2509 if (connector_function_pre) myurl+='&connector_pre='+encodeURIComponent(connector_function_pre); 2510 if (connector_function_post) myurl+='&connector_post='+encodeURIComponent(connector_function_post); 2511 if (connector_data) for (let k in connector_data){ 2512 let v=connector_data[k]; 2513 if (typeof v=='string'||typeof v=='number'||typeof v=='boolean') myurl+='&data['+k+']='+encodeURIComponent(v); 2514 } 2515 } 2516 if (mime) myurl+='&mime='+mime; 2517 const fd=new FormData(); 2518 if (file) fd.append("fileToUpload",file); else { 2519 const files=elem.files; 2520 if (!files||!files.length){ 2521 const err=[{passed:0,error:-1000811,error_message:'file not loaded'}]; 2522 if (typeof onfailed=='function') return context?onfailed.apply(context,[err]):onfailed(err),false; 2523 return false; 2524 } 2525 for (const f of files) fd.append("fileToUpload[]",f); 2526 } 2527 const xhr=new XMLHttpRequest(); 2528 xhr.responseType='json'; 2529 xhr.open("POST",myurl,true); 2530 xhr.callback_success=onsuccess; 2531 xhr.callback_error=onfailed; 2532 xhr.context=context; 2533 xhr.onreadystatechange=function(){ 2534 if (this.readyState!==4) return; 2535 const r=this.response; 2536 if (!r||r.passed===undefined){ 2537 if (this.callback_error) return this.context?this.callback_error.apply(this.context,[r,this]):this.callback_error(r,this); 2538 return; 2539 } 2540 this.context?this.callback_success.apply(this.context,[r,this]):this.callback_success(r,this); 2541 }; 2542 try { xhr.send(fd); } 2543 catch(e){ 2544 console.log('XHR error on sending file'); 2545 if (typeof onfailed=='function') return context?onfailed.apply(context,[xhr]):onfailed(xhr),false; 2546 return false; 2547 } 2548 return false; 2549 } 2550 2551 // --------------------------------------------------------- 2552 // uploaded_file_remove() 2553 // --------------------------------------------------------- 2554 2555 static uploaded_file_remove(file_id_or_path, callback, context) { 2556 2557 console.log('CMS.uploaded_file_remove() ' + Math.random()); 2558 2559 let url = '/_upload.php?action=remove_uploaded_file&file=' + encodeURIComponent(file_id_or_path); 2560 2561 let xhr = new XMLHttpRequest(); 2562 xhr.responseType = 'json'; 2563 xhr.open("GET", url, true); 2564 2565 xhr.callback = callback; 2566 if (typeof context !== 'undefined') xhr.context = context; 2567 2568 xhr.onreadystatechange = function () { 2569 2570 if (xhr.readyState !== 4) return true; 2571 2572 let result = this.response; 2573 2574 if (typeof this.context !== 'undefined') { 2575 this.callback.apply(this.context, [result, xhr]); 2576 } else { 2577 this.callback(result, xhr); 2578 } 2579 2580 return true; 2581 }; 2582 2583 try { 2584 xhr.send(); 2585 } catch(err) { 2586 console.log('XHR error on sending file'); 2587 if (typeof xhr.context !== 'undefined') { 2588 xhr.callback.apply(xhr.context, [null, xhr]); 2589 } else { 2590 xhr.callback(null, xhr); 2591 } 2592 } 2593 2594 2595 return false; 2596 } 2597}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.