(function(window){ if (window.BX.ajax) return; var BX = window.BX, tempDefaultConfig = {}, defaultConfig = { method: 'GET', // request method: GET|POST dataType: 'html', // type of data loading: html|json|script timeout: 0, // request timeout in seconds. 0 for browser-default async: true, // whether request is asynchronous or not processData: true, // any data processing is disabled if false, only callback call scriptsRunFirst: false, // whether to run _all_ found scripts before onsuccess call. script tag can have an attribute "bxrunfirst" to turn this flag on only for itself emulateOnload: true, start: true, // send request immediately (if false, request can be started manually via XMLHttpRequest object returned) cache: true // whether NOT to add random addition to URL /* other parameters: url: url to get/post data: data to post onsuccess: successful request callback. BX.proxy may be used. onfailure: request failure callback. BX.proxy may be used. any of the default parameters can be overridden. defaults can be changed by BX.ajax.Setup() - for all further requests! */ }, ajax_session = null, loadedScripts = {}, r = { 'url_utf': /[^\034-\254]+/g, 'script_self': /\/bitrix\/js\/main\/core\/core(_ajax)*.js$/i, 'script_self_window': /\/bitrix\/js\/main\/core\/core_window.js$/i, 'script_self_admin': /\/bitrix\/js\/main\/core\/core_admin.js$/i, 'script_onload': /window.onload/g }; // low-level method BX.ajax = function(config) { var status, data; if (!config || !config.url || !BX.type.isString(config.url)) { return false; } for (var i in tempDefaultConfig) if (typeof (config[i]) == "undefined") config[i] = tempDefaultConfig[i]; tempDefaultConfig = {}; for (var i in defaultConfig) if (typeof (config[i]) == "undefined") config[i] = defaultConfig[i]; config.method = config.method.toUpperCase(); if (BX.browser.IsIE()) { var result = r.url_utf.exec(config.url); if (result) { do { config.url = config.url.replace(result, BX.util.urlencode(result)); result = r.url_utf.exec(config.url); } while (result); } } if (!config.cache && config.method == 'GET') config.url = BX.ajax._uncache(config.url); if (config.method == 'POST') { config.data = BX.ajax.prepareData(config.data); } config.xhr = BX.ajax.xhr(); if (!config.xhr) return; config.xhr.open(config.method, config.url, config.async); if (config.method == 'POST') { config.xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); } var bRequestCompleted = false; var onreadystatechange = config.xhr.onreadystatechange = function(additional) { if (bRequestCompleted) return; if (additional === 'timeout') { if (config.onfailure) config.onfailure("timeout"); BX.onCustomEvent(config.xhr, 'onAjaxFailure', ['timeout', '', config]); config.xhr.onreadystatechange = BX.DoNothing; config.xhr.abort(); if (config.async) { config.xhr = null; } } else { if (config.xhr.readyState == 4 || additional == 'run') { status = BX.ajax.xhrSuccess(config.xhr) ? "success" : "error"; bRequestCompleted = true; config.xhr.onreadystatechange = BX.DoNothing; // var status = oAjax.arThreads[TID].httpRequest.getResponseHeader('X-Bitrix-Ajax-Status'); // var bRedirect = (status == 'Redirect'); if (status == 'success') { var data = config.xhr.responseText; if (!config.processData) { if (config.onsuccess) { config.onsuccess(data); } BX.onCustomEvent(config.xhr, 'onAjaxSuccess', [data, config]); } else { try { data = BX.ajax.processRequestData(data, config); } catch (e) { if (config.onfailure) config.onfailure("processing", e); BX.onCustomEvent(config.xhr, 'onAjaxFailure', ['processing', e, config]); } } } else if (config.onfailure) { config.onfailure("status", config.xhr.status); BX.onCustomEvent(config.xhr, 'onAjaxFailure', ['status', config.xhr.status, config]); } if (config.async) { config.xhr = null; } } } } if (config.async && config.timeout > 0) { setTimeout(function() { if (config.xhr && !bRequestCompleted) { onreadystatechange("timeout"); } }, config.timeout * 1000); } if (config.start) { config.xhr.send(config.data); if (!config.async) { onreadystatechange('run'); } } return config.xhr; } BX.ajax.xhr = function() { if (window.XMLHttpRequest) { try {return new XMLHttpRequest();} catch(e){} } else if (window.ActiveXObject) { try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch(e) {} try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch(e) {} try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) {} try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {} throw new Error("This browser does not support XMLHttpRequest."); } return null; } BX.ajax.__prepareOnload = function(scripts) { if (scripts.length > 0) { BX.ajax['onload_' + ajax_session] = null; for (var i=0,len=scripts.length;i= 0) eval('result = ' + data); else result = (new Function("return " + data))(); break; case 'SCRIPT': scripts.push({"isInternal": true, "JS": data, bRunFirst: config.scriptsRunFirst}); result = data; break; default: // HTML var ob = BX.processHTML(data, config.scriptsRunFirst); result = ob.HTML; scripts = ob.SCRIPT; break; } var bSessionCreated = false; if (null == ajax_session) { ajax_session = parseInt(Math.random() * 1000000); bSessionCreated = true; } if (config.emulateOnload) BX.ajax.__prepareOnload(scripts); BX.ajax.processScripts(scripts, true); if (config.onsuccess) { config.onsuccess(result); } BX.onCustomEvent(config.xhr, 'onAjaxSuccess', [result, config]); BX.ajax.processScripts(scripts, false); setTimeout(function() { if (config.emulateOnload) BX.ajax.__runOnload(); if (bSessionCreated) ajax_session = null; }, 10); } BX.ajax.processScripts = function(scripts, bRunFirst) { for (var i = 0, length = scripts.length; i < length; i++) { if (null != bRunFirst && bRunFirst != !!scripts[i].bRunFirst) continue; if (scripts[i].isInternal) { BX.evalGlobal(scripts[i].JS); } else { BX.ajax.loadScriptAjax([scripts[i].JS]); } } } // TODO: extend this function to use with any data objects or forms BX.ajax.prepareData = function(arData, prefix) { var data = ''; if (BX.type.isString(arData)) data = arData; else if (null != arData) { for(var i in arData) { if (data.length > 0) data += '&'; var name = BX.util.urlencode(i); if(prefix) name = prefix + '[' + name + ']'; if(typeof arData[i] == 'object') data += BX.ajax.prepareData(arData[i], name) else data += name + '=' + BX.util.urlencode(arData[i]) } } return data; } BX.ajax.xhrSuccess = function(xhr) { return (xhr.status >= 200 && xhr.status < 300) || xhr.status === 304 || xhr.status === 1223 || xhr.status === 0; } BX.ajax.Setup = function(config, bTemp) { bTemp = !!bTemp; for (var i in config) { if (bTemp) tempDefaultConfig[i] = config[i]; else defaultConfig[i] = config[i]; } } BX.ajax._uncache = function(url) { return url + ((url.indexOf('?') !== -1 ? "&" : "?") + '_=' + (new Date).getTime()); } /* simple interface */ BX.ajax.get = function(url, data, callback) { if (BX.type.isFunction(data)) { callback = data; data = ''; } data = BX.ajax.prepareData(data); if (data) { url += (url.indexOf('?') !== -1 ? "&" : "?") + data; data = ''; } return BX.ajax({ 'method': 'GET', 'dataType': 'html', 'url': url, 'data': '', 'onsuccess': callback }); } BX.ajax.getCaptcha = function(callback) { return BX.ajax.loadJSON('/bitrix/tools/ajax_captcha.php', callback); } BX.ajax.insertToNode = function(url, node) { if (node = BX(node)) { BX.onCustomEvent('onAjaxInsertToNode', [{url: url, node: node}]); var show = null; if (!tempDefaultConfig.denyShowWait) { show = BX.showWait(node); delete tempDefaultConfig.denyShowWait; } return BX.ajax.get(url, function(data) { node.innerHTML = data; BX.closeWait(node, show); }); } } BX.ajax.post = function(url, data, callback) { data = BX.ajax.prepareData(data); return BX.ajax({ 'method': 'POST', 'dataType': 'html', 'url': url, 'data': data, 'onsuccess': callback }); } /* load and execute external file script with onload emulation */ BX.ajax.loadScriptAjax = function(script_src, callback) { if (BX.type.isArray(script_src)) { for (var i=0,len=script_src.length;i= len) callback(); }; for (var i = 0, len = arObs.length; i= len) callback(); break; case 'JSON': BX.ajax.loadJSON(arObs.url, jsBX.proxy(handler, arObs[i])); break; default: BX.ajax.get(arObs.url, '', jsBX.proxy(handler, arObs[i])); break; } } } /* ajax form sending */ BX.ajax.submit = function(obForm, callback) { if (!obForm.target) { if (null == obForm.BXFormTarget) { var frame_name = 'formTarget_' + Math.random(); obForm.BXFormTarget = document.body.appendChild(BX.create('IFRAME', { props: { name: frame_name, id: frame_name, src: 'javascript:void(0)' }, style: { display: 'none' } })); } obForm.target = obForm.BXFormTarget.name; } obForm.BXFormCallback = callback; BX.bind(obForm.BXFormTarget, 'load', BX.proxy(BX.ajax._submit_callback, obForm)); BX.submit(obForm); return false; } BX.ajax.submitComponentForm = function(obForm, container) { if (!obForm.target) { if (null == obForm.BXFormTarget) { var frame_name = 'formTarget_' + Math.random(); obForm.BXFormTarget = document.body.appendChild(BX.create('IFRAME', { props: { name: frame_name, id: frame_name, src: 'javascript:void(0)' }, style: { display: 'none' } })); } obForm.target = obForm.BXFormTarget.name; } obForm.BXFormCallback = function(d) { BX(container).innerHTML = d; if (window.bxcompajaxframeonload){ setTimeout("window.bxcompajaxframeonload();window.bxcompajaxframeonload=null;", 10) }; BX.onCustomEvent('onAjaxSuccess', []); }; BX.bind(obForm.BXFormTarget, 'load', BX.proxy(BX.ajax._submit_callback, obForm)); return true; } // func will be executed in form context BX.ajax._submit_callback = function() { //opera triggers onload event even on empty iframe if(this.BXFormTarget.contentWindow.location.href.indexOf('http') != 0) return; if (this.BXFormCallback) this.BXFormCallback.apply(this, [this.BXFormTarget.contentWindow.document.body.innerHTML]); BX.unbindAll(this.BXFormTarget); } // TODO: currently in window extension. move it here. BX.ajax.submitAjax = function(obForm, callback) { } BX.ajax.UpdatePageData = function (arData) { if (arData.TITLE) BX.ajax.UpdatePageTitle(arData.TITLE); if (arData.NAV_CHAIN) BX.ajax.UpdatePageNavChain(arData.NAV_CHAIN); if (arData.CSS && arData.CSS.length > 0) BX.loadCSS(arData.CSS); if (arData.SCRIPTS && arData.SCRIPTS.length > 0) BX.loadScript(arData.SCRIPTS); } BX.ajax.UpdatePageTitle = function(title) { var obTitle = BX('pagetitle'); if (obTitle) { obTitle.removeChild(obTitle.firstChild); if (!obTitle.firstChild) obTitle.appendChild(document.createTextNode(title)); else obTitle.insertBefore(document.createTextNode(title), obTitle.firstChild); } document.title = title; } BX.ajax.UpdatePageNavChain = function(nav_chain) { var obNavChain = BX('navigation'); if (obNavChain) { obNavChain.innerHTML = nav_chain; } } /* user options handling */ BX.userOptions = { options: null, bSend: false, delay: 5000 } BX.userOptions.save = function(sCategory, sName, sValName, sVal, bCommon) { if (null == BX.userOptions.options) BX.userOptions.options = {}; bCommon = !!bCommon; BX.userOptions.options[sCategory+'.'+sName+'.'+sValName] = [sCategory, sName, sValName, sVal, bCommon]; var sParam = BX.userOptions.__get(); if (sParam != '') document.cookie = BX.message('COOKIE_PREFIX')+"_LAST_SETTINGS=" + sParam + "&sessid="+BX.bitrix_sessid()+"; expires=Thu, 31 Dec 2020 23:59:59 GMT; path=/;"; if(!BX.userOptions.bSend) { BX.userOptions.bSend = true; setTimeout(function(){BX.userOptions.send(null)}, BX.userOptions.delay); } } BX.userOptions.send = function(callback) { var sParam = BX.userOptions.__get(); BX.userOptions.options = null; BX.userOptions.bSend = false; if (sParam != '') { document.cookie = BX.message('COOKIE_PREFIX') + "_LAST_SETTINGS=; path=/;"; BX.ajax({ 'method': 'GET', 'dataType': 'html', 'processData': false, 'cache': false, 'url': '/bitrix/admin/user_options.php?'+sParam+'&sessid='+BX.bitrix_sessid(), 'onsuccess': callback }); } } BX.userOptions.del = function(sCategory, sName, bCommon, callback) { BX.ajax.get('/bitrix/admin/user_options.php?action=delete&c='+sCategory+'&n='+sName+(bCommon == true? '&common=Y':'')+'&sessid='+BX.bitrix_sessid(), callback); } BX.userOptions.__get = function() { if (!BX.userOptions.options) return ''; var sParam = '', n = -1, prevParam = '', arOpt, i; for (i in BX.userOptions.options) { aOpt = BX.userOptions.options[i]; if (prevParam != aOpt[0]+'.'+aOpt[1]) { n++; sParam += '&p['+n+'][c]='+BX.util.urlencode(aOpt[0]); sParam += '&p['+n+'][n]='+BX.util.urlencode(aOpt[1]); if (aOpt[4] == true) sParam += '&p['+n+'][d]=Y'; prevParam = aOpt[0]+'.'+aOpt[1]; } sParam += '&p['+n+'][v]['+BX.util.urlencode(aOpt[2])+']='+BX.util.urlencode(aOpt[3]); } return sParam.substr(1); } BX.ajax.history = { expected_hash: '', obParams: null, obFrame: null, obImage: null, obTimer: null, bInited: false, bHashCollision: false, bPushState: !!(history.pushState && BX.type.isFunction(history.pushState)), init: function(obParams) { if (BX.ajax.history.bInited) return; this.obParams = obParams; var obCurrentState = this.obParams.getState(); if (BX.ajax.history.bPushState) { BX.ajax.history.expected_hash = window.location.pathname; if (window.location.search) BX.ajax.history.expected_hash += window.location.search; BX.ajax.history.put(obCurrentState, BX.ajax.history.expected_hash); BX.bind(window, 'popstate', BX.ajax.history.__hashListener); } else { BX.ajax.history.expected_hash = window.location.hash; if (!BX.ajax.history.expected_hash || BX.ajax.history.expected_hash == '#') BX.ajax.history.expected_hash = '__bx_no_hash__'; jsAjaxHistoryContainer.put(BX.ajax.history.expected_hash, obCurrentState); BX.ajax.history.obTimer = setTimeout(BX.ajax.history.__hashListener, 500); if (BX.browser.IsIE()) { BX.ajax.history.obFrame = document.createElement('IFRAME'); BX.hide_object(BX.ajax.history.obFrame); document.body.appendChild(BX.ajax.history.obFrame); BX.ajax.history.obFrame.contentWindow.document.open(); BX.ajax.history.obFrame.contentWindow.document.write(BX.ajax.history.expected_hash); BX.ajax.history.obFrame.contentWindow.document.close(); } else if (BX.browser.IsOpera()) { BX.ajax.history.obImage = document.createElement('IMG'); BX.hide_object(BX.ajax.history.obImage); document.body.appendChild(BX.ajax.history.obImage); BX.ajax.history.obImage.setAttribute('src', 'javascript:location.href = \'javascript:BX.ajax.history.__hashListener();\';'); } } BX.ajax.history.bInited = true; }, __hashListener: function(e) { e = e || window.event || {state:false}; if (BX.ajax.history.bPushState && e.state) { BX.ajax.history.obParams.setState(e.state); } else { if (BX.ajax.history.obTimer) { window.clearTimeout(BX.ajax.history.obTimer); BX.ajax.history.obTimer = null; } if (null != BX.ajax.history.obFrame) var current_hash = BX.ajax.history.obFrame.contentWindow.document.body.innerText; else var current_hash = window.location.hash; if (!current_hash || current_hash == '#') current_hash = '__bx_no_hash__'; if (current_hash.indexOf('#') == 0) current_hash = current_hash.substring(1); if (current_hash != BX.ajax.history.expected_hash) { var state = jsAjaxHistoryContainer.get(current_hash); if (state) { BX.ajax.history.obParams.setState(state); BX.ajax.history.expected_hash = current_hash; if (null != BX.ajax.history.obFrame) { var __hash = current_hash == '__bx_no_hash__' ? '' : current_hash; if (window.location.hash != __hash && window.location.hash != '#' + __hash) window.location.hash = __hash; } } } BX.ajax.history.obTimer = setTimeout(BX.ajax.history.__hashListener, 500); } }, put: function(state, new_hash, new_hash1) { if (this.bPushState) { history.pushState(state, '', new_hash); } else { if (typeof new_hash1 != 'undefined') new_hash = new_hash1; else new_hash = 'view' + new_hash; jsAjaxHistoryContainer.put(new_hash, state); BX.ajax.history.expected_hash = new_hash; window.location.hash = BX.util.urlencode(new_hash); if (null != BX.ajax.history.obFrame) { BX.ajax.history.obFrame.contentWindow.document.open(); BX.ajax.history.obFrame.contentWindow.document.write(new_hash); BX.ajax.history.obFrame.contentWindow.document.close(); } } }, checkRedirectStart: function(param_name, param_value) { var current_hash = window.location.hash; if (current_hash.substring(0, 1) == '#') current_hash = current_hash.substring(1); var test = current_hash.substring(0, 5); if (test == 'view/' || test == 'view%') { BX.ajax.history.bHashCollision = true; document.write('<' + 'div id="__ajax_hash_collision_' + param_value + '" style="display: none;">'); } }, checkRedirectFinish: function(param_name, param_value) { document.write(''); var current_hash = window.location.hash; if (current_hash.substring(0, 1) == '#') current_hash = current_hash.substring(1); BX.ready(function () { var test = current_hash.substring(0, 5); if (test == 'view/' || test == 'view%') { var obColNode = BX('__ajax_hash_collision_' + param_value); var obNode = obColNode.firstChild; BX.cleanNode(obNode); obColNode.style.display = 'block'; // IE, Opera and Chrome automatically modifies hash with urlencode, but FF doesn't ;-( if (test != 'view%') current_hash = BX.util.urlencode(current_hash); current_hash += (current_hash.indexOf('%3F') == -1 ? '%3F' : '%26') + param_name + '=' + param_value; var url = '/bitrix/tools/ajax_redirector.php?hash=' + current_hash; BX.ajax.insertToNode(url, obNode); } }); } } BX.ajax.component = function(node) { this.node = node; } BX.ajax.component.prototype.getState = function() { var state = { 'node': this.node, 'title': window.document.title, 'data': BX(this.node).innerHTML }; var obNavChain = BX('navigation'); if (null != obNavChain) state.nav_chain = obNavChain.innerHTML; return state; } BX.ajax.component.prototype.setState = function(state) { BX(state.node).innerHTML = state.data; BX.ajax.UpdatePageTitle(state.title); if (state.nav_chain) BX.ajax.UpdatePageNavChain(state.nav_chain); } var jsAjaxHistoryContainer = { arHistory: {}, put: function(hash, state) { this.arHistory[hash] = state; }, get: function(hash) { return this.arHistory[hash]; } } })(window)