Вход Регистрация
Файл: domAjax.js
Строк: 666
<?php
(function(){
    
// node.parentElement not node.parentNode to check if it has dom-ajax-repeat
    // 
    
this.map = [];
    
this.version "1.0.1";
    
this.mapPointer 0;
    
this.useDefaultCallback true
    
    
var walkDom = function()
    {
        var 
selector document.querySelectorAll("[data-ajax-url]");
        for(var 
0selector.lengthi++)
        {
            
dom selector[i];
            
entry = {};
            
entry.id dom.getAttribute("id") || false;
            
entry.url dom.getAttribute("data-ajax-url") || false;
            
entry.method dom.getAttribute("data-ajax-method") || "get";
            
entry.event dom.getAttribute("data-ajax-event") || false;
                if(
typeof entry.event === "string" && entry.event.indexOf(".") > -1){
                    
ev entry.event;
                    
entry.event parseDotValue(ev2);
                    
entry.id parseDotValue(ev1);
                }
            
entry.callback dom.getAttribute("data-ajax-callback") || defaultCallBack;
            
entry.params dom.getAttribute("data-ajax-params") || false;
            
entry.interval dom.getAttribute("data-ajax-interval") || false;
                if(
typeof entry.interval === "string" && entry.interval.indexOf(".") > -1){
                    
iv entry.interval;
                    
entry.interval parseDotValue(iv1);
                    
entry.maxRequests parseDotValue(iv2);
                }
            
            
this.map[this.map.length] = entry;
            
delete entry;
            
// heirarchy, event, interval, instant
            
        
}
        
        var 
selector2 document.querySelectorAll("[data-ajax-config]");
        for(var 
0selector2.lengthi++)
        {
            
dom2 selector2[i];
            
config dom2.getAttribute("data-ajax-config");
            if(
isValidJson(config))
            {
                
entry = {};
                
configJson JSON.parse(config);
                
entry.id dom2.getAttribute("id");
                
entry.url configJson.url;
                
entry.method configJson.method;
                
entry.event configJson.event;
                    if(
typeof entry.event === "string" && entry.event.indexOf(".") > -1){
                        
ev entry.event;
                        
entry.event parseDotValue(ev2);
                        
entry.id parseDotValue(ev1);
                    }
                
entry.callback configJson.callback;
                
entry.params configJson.params;
                
entry.interval configJson.interval;
                    if(
typeof entry.interval === "string" && entry.interval.indexOf(".") > -1){
                        
iv entry.interval;
                        
entry.interval parseDotValue(iv1);
                        
entry.maxRequests parseDotValue(iv2);
                    }

                
                
this.map[this.map.length] = entry;
                
delete entry;
            }
            else{
                
console.log("domAjax - error - data-ajax-config does not have valid JSON");
            }
        }
        
    }
    
    var 
processDom = function()
    {
        for(var 
this.mapPointerthis.map.lengthi++)
        {
            
entry this.map[i];
            if(
entry.id)
            {
                
                if(
entry.event)
                {
                    
dom document.getElementById(entry.id);
                    
                    if(
dom.addEventListener){
                        
dom.addEventListener(entry.event, function(evtObj){
                        
ajax(this.urlthis.methodthis.paramsthis.callbackthis.idevtObj);
                        }.
bind(entry));
                    }
                }
                else if(
entry.interval)
                {
                    
intval entry.interval;

                    
ref this.map[i];
                    if(
entry.maxRequests){this.map[i].curRequest 1;}
                    
                    
// comment next line for the first ajax call to occur after interval seconds
                    // next line makes an instant ajax call before setting up the interval
                    
ajax(ref.urlref.methodref.paramsref.callbackref.idfalse);
                    
                    
this.map[i].intervalReference setInterval(function(ref){
                        
ajax(this.urlthis.methodthis.paramsthis.callbackthis.idfalse);
                        
ref.curRequest++;
                        if(
ref.curRequest ref.maxRequests){
                            
clearInterval(ref.intervalReference);
                        }
                    }.
bind(entry), intvalref);
                }
                else
                {
                    
eid entry.id;
                    
url entry.url;
                    
method entry.method;
                    
params entry.params;
                    
callback entry.callback;
                    
ajax(urlmethodparamscallbackeidfalse);
                }
            }
            
delete entry;
            
this.mapPointer i;
        }
        
this.mapPointer++;
    }
    
    var 
parseConfig = function(config)
    {
        
// expected structure [{id,url,method,event,callback},{},{}]
        
var toRet false;
        if(
config.constructor && config.constructor === Array)
        {
            for(var 
0config.lengthi++)
            {
                
singleConfig config[i];
                if(
singleConfig !== null && typeof singleConfig === 'object')
                {
                    if(
singleConfig.event && singleConfig.event.indexOf(".") > -1){
                            
ev singleConfig.event;
                            
singleConfig.event parseDotValue(ev2);
                            
singleConfig.id parseDotValue(ev1);
                    }
                    if(
singleConfig.interval && singleConfig.interval.indexOf(".") > -1){
                            
iv singleConfig.interval;
                            
singleConfig.interval parseDotValue(iv1);
                            
singleConfig.maxRequests parseDotValue(iv2);
                    }
                    
                    if(!
singleConfig.method){ singleConfig.method "get"; }
                    
this.map[this.map.length] = singleConfig;
                    
toRet true;
                }
                else{
console.log("domAjax - error - Parameter in config array is not an object");}
            }
        }
        else{
            
console.log("domAjax - error - config param passed to domAjax is not an array");
            
toRet false;
        }
        
        return 
toRet;
    }
    
    var 
ajax = function(urlmethodparamcallbackrefentryIdevt)
    {
        var 
ajax = new XMLHttpRequest();
            
ajax.open(method.toUpperCase(), encodeURI(url), true);
            
//ajax.setRequestHeader('Content-Type', 'application/json');
            
            
ajax.onload = function(){
                if (
ajax.status === 200) {
                    
resp ajax.responseText;
                    if(
isValidJson(resp))
                    {
                        
jsn JSON.parse(resp);
                        if(
jsn.hasOwnProperty("domAjax-redirect"))
                        {
                            
loc jsn["domAjax-redirect"]; // todo: decodeUriComponent
                            
location.href loc;
                            return;
                        }
                    }
                    else{
                        
tmpJson = {data:ajax.responseText};
                        
resp JSON.stringify(tmpJson);
                    }
                    
                    if(
typeof callbackref === "function")
                    {
                        if(
callbackref === defaultCallBack){
                            
//domAjaxRepeat(JSON.parse(resp));
                            
callbackref(JSON.parse(resp), evtentryId);
                            
domAjaxRepeat(JSON.parse(resp));
                        }
                        else{
                            
callbackref(JSON.parse(resp), evtentryId);
                        }
                    }
                    else{
                        var 
cbref window[callbackref];
                        if(
typeof cbref === "function")
                        {
                            
cbref(JSON.parse(resp), evtentryId);
                        }
                        else
                        {
                            
cbref2 containsDotAndProcess(callbackref);
                            if(
typeof cbref2 === "function")
                            {
                                
cbref2(JSON.parse(resp), evtentryId);
                            }
                            else
                            {
                                if(
this.useDefaultCallback)
                                {
                                var 
errmsg "domAjax - error - invalid callback for element with ID ";
                                
errmsg += entryId ". Fallback to default";
                                
console.log(errmsg);
                                
//domAjaxRepeat(JSON.parse(resp));
                                
defaultCallBack(JSON.parse(resp), evtentryId);
                                
domAjaxRepeat(JSON.parse(resp));
                                }
                                else{
                                var 
errmsg "domAjax - error - invalid callback for element with ID ";
                                
errmsg += entryId ". Default CallBack Disabled";
                                
console.log(errmsg);
                                }
                            }
                        }
                    }
                    
                }
            }.
bind(this);
            
            if(
method.toUpperCase() === "POST" && isValidJson(param)){
                
ajax.setRequestHeader('Content-Type''application/x-www-form-urlencoded');
                var 
arg "data=" encodeURIComponent(JSON.stringify(param));
                
ajax.send(arg);
            }
            else if(
param && isValidJson(param))
            {
                
ajax.setRequestHeader('Content-Type''application/json');
                
ajax.send(JSON.stringify(param));
            }
            else{
                
ajax.send();
            }
    }
    
    var 
defaultCallBack = function(dataevteid)
    {
        
        if(
typeof eid === "string"){ var elem document.getElementById(eid); }
        else if(
typeof eid === "object"){var elem eid;}
        if(
elem === null){
            
console.log("domAjax - error - could not get element with id " eid);
            return;
            }
        
        var 
dataKeys objKeys(data);
        var 
keyMap objKeysAsObjArray(data);
        var 
templateKeys = [];

    
//parseNode();
            
            
            
for(key in dataKeys)
            {
            
                var 
curKey dataKeys[key];
                
//var dataValue = parseTemplateStr(curKey, data);
                
var templateKey "{{" curKey "}}";
                
templateKeys[templateKeys.length] = templateKey;
                
//keyMap[templateKey] = dataValue;
                //parseNode(elem, dataKeys, keyMap);
                 
            
}
            
            var 
textNodes getTextNodes(elemtemplateKeystrue);
            
            for(
nkey in textNodes)
            {
                
node textNodes[nkey];
                
                
curText node.nodeValue;
                for(
itr in templateKeys)
                {
                    
tmpKey templateKeys[itr];
                    if(
curText.search(tmpKey) !== -1){
                        var 
tmpTxt curText.replace(tmpKeykeyMap[tmpKey]);
                        
curText tmpTxt;
                    }
                }
                
node.nodeValue curText;
                
                
            }
    }
    
    
// handle data-ajax-repeat
    
function domAjaxRepeat(jsonObj){
    
        var 
domSelector document.querySelectorAll("[data-ajax-repeat]");
        for(var 
0domSelector.lengthi++)
        {
            
dNode domSelector[i];
            
dNode.style.display "none";
            
            
// data-ajax-repeat should not be used on domAjax nodes
            
if(dNode.hasAttribute("data-ajax-url") || dNode.hasAttribute("data-ajax-config"))
            {
                
console.log("domAjax - Warning - data-ajax-repeat should not be used on domAjax nodes");
                continue;
            }
            
            
rootObjString dNode.getAttribute("data-ajax-repeat") || false;
            if(
rootObjString)
            {
                
rootObject parseTemplateStr(rootObjStringjsonObj);
                if(Array.
isArray(rootObject) && rootObject.length 0)
                {
                var 
1;
                    for(
key in rootObject)
                    {
                        
currentObj rootObject[key];
                        if(
typeof currentObj === "object")
                        {
                            
newNode dNode.cloneNode(true);
                            
newNode.style.display "inherit";
                            
newNode.removeAttribute("data-ajax-repeat");
                            var 
keyarr objKeys(currentObj);
                            var 
keyobj objKeysAsObjArray(currentObj);
                            
parseNode(newNodekeyarrkeyobj);
                            
dNode.parentNode.insertBefore(newNodedNode); // dNode.lastSibling
                        
}
                    }
                }
            }
            
// I can hide node instead of removing it so that dom-ajax-interval 
            // can function together with dom-ajax-repeat
            //dNode.parentNode.removeChild(dNode); 
            
delete dNode;
        }
    }
    
    function 
parseNode(nodekeyArrkeyArrVal){
        
// take an arbitrary node, parse any template textnodes in them based on json
        
var textNodes getTextNodes(nodekeyArr);
        
parseHTMLinJson(textNodeskeyArrkeyArrVal); //
        //var textNodes = getTextNodes(node, keyArr);
        
for(var nkey in textNodes)
        {
            
node textNodes[nkey];
            
curText node.nodeValue;
            for(
itr in keyArr)
            {
                
tmpKey "{{" keyArr[itr] + "}}";
                if(
curText.search(tmpKey) !== -1){
                        
txtTemp curText.replace(tmpKeykeyArrVal[tmpKey]);
                        
curText txtTemp;
                }
            }
            
node.nodeValue curText;
            
        }
        
    }
    
    
    
// support object dot notation in callback upto 3 properties deep
    // obj.obj.obj.method
    
function containsDotAndProcess(str)
    {
        if(
typeof str === "string")
        {
            if(
str.indexOf(".") > -1){
                
parts str.split(".");
                if(
parts.length 2){ return false; }
                if(
parts.length === 2)
                {
                    
p1 parts[0];
                    
p2 parts[1];
                    var 
func window[p1][p2];
                }
                else if(
parts.length === 3)
                {
                    
p1 parts[0];
                    
p2 parts[1];
                    
p3 parts[2];
                    var 
func window[p1][p2][p3];
                }
                else if(
parts.length === 4)
                {
                    
p1 parts[0];
                    
p2 parts[1];
                    
p3 parts[2];
                    
p4 parts[3];
                    var 
func window[p1][p2][p3][p4];
                }
                    if(
typeof func === "function"){return func; }
                    else{return 
false;}
            }
            else{return 
false;}
        }else{return 
false;}
    }
    
    function 
isValidJson(str) {
        try {
            
JSON.parse(str);
        } catch (
e) {
            return 
false;
        }
        return 
true;
    }
    
    function 
parseEntry(entry)
    {
        if(
entry.url && entry.url !== ""){}else{ return false; }
        if(
entry.id && entry.id !== ""){}else{ return false; }
        return 
true;
    }
    
    function 
parseDotValue(dotValueret)
    {
        if(
typeof dotValue === "string")
        {
            if(
dotValue.indexOf(".") > -1){
                
parts dotValue.split(".");
                if(
ret === 1){return parts[0]; }
                else if(
ret === 2){return parts[1];}
            }
            else{
                if(
ret === 1){return dotValue; }
                else if(
ret === 2){return false;}
            }
        }
    }
    
    
// recursively walk a json object
    
function objKeys(obj)
    {
    var 
dd = [];
        for (var 
k in obj)
        {
            if (
typeof obj[k] == "object" && obj[k] !== null){
                var 
objKeys(obj[k]);
                for(var 
x in c)
                {
                    
dd[dd.length] = "." c[x];
                }
              }
            else{
                    if(
typeof obj[k] !== "function"){
                        
dd[dd.length] = k;
                    }
               }
        }
    return 
dd;
    }
    
function 
objKeysAsObjArray(objlevel)
{
        var 
dd = [];
        var 
ff = {};
        if(!
level){level 1;}
        var 
level 1;
        for (var 
k in obj)
        {
            if (
typeof obj[k] == "object" && obj[k] !== null){
                var 
objKeysAsObjArray(obj[k], l);
                for(var 
x in c)
                {
                    
dd[dd.length] = {key:"." c[x].keyval:c[x].val};
                }
              }
            else{
                    if(
typeof obj[k] !== "function"){
                        
dd[dd.length] = {key:kval:obj[k]};
                    }
               }
        }
    
    if(
level === 1){
        for(var 
x in dd)
        {
            var 
objx dd[x];
            
ff["{{" objx.key "}}"] = objx.val;
        }
        return 
ff;
        }
        else{
            return 
dd;
        }
    }
    
    function 
parseTemplateStr(strobj)
    {
        if(
typeof str === "string")
        {
            if(
str.indexOf(".") > -1)
            {
                
parts str.split(".");
                if(
parts.length === 2){
                    return 
obj[parts[0]][parts[1]];
                }
                if(
parts.length === 3){
                    return 
obj[parts[0]][parts[1]][parts[2]];
                }
                if(
parts.length === 4){
                    return 
obj[parts[0]][parts[1]][parts[2]][parts[3]];
                }
            }
            else if(
obj[str]){return obj[str];}
            else{return 
false;}
        }
    }
    
    function 
parseHTMLinJson(txtNodesarrKeytemplateMap)
    {
        for(
lKey in txtNodes){
            
curNode txtNodes[lKey];
            
curTxt curNode.nodeValue;
            
            for(
loopArrKey in arrKey){
                
cKey "{{" arrKey[loopArrKey] + "}}";
                if(
cKey.search("domAjax-html") !== -1){
                    if(
curTxt.search(cKey) !== -1)
                    {
                        
tmpTxt curTxt;
                        
thisHtml templateMap[cKey];
                        
tmpTxt tmpTxt.replace(cKeythisHtml);
                            
divNode document.createElement("div");
                            
divNode.innerHTML tmpTxt;
                            
                            while(
divNode.firstChild){
                                
curNode.parentNode.insertBefore(divNode.firstChildcurNode);
                            }
                            
curNode.parentNode.removeChild(curNode);
                            
                    }
                    else{ continue; }
                }
            }
        }
        
    }
    
// traverse dom to get text nodes starting from element
    
function getTextNodes(elempropscallingFunction)
    {
        var 
textNodes = [];
        if(
document.createTreeWalker)
        {
            var 
treeWalker document.createTreeWalker(elemNodeFilter.SHOW_TEXT
            { 
acceptNode: function(node) { 
                  if(!
props || !Array.isArray(props)){ return NodeFilter.FILTER_SKIP; }
                  
// following conditions should reject node only if the method calling this function is the defaultCallBack
                  /*
                    Why I'm Checking parent nodes
                    To prevent defaultCallBAck from processing {{templates}} within data-ajax-repeat
                    nodes
                  */
                 
try{
                  if(
node.parentNode.hasAttribute("data-ajax-repeat") && callingFunction){
                    return 
NodeFilter.FILTER_REJECT;
                  }
                  else if(
typeof node.parentNode.parentNode !== 'undefined'){
                      if(
node.parentNode.parentNode.hasAttribute("data-ajax-repeat") && callingFunction){
                                return 
NodeFilter.FILTER_REJECT;
                        }
                    }
                  else if(
typeof node.parentNode.parentNode.parentNode !== 'undefined'){
                      if(
node.parentNode.parentNode.parentNode.hasAttribute("data-ajax-repeat") && callingFunction){
                                return 
NodeFilter.FILTER_REJECT;
                        }
                    }
                  }
                  catch(
ex){ return NodeFilter.FILTER_REJECT; }
                  
                  var 
nodeText node.nodeValue;
                      for(var 
i in props){
                        if(
nodeText.search(props[i]) !== -1){ return NodeFilter.FILTER_ACCEPT; }
                      }
                      return 
NodeFilter.FILTER_SKIP
                  }
                });
                      
            while(
treeWalker.nextNode()){
                
textNodes.push(treeWalker.currentNode);
            }
        }
        else{
            
textNodes getTextNodesIn(elemprops, function(nodeparentprms){
                if(!
prms || !Array.isArray(prms)){ return false; }
                
                try
                {
                    if(
node.parentNode.hasAttribute("data-ajax-repeat")){ return false; }
                    if(
node.parentNode.parentNode)
                    {
                        if(
node.parentNode.parentNode.hasAttribute("data-ajax-repeat")){
                        return 
false; }
                    }
                    if(
node.parentNode.parentNode.parentNode)
                    {
                    if(
node.parentNode.parentNode.parentNode.hasAttribute("data-ajax-repeat")){
                        return 
false; }
                    }
                }
                catch(
ex){ return false; }
                
                var 
nodeText node.nodeValue;
                for(var 
i in prms){ if(nodeText.search(prms[i])){ return true; }}
                return 
false;
            });
        }
        
        return 
textNodes;
    }
    
    
// http://cwestblog.com/2014/03/14/javascript-getting-all-text-nodes/
    // traverse dom to get text nodes starting from element
     
var getTextNodesIn = function(elemparamsopt_fnFilter) {
          var 
textNodes = [];
          if (
elem) {
            for (var 
nodes elem.childNodesnodes.lengthi--;) {
              var 
node nodes[i], nodeType node.nodeType;
              if (
nodeType == 3) {
                if (!
opt_fnFilter || opt_fnFilter(nodeelemparams)) {
                  
textNodes.push(node);
                }
              }
              else if (
nodeType == || nodeType == || nodeType == 11) {
                
textNodes textNodes.concat(getTextNodesIn(nodeparamsopt_fnFilter));
              }
            }
          }
          return 
textNodes;
    }

    
walkDom();
    
processDom();

    
window.domAjax = function(confval){
        if(
typeof conf === "string")
        {
            switch(
conf)
            {
                case 
"version":
                return 
this.version;
                break;
                case 
"map":
                    var 
mp this.map.slice();
                    return 
mp;
                break;
                
// Experimental - Debug - Always true
                
case "useDefaultCallback":
                    if(
val && typeof val === "boolean")
                    {
                        
this.useDefaultCallback val;
                    }
                    else{
                        return 
this.useDefaultCallback;
                    }
                break;
                default:
                    return 
this.version;
                break;
            }
        }
        else
        {
            if(
parseConfig(conf)){ processDom(); }
        }
    }.
bind(this);
    
    
// polyfill for Array.isArray, maybe move to top of script
    
if (!Array.isArray) {
          Array.
isArray = function(arg) {
            return 
Object.prototype.toString.call(arg) === '[object Array]';
          };
    }
}());
?>
Онлайн: 1
Реклама