diff --git a/dist/jaxon.core.js b/dist/jaxon.core.js index 5f08d7f..1284403 100644 --- a/dist/jaxon.core.js +++ b/dist/jaxon.core.js @@ -430,22 +430,22 @@ window.jaxon = jaxon; * Given an element and an attribute with 0 or more dots, * get the inner object and the corresponding attribute name. * - * @param {object} xElement The outer element. - * @param {string} attribute The attribute name. + * @param {string} sAttrName The attribute name. + * @param {object=} xElement The outer element. * * @returns {object|null} The inner object and the attribute name in an object. */ - self.getInnerObject = (xElement, attribute) => { - const aNames = attribute.split('.'); + self.getInnerObject = (sAttrName, xElement = window) => { + const aNames = sAttrName.split('.'); // Get the last element in the array. - attribute = aNames.pop(); + sAttrName = aNames.pop(); // Move to the inner object. const nLength = aNames.length; for (let i = 0; i < nLength && (xElement); i++) { // The real name for the "css" object is "style". xElement = xElement[aNames[i] === 'css' ? 'style' : aNames[i]]; } - return !xElement ? null : { node: xElement, attr: attribute }; + return !xElement ? null : { node: xElement, attr: sAttrName }; }; })(jaxon.utils.dom, jaxon.utils.types, jaxon.config.baseDocument); @@ -975,7 +975,10 @@ window.jaxon = jaxon; */ const xErrors = { comparator: () => false, // The default comparison operator. - command: (xCall) => console.error('Unexpected command: ' + JSON.stringify({ call: xCall })), + command: (xCall) => { + console.error('Unexpected command: ' + JSON.stringify({ call: xCall })); + return undefined; + }, }; /** @@ -1001,7 +1004,7 @@ window.jaxon = jaxon; * * @returns {boolean} */ - const isExpression = xArg => types.isObject(xArg) && (xArg._type); + const isValidCall = xArg => types.isObject(xArg) && (xArg._type); /** * Get the value of a single argument. @@ -1012,7 +1015,7 @@ window.jaxon = jaxon; * @returns {mixed} */ const getValue = (xArg, xCurrValue) => { - if (!isExpression(xArg)) { + if (!isValidCall(xArg)) { return xArg; } const { _type: sType, _name: sName } = xArg; @@ -1021,8 +1024,8 @@ window.jaxon = jaxon; case 'html': return dom.$(sName).innerHTML; case 'input': return dom.$(sName).value; case 'checked': return dom.$(sName).checked; - case 'expr': return execExpression(xArg); - case '_': return sName === 'this' ? xCurrValue : undefined + case 'expr': return execExpression(xArg, { target: window }); + case '_': return sName === 'this' ? xCurrValue : undefined; default: return undefined; } }; @@ -1043,42 +1046,42 @@ window.jaxon = jaxon; * @var {object} */ const xCommands = { - select: ({ _name: sName, context: xSelectContext = null }, xCurrValue, oCallContext) => { + select: ({ _name: sName, context: xSelectContext = null }, oCallContext) => { switch(sName) { case 'this': return query.select(oCallContext.target); // The last event target. case 'event': return oCallContext.event; // The last event - case 'window': - return window; default: // Call the selector. - return query.select(sName, getValue(xSelectContext, xCurrValue)); + return query.select(sName, xSelectContext); } }, - event: ({ _name: sName, func: xExpression }, xCurrValue, oCallContext) => { + event: ({ _name: sName, func: xExpression }, oCallContext, xCurrValue) => { // Set an event handler. Takes an expression as argument. xCurrValue.on(sName, (event) => execExpression(xExpression, { ...oCallContext, event, target: event.currentTarget, - value: null, })); return xCurrValue; }, - func: ({ _name: sName, args: aArgs = [] }, xCurrValue, oCallContext) => { + func: ({ _name: sName, args: aArgs = [] }, oCallContext, xCurrValue) => { // Call a "global" function with the current context as "this". const func = dom.findFunction(sName); - return !func ? null : func.apply(oCallContext, getArgs(aArgs, xCurrValue)); + return !func ? undefined : func.apply(oCallContext, getArgs(aArgs, xCurrValue)); }, - method: ({ _name: sName, args: aArgs = [] }, xCurrValue) => { + method: ({ _name: sName, args: aArgs = [] }, oCallContext, xCurrValue) => { // Call a function with the current value as "this". const func = dom.findFunction(sName, xCurrValue); // toInt() is a peudo-method that converts the current value to int. - return !func ? (sName === 'toInt' ? types.toInt(xCurrValue) : null) : + return !func ? (sName === 'toInt' ? types.toInt(xCurrValue) : undefined) : func.apply(xCurrValue, getArgs(aArgs, xCurrValue)); }, - attr: ({ _name: sName, value: xValue }, xCurrValue) => { - const xElt = dom.getInnerObject(xCurrValue, sName); + attr: ({ _name: sName, value: xValue }, oCallContext, xCurrValue) => { + const xElt = dom.getInnerObject(sName, xCurrValue || oCallContext.target); + if (!xElt) { + return undefined; + } if (xValue !== undefined) { // Assign an attribute. xElt.node[xElt.attr] = getValue(xValue, xCurrValue); @@ -1092,13 +1095,13 @@ window.jaxon = jaxon; * * @param {object} xCall * @param {object} oCallContext The context to execute calls in. + * @param {mixed=} xCurrValue The current expression value. * * @returns {void} */ - const execCall = (xCall, oCallContext) => { - const { value: xCurrValue } = oCallContext; - const xCommand = xCommands[xCall._type] ?? xErrors.command; - return xCommand(xCall, xCurrValue, oCallContext); + const execCall = (xCall, oCallContext, xCurrValue) => { + const xCommand = isValidCall(xCall) ? xCommands[xCall._type] : xErrors.command; + return xCommand(xCall, oCallContext, xCurrValue); }; /** @@ -1109,8 +1112,7 @@ window.jaxon = jaxon; * * @returns {mixed} */ - self.execCall = (xCall, oCallContext) => !types.isObject(xCall) ? null : - execCall(xCall, oCallContext || { target: window, value: null }); + self.execCall = (xCall, oCallContext) => execCall(xCall, { target: window, ...oCallContext }); /** * Execute the javascript code represented by an expression object. @@ -1120,8 +1122,17 @@ window.jaxon = jaxon; * * @returns {mixed} */ - const execCalls = (aCalls, oCallContext) => - aCalls.reduce((xValue, xCall) => execCall(xCall, { ...oCallContext, value: xValue }), null); + const execCalls = (aCalls, oCallContext) => { + let xCurrValue = undefined; + const nLength = aCalls.length; + for (let i = 0; i < nLength; i++) { + xCurrValue = execCall(aCalls[i], oCallContext, xCurrValue); + if (xCurrValue === undefined) { + return xCurrValue; // Exit the loop if a call return an undefined value. + } + } + return xCurrValue; + }; /** * Replace placeholders in a given string with values @@ -1218,7 +1229,7 @@ window.jaxon = jaxon; * @returns {mixed} */ self.execExpr = (xExpression, oCallContext) => !types.isObject(xExpression) ? null : - execExpression(xExpression, oCallContext || { target: window, value: null }); + execExpression(xExpression, { target: window, ...oCallContext }); })(jaxon.call.json, jaxon.call.query, jaxon.dialog.lib, jaxon.utils.dom, jaxon.utils.form, jaxon.utils.types); @@ -2208,7 +2219,7 @@ window.jaxon = jaxon; return true; } - const xElt = dom.getInnerObject(target, attr); + const xElt = dom.getInnerObject(attr, target); if (xElt !== null) { xElt.node[xElt.attr] = value; } @@ -2236,7 +2247,7 @@ window.jaxon = jaxon; return true; } - const xElt = dom.getInnerObject(target, attr); + const xElt = dom.getInnerObject(attr, target); if (xElt !== null) { xElt.node[xElt.attr] = xElt.node[xElt.attr] + value; } @@ -2264,7 +2275,7 @@ window.jaxon = jaxon; return true; } - const xElt = dom.getInnerObject(target, attr); + const xElt = dom.getInnerObject(attr, target); if (xElt !== null) { xElt.node[xElt.attr] = value + xElt.node[xElt.attr]; } @@ -2304,7 +2315,7 @@ window.jaxon = jaxon; */ self.replace = ({ target, attr, search, replace }) => { const sSearch = attr === 'innerHTML' ? dom.getBrowserHTML(search) : search; - const xElt = dom.getInnerObject(target, attr); + const xElt = dom.getInnerObject(attr, target); if (xElt !== null) { replaceText(xElt.node, xElt.attr, sSearch, replace); } diff --git a/dist/jaxon.core.min.js b/dist/jaxon.core.min.js index 642b859..eb9a2eb 100644 --- a/dist/jaxon.core.min.js +++ b/dist/jaxon.core.min.js @@ -6,4 +6,4 @@ @copyright Copyright (c) 2017 by Thierry Feuzeu, Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson @license https://opensource.org/license/bsd-3-clause/ BSD License */ -var jaxon={version:{major:"5",minor:"0",patch:"0rc-2"},debug:{verbose:{}},ajax:{callback:{},handler:{},parameters:{},request:{},response:{}},cmd:{body:{},script:{},event:{}},call:{json:{},query:{}},utils:{dom:{},form:{},queue:{},types:{},string:{},upload:{}},dom:{},dialog:{cmd:{},lib:{}},config:{}};!function(e){e.commonHeaders={"If-Modified-Since":"Sat, 1 Jan 2000 00:00:00 GMT"},e.postHeaders={},e.getHeaders={},e.waitCursor=!1,e.statusMessages=!1,e.baseDocument=document,e.requestURI=document.URL,e.defaultMode="asynchronous",e.defaultHttpVersion="HTTP/1.1",e.defaultContentType="application/x-www-form-urlencoded",e.defaultResponseDelayTime=1e3,e.convertResponseToJson=!0,e.defaultExpirationTime=1e4,e.defaultMethod="POST",e.defaultRetry=5,e.defaultReturnValue=!1,e.maxObjectDepth=20,e.maxObjectSize=2e3,e.commandQueueSize=1e3,e.requestQueueSize=1e3,e.httpRequestOptions={mode:"cors",cache:"no-cache",credentials:"same-origin",redirect:"manual"},e.setRequestOptions=t=>{if(void 0===e.requestURI)throw{code:10005};["commonHeaders","postHeaders","getHeaders"].forEach((n=>t[n]={...e[n],...t[n]}));const n={statusMessages:e.statusMessages,waitCursor:e.waitCursor,mode:e.defaultMode,method:e.defaultMethod,URI:e.requestURI,httpVersion:e.defaultHttpVersion,contentType:e.defaultContentType,convertResponseToJson:e.convertResponseToJson,retry:e.defaultRetry,returnValue:e.defaultReturnValue,maxObjectDepth:e.maxObjectDepth,maxObjectSize:e.maxObjectSize,context:window,upload:!1,aborted:!1};Object.keys(n).forEach((e=>t[e]=t[e]??n[e])),t.method=t.method.toUpperCase(),"GET"!==t.method&&(t.method="POST"),t.requestRetry=t.retry},e.status={update:{onRequest:()=>console.log("Sending Request..."),onWaiting:()=>console.log("Waiting for Response..."),onProcessing:()=>console.log("Processing..."),onComplete:()=>console.log("Done.")},dontUpdate:{onRequest:()=>{},onWaiting:()=>{},onProcessing:()=>{},onComplete:()=>{}}},e.cursor={update:{onWaiting:()=>{jaxon.config.baseDocument.body&&(jaxon.config.baseDocument.body.style.cursor="wait")},onComplete:()=>{jaxon.config.baseDocument.body&&(jaxon.config.baseDocument.body.style.cursor="auto")}},dontUpdate:{onWaiting:()=>{},onComplete:()=>{}}}}(jaxon.config),window.jaxon=jaxon,function(e,t,n){e.$=e=>e?t.isString(e)?n.getElementById(e):e:null;e.getBrowserHTML=t=>{const o=(()=>{const t=e.$("jaxon_temp_workspace");if(t)return t;if(!n.body)return null;const o=n.createElement("div");return o.setAttribute("id","jaxon_temp_workspace"),o.style.display="none",o.style.visibility="hidden",n.body.appendChild(o),o})();o.innerHTML=t;const r=o.innerHTML;return o.innerHTML="",r},e.willChange=(t,n,o)=>!!(t=e.$(t))&&o!=t[n],e.removeElement=t=>{(t=e.$(t))&&t.parentNode&&t.parentNode.removeChild&&t.parentNode.removeChild(t)},e.findFunction=(e,n=window)=>{if("toInt"===e&&n===window)return t.toInt;const o=e.split("."),r=o.length;for(let e=0;e{const n=t.split(".");t=n.pop();const o=n.length;for(let t=0;t{t.forEach((t=>{void 0!==t.childNodes&&"select-one"!==t.type&&"select-multiple"!==t.type&&n(e,t.childNodes,o,r),((e,t,n,o)=>{if(!t.name||"PARAM"===t.tagName)return;if(!n&&t.disabled)return;if(o!==t.name.substring(0,o.length))return;if(("radio"===t.type||"checkbox"===t.type)&&!t.checked)return;if("file"===t.type)return;const r=t.name,a="select-multiple"!==t.type?t.value:t.options.filter((({selected:e})=>e)).map((({value:e})=>e)),s=r.indexOf("[");if(s<0)return void(e[r]=a);let l=r.substring(0,s),i=r.substring(s);void 0===e[l]&&(e[l]={});let u=e;for(;i.length>0;){const e=i.substring(0,i.indexOf("]")+1),n=l,o=u;i=i.substring(i.indexOf("]")+1),u=u[l],l=e.substring(1,e.length-1),""===l&&("select-multiple"===t.type?(l=n,u=o):l=u.length),void 0===l&&(l=Object.keys(o[n]).length),u[l]=u[l]||{}}u[l]=a})(e,t,o,r)}))};e.getValues=(e,o,r="")=>{const a=!0===o,s=r??"",l=t.$(e),i={};return l&&l.childNodes&&n(i,l.childNodes,a,s),i}}(jaxon.utils.form,jaxon.utils.dom),function(e){e.create=e=>({start:0,count:0,size:e,end:0,elements:[],paused:!1}),e.empty=e=>e.count<=0,e.full=e=>e.count>=e.size,e.push=(t,n)=>{if(e.full(t))throw{code:10003};return t.elements[t.end]=n,++t.end>=t.size&&(t.end=0),++t.count},e.pushFront=(t,n)=>{if(e.full(t))throw{code:10003};return e.empty(t)?e.push(t,n):(--t.start<0&&(t.start=t.size-1),t.elements[t.start]=n,++t.count)},e.pop=t=>{if(e.empty(t))return null;let n=t.elements[t.start];return delete t.elements[t.start],++t.start>=t.size&&(t.start=0),t.count--,n},e.peek=t=>e.empty(t)?null:t.elements[t.start]}(jaxon.utils.queue),function(e){"use strict";let t=[],n=!1,o=!1;const r=()=>{n||(n=!0,t.forEach((e=>e.fn.call(window,e.ctx))),t=[])};e.ready=function(e,a){n?setTimeout((function(){e(a)}),1):(t.push({fn:e,ctx:a}),"complete"===document.readyState||!document.attachEvent&&"interactive"===document.readyState?setTimeout(r,1):o||(document.addEventListener("DOMContentLoaded",r,!1),window.addEventListener("load",r,!1),o=!0))}}(jaxon.utils.dom),function(e){e.doubleQuotes=e=>void 0!==e&&e.replace(new RegExp("'","g"),'"'),e.singleQuotes=e=>void 0!==e&&e.replace(new RegExp('"',"g"),"'"),e.stripOnPrefix=e=>0===(e=e.toLowerCase()).indexOf("on")?e.replace(/on/,""):e,e.addOnPrefix=e=>0!==(e=e.toLowerCase()).indexOf("on")?"on"+e:e,String.prototype.supplant||(String.prototype.supplant=function(e){return this.replace(/\{([^{}]*)\}/g,((t,n)=>{const o=e[n],r=typeof o;return"string"===r||"number"===r?o:t}))})}(jaxon.utils.string),function(e){e.of=e=>Object.prototype.toString.call(e).slice(8,-1).toLowerCase(),e.isObject=t=>"object"===e.of(t),e.isArray=t=>"array"===e.of(t),e.isString=t=>"string"===e.of(t),e.isFunction=t=>"function"===e.of(t),e.toInt=e=>parseInt(e),Array.prototype.top||(Array.prototype.top=function(){return this.length>0?this[this.length-1]:void 0})}(jaxon.utils.types),function(e,t,n){e.initialize=e=>{(e=>{if(!e.upload)return!1;e.upload={id:e.upload,input:null,form:null};const o=t.$(e.upload.id);return o?"file"!==o.type?(n.log("The upload input field with id "+e.upload.id+" is not of type file"),!1):0===o.files.length?(n.log("There is no file selected for upload in input field with id "+e.upload.id),!1):void 0===o.name?(n.log("The upload input field with id "+e.upload.id+" has no name attribute"),!1):(e.upload.input=o,e.upload.form=o.form,!0):(n.log("Unable to find input field for file upload with id "+e.upload.id),!1)})(e)||(e.postHeaders["content-type"]=e.contentType)}}(jaxon.utils.upload,jaxon.utils.dom,console),function(e,t,n,o,r,a){const s={comparator:()=>!1,command:e=>console.error("Unexpected command: "+JSON.stringify({call:e}))},l={eq:(e,t)=>e==t,teq:(e,t)=>e===t,ne:(e,t)=>e!=t,nte:(e,t)=>e!==t,gt:(e,t)=>e>t,ge:(e,t)=>e>=t,lt:(e,t)=>ee<=t},i=(e,t)=>{if(!(e=>a.isObject(e)&&e._type)(e))return e;const{_type:n,_name:s}=e;switch(n){case"form":return r.getValues(s);case"html":return o.$(s).innerHTML;case"input":return o.$(s).value;case"checked":return o.$(s).checked;case"expr":return f(e);case"_":return"this"===s?t:void 0;default:return}},u=(e,t)=>e.map((e=>i(e,t))),c={select:({_name:e,context:n=null},o,r)=>{switch(e){case"this":return t.select(r.target);case"event":return r.event;case"window":return window;default:return t.select(e,i(n,o))}},event:({_name:e,func:t},n,o)=>(n.on(e,(e=>f(t,{...o,event:e,target:e.currentTarget,value:null}))),n),func:({_name:e,args:t=[]},n,r)=>{const a=o.findFunction(e);return a?a.apply(r,u(t,n)):null},method:({_name:e,args:t=[]},n)=>{const r=o.findFunction(e,n);return r?r.apply(n,u(t,n)):"toInt"===e?a.toInt(n):null},attr:({_name:e,value:t},n)=>{const r=o.getInnerObject(n,e);return void 0!==t&&(r.node[r.attr]=i(t,n)),r.node[r.attr]}},d=(e,t)=>{const{value:n}=t;return(c[e._type]??s.command)(e,n,t)};e.execCall=(e,t)=>a.isObject(e)?d(e,t||{target:window,value:null}):null;const p=(e,t)=>e.reduce(((e,n)=>d(n,{...t,value:e})),null);e.makePhrase=({str:e,args:t})=>{const n={};let o=1;return t.forEach((e=>n[o++]=i(e))),e.supplant(n)};const m=t=>{if(t){const{lib:o,type:r,content:{title:a,phrase:s}}=t;n.get(o).alert(r,e.makePhrase(s),a)}},f=(t,o)=>{const{calls:r,question:a,condition:u,message:c}=t;if(a)((t,o,r,a)=>{const{lib:s,phrase:l}=o;n.get(s).confirm(e.makePhrase(l),"",(()=>p(t,a)),(()=>m(r)))})(r,a,c,o);else{if(!u)return p(r,o);((e,t,n,o)=>{const[r,a,u]=t;(l[r]??s.comparator)(i(a),i(u))?p(e,o):m(n)})(r,u,c,o)}};e.execExpr=(e,t)=>a.isObject(e)?f(e,t||{target:window,value:null}):null}(jaxon.call.json,jaxon.call.query,jaxon.dialog.lib,jaxon.utils.dom,jaxon.utils.form,jaxon.utils.types),function(e,t){e.jq=t,e.select=(t,n=null)=>n?e.jq(t,n):e.jq(t)}(jaxon.call.query,window.jQuery),function(e,t,n){const o=e=>({timer:null,delay:e}),r=["onInitialize","onProcessParams","onPrepare","onRequest","onResponseDelay","onExpiration","beforeResponseProcessing","onFailure","onRedirect","onSuccess","onComplete"];e.create=(e,t)=>({timers:{onResponseDelay:o(e??n.defaultResponseDelayTime),onExpiration:o(t??n.defaultExpirationTime)},onInitialize:null,onProcessParams:null,onPrepare:null,onRequest:null,onResponseDelay:null,onExpiration:null,beforeResponseProcessing:null,onFailure:null,onRedirect:null,onSuccess:null,onComplete:null}),e.callback=e.create(),e.initCallbacks=t=>{const n=e.create();let o=!1;r.forEach((e=>{void 0!==t[e]&&(n[e]=t[e],o=!0,delete t[e])})),void 0!==t.callback?(void 0===t.callback.timers&&(t.callback.timers={}),o&&(t.callback=[t.callback,n])):t.callback=n};const a=n=>n.callback?t.isArray(n.callback)?[e.callback,...n.callback]:[e.callback,n.callback]:[e.callback];e.execute=(e,n)=>a(e).forEach((o=>((e,n,o)=>{const r=e[n],a=e.timers?e.timers[n]:null;r&&t.isFunction(r)&&(a?a.timer=setTimeout((()=>r(o)),a.delay):r(o))})(o,n,e)));e.clearTimer=(e,t)=>a(e).forEach((e=>((e,t)=>{const n=e.timers[t];void 0!==n&&null!==n.timer&&clearTimeout(n.timer)})(e,t)))}(jaxon.ajax.callback,jaxon.utils.types,jaxon.config),function(e,t,n,o,r,a,s){const l={};e.q={send:r.create(t.requestQueueSize),recv:r.create(2*t.requestQueueSize)},e.register=(e,t,n="")=>l[e]={desc:n,func:t},e.unregister=e=>{const t=l[e];return t?(delete l[e],t.func):null},e.isRegistered=({name:e})=>void 0!==e&&void 0!==l[e];e.execute=t=>{const{name:n,args:o}=t;if(!e.isRegistered({name:n}))return!0;const r=o?.id;return r&&(o.target=a.$(r)),((e,t,n)=>{const{func:o,desc:r}=l[e];return o(t,{...n,desc:r})})(n,o,t)},e.popAsyncRequest=e=>r.empty(e)||"synchronous"===r.peek(e).mode?null:r.pop(e),e.sleep=({duration:e},{commandQueue:t})=>(t.paused=!0,setTimeout((()=>{t.paused=!1,n.processCommands(t)}),100*e),!0);const i=(e,t=0)=>{for(;t>0&&e.count>1&&null!==r.pop(e);)--t;e.paused=!1,n.processCommands(e)};e.confirm=({count:e,question:{lib:t,phrase:n}},{commandQueue:r})=>{r.paused=!0;return s.get(t).confirm(o.makePhrase(n),"",(()=>i(r)),(()=>i(r,e))),!0}}(jaxon.ajax.handler,jaxon.config,jaxon.ajax.response,jaxon.call.json,jaxon.utils.queue,jaxon.utils.dom,jaxon.dialog.lib),function(e,t,n){e.bags={};const o=({func:o,parameters:r,bags:a=[]},s)=>{const l=new Date;var i;s("jxnr",l.getTime()),s("jxnv",`${n.major}.${n.minor}.${n.patch}`),Object.keys(o).forEach((e=>s(e,encodeURIComponent(o[e])))),[...r].forEach((e=>s("jxnargs[]",(e=>{if(null==e)return"*";const n=t.of(e);if("object"===n||"array"===n)try{return encodeURIComponent(JSON.stringify(e))}catch(t){e=""}return e=encodeURIComponent(e),"string"===n?"S"+e:"boolean"===n?"B"+e:"number"===n?"N"+e:e})(e)))),a.length>0&&s("jxnbags",encodeURIComponent((i=a,JSON.stringify(i.reduce(((t,n)=>({...t,[n]:e.bags[n]??"*"})),{})))))};e.process=e=>{e.requestURI=e.URI,e.requestData=(({upload:e})=>e&&e.ajax&&e.input)(e)?(e=>{const t=new FormData;o(e,((e,n)=>t.append(e,n)));const n=e.upload.input;return n.files&&n.files.forEach((e=>t.append(n.name,e))),t})(e):(e=>{const t=[];return o(e,((e,n)=>t.push(e+"="+n))),"POST"===e.method?t.join("&"):(e.requestURI+=-1===e.requestURI.indexOf("?")?"?":"&",e.requestURI+=t.join("&"),"")})(e)}}(jaxon.ajax.parameters,jaxon.utils.types,jaxon.version),function(e,t,n,o,r,a,s,l){const i=e=>{r.execute(e,"onPrepare"),e.httpRequestOptions={...t.httpRequestOptions,method:e.method,headers:{...e.commonHeaders,..."POST"===e.method?e.postHeaders:e.getHeaders},body:e.requestData},e.responseConverter=t=>(e.response=t,e.convertResponseToJson?t.json():t.text()),e.responseHandler=t=>{e.responseContent=t,l.empty(a.q.send)||"synchronous"===e.mode?o.received(e):l.push(a.q.recv,e)},e.errorHandler=t=>{throw r.execute(e,"onFailure"),t},e.responseProcessor||(e.responseProcessor=o.jsonProcessor)},u=e=>(--e.requestRetry,e.status.onRequest(),r.execute(e,"onResponseDelay"),r.execute(e,"onExpiration"),r.execute(e,"onRequest"),e.cursor.onWaiting(),e.status.onWaiting(),fetch(e.requestURI,e.httpRequestOptions).then(e.responseConverter).then(e.responseHandler).catch(e.errorHandler),e.returnValue);e.complete=e=>{if(r.execute(e,"onComplete"),e.cursor.onComplete(),e.status.onComplete(),(e=>{delete e.func,delete e.URI,delete e.requestURI,delete e.requestData,delete e.requestRetry,delete e.httpRequestOptions,delete e.responseHandler,delete e.responseConverter,delete e.responseContent,delete e.response,delete e.errorHandler})(e),"synchronous"===e.mode){for(l.pop(a.q.send),l.pop(a.q.recv);null!==(recvRequest=a.popAsyncRequest(a.q.recv));)o.received(recvRequest);for(;null!==(nextRequest=a.popAsyncRequest(a.q.send));)u(nextRequest);null!==(nextRequest=l.peek(a.q.send))&&u(nextRequest)}},e.abort=t=>{t.aborted=!0,e.complete(t)},e.execute=(e,o)=>{if(void 0===e)return!1;const c=o??{};for(c.func=e,(e=>{r.execute(e,"onInitialize"),t.setRequestOptions(e),r.initCallbacks(e),e.status=e.statusMessages?t.status.update:t.status.dontUpdate,e.cursor=e.waitCursor?t.cursor.update:t.cursor.dontUpdate,s.initialize(e),e.submit=l.empty(a.q.send),"synchronous"===e.mode&&(l.push(a.q.send,e),l.push(a.q.recv,e)),e.submit||l.push(a.q.send,e)})(c),r.execute(c,"onProcessParams"),n.process(c);c.requestRetry>0;)try{return i(c),c.submit?u(c):null}catch(e){if(r.execute(c,"onFailure"),0===c.requestRetry)throw e}return!0}}(jaxon.ajax.request,jaxon.config,jaxon.ajax.parameters,jaxon.ajax.response,jaxon.ajax.callback,jaxon.ajax.handler,jaxon.utils.upload,jaxon.utils.queue),function(e,t,n,o,r,a,s){const l=[0,200],i=[400,401,402,403,404,500,501,502,503],u=[301,302,307],c=e=>{try{return n.execute(e)}catch(e){console.log(e)}return!0};e.processCommands=e=>{let t=null;for(;!e.paused&&null!==(t=a.pop(e));)if(!c(t))return!1;return!0},e.jsonProcessor=t=>l.indexOf(t.response.status)>=0?(r.execute(t,"onSuccess"),(e=>{if(!s.isObject(e.responseContent))return;const{debug:{message:t}={},jxn:{value:n,commands:o=[]}={}}=e.responseContent;e.status.onProcessing(),n&&(e.returnValue=n),t&&console.log(t);let r=0;o.forEach((t=>a.push(e.commandQueue,{fullName:"*unknown*",...t,sequence:r++,commandQueue:e.commandQueue,request:e,context:e.context}))),a.push(e.commandQueue,{name:"response.complete",fullName:"Response Complete",sequence:r,commandQueue:e.commandQueue,request:e,context:e.context})})(t),e.processCommands(t.commandQueue),t.returnValue):u.indexOf(t.response.status)>=0?(r.execute(t,"onRedirect"),o.complete(t),window.location=t.response.headers.get("location"),t.returnValue):i.indexOf(t.response.status)>=0?(r.execute(t,"onFailure"),o.complete(t),t.returnValue):t.returnValue,e.received=e=>e.aborted?null:(e.commandQueue=a.create(t.commandQueueSize),r.clearTimer(e,"onExpiration"),r.clearTimer(e,"onResponseDelay"),r.execute(e,"beforeResponseProcessing"),e.responseProcessor(e))}(jaxon.ajax.response,jaxon.config,jaxon.ajax.handler,jaxon.ajax.request,jaxon.ajax.callback,jaxon.utils.queue,jaxon.utils.types),function(e,t,n,o){e.assign=({target:e,attr:n,value:o})=>{if("innerHTML"===n)return e.innerHTML=o,!0;if("outerHTML"===n)return e.outerHTML=o,!0;const r=t.getInnerObject(e,n);return null!==r&&(r.node[r.attr]=o),!0},e.append=({target:e,attr:n,value:o})=>{if("innerHTML"===n)return e.innerHTML=e.innerHTML+o,!0;if("outerHTML"===n)return e.outerHTML=e.outerHTML+o,!0;const r=t.getInnerObject(e,n);return null!==r&&(r.node[r.attr]=r.node[r.attr]+o),!0},e.prepend=({target:e,attr:n,value:o})=>{if("innerHTML"===n)return e.innerHTML=o+e.innerHTML,!0;if("outerHTML"===n)return e.outerHTML=o+e.outerHTML,!0;const r=t.getInnerObject(e,n);return null!==r&&(r.node[r.attr]=o+r.node[r.attr]),!0};e.replace=({target:e,attr:o,search:r,replace:a})=>{const s="innerHTML"===o?t.getBrowserHTML(r):r,l=t.getInnerObject(e,o);return null!==l&&((e,o,r,a)=>{const s=n.isFunction(e[o]),l=(s?e[o].join(""):e[o]).replaceAll(r,a);(s||t.willChange(e,o,l))&&(e[o]=l)})(l.node,l.attr,s,a),!0},e.clear=({target:t,attr:n})=>(e.assign({target:t,attr:n,value:""}),!0),e.remove=({target:e})=>(t.removeElement(e),!0);const r=(e,t)=>{const n=o.createElement(e);return n.setAttribute("id",t),n};e.create=({target:e,tag:{id:t,name:n}})=>(e&&e.appendChild(r(n,t)),!0),e.insert=({target:e,tag:{id:t,name:n}})=>(e&&e.parentNode&&e.parentNode.insertBefore(r(n,t),e),!0),e.insertAfter=({target:e,tag:{id:t,name:n}})=>(e&&e.parentNode&&e.parentNode.insertBefore(r(n,t),e.nextSibling),!0)}(jaxon.cmd.body,jaxon.utils.dom,jaxon.utils.types,jaxon.config.baseDocument),function(e,t,n,o){e.addHandler=({target:e,event:t,func:r})=>(e.addEventListener(o.stripOnPrefix(t),n.findFunction(r),!1),!0),e.removeHandler=({target:e,event:t,func:r})=>(e.removeEventListener(o.stripOnPrefix(t),n.findFunction(r),!1),!0);const r=(e,n,o)=>{t.execExpr({_type:"expr",...o},{event:e,target:n})};e.addEventHandler=({target:e,event:t,func:n,options:a})=>(e.addEventListener(o.stripOnPrefix(t),(t=>r(t,e,n)),a??!1),!0),e.setEventHandler=({target:e,event:t,func:n})=>(e[o.addOnPrefix(t)]=t=>r(t,e,n),!0)}(jaxon.cmd.event,jaxon.call.json,jaxon.utils.dom,jaxon.utils.string),function(e,t,n,o){e.call=({func:e,args:n},{context:o={}})=>(t.execCall({_type:"func",_name:e,args:n},o),!0),e.redirect=({url:e,delay:t})=>t<=0?(window.location=e,!0):(window.setTimeout((()=>window.location=e),1e3*t),!0),e.databag=({values:e})=>{for(const t in e)n.bags[t]=e[t];return!0},e.jquery=({selector:e})=>(t.execExpr(e),!0);const r=(e,t)=>e.map((e=>o.isObject(e)&&"page"===e._type?parseInt(t.parentNode.getAttribute("data-page")):e));e.paginate=({target:e,func:{calls:[n]}})=>{const o=e.querySelectorAll("li.enabled > a"),{args:a}=n;return o.forEach((e=>e.addEventListener("click",(()=>t.execCall({...n,_type:"func",args:r(a,e)}))))),!0}}(jaxon.cmd.script,jaxon.call.json,jaxon.ajax.parameters,jaxon.utils.types),function(e,t,n){const o=(e,n)=>{t.has(e)||console.warn(`Unable to find a Jaxon dialog library with name "${e}".`);const o=t.get(e);return o[n]?o:(console.error(`The chosen Jaxon dialog library doesn't implement the "${n}" function.`),null)};e.showMessage=({lib:e,type:t,content:r})=>{const{title:a,phrase:s}=r,l=o(e,"alert");return l&&l.alert(t,n.makePhrase(s),a),!0},e.showModal=({lib:e,dialog:{title:t,content:n,buttons:r,options:a}})=>{const s=o(e,"show");return s&&s.show(t,n,r,a),!0},e.hideModal=({lib:e})=>{const t=o(e,"hide");return t&&t.hide(),!0}}(jaxon.dialog.cmd,jaxon.dialog.lib,jaxon.call.json),function(e,t,n,o,r){const a={yes:"Yes",no:"No"};e.default={},e.has=t=>!!e[t],e.get=t=>e[t]??e.default,e.register=(s,l)=>{e[s]={},l(e[s],{types:t,dom:n,js:o,jq:r,labels:a})}}(jaxon.dialog.lib,jaxon.utils.types,jaxon.dom,jaxon.call.json,window.jQuery),jaxon.dialog.lib.register("default",(e=>{e.alert=(e,t,n)=>alert(n?`${n}
${t}`:t),e.confirm=(e,t,n,o)=>{confirm(t?`${t}
${e}`:e)?n():o&&o()}})),jaxon.request=jaxon.ajax.request.execute,jaxon.register=jaxon.ajax.handler.register,jaxon.$=jaxon.utils.dom.$,jaxon.jq=jaxon.call.query.jq,jaxon.exec=jaxon.call.json.execExpr,jaxon.dom.ready=jaxon.utils.dom.ready,jaxon.getFormValues=jaxon.utils.form.getValues,jaxon.isLoaded=!0,function(e,t,n,o){e("response.complete",((e,{request:t})=>(n.request.complete(t),!0)),"Response complete"),e("dom.assign",t.body.assign,"Dom::Assign"),e("dom.append",t.body.append,"Dom::Append"),e("dom.prepend",t.body.prepend,"Dom::Prepend"),e("dom.replace",t.body.replace,"Dom::Replace"),e("dom.clear",t.body.clear,"Dom::Clear"),e("dom.remove",t.body.remove,"Dom::Remove"),e("dom.create",t.body.create,"Dom::Create"),e("dom.insert.before",t.body.insert,"Dom::InsertBefore"),e("dom.insert.after",t.body.insertAfter,"Dom::InsertAfter"),e("script.call",t.script.call,"Script::CallJsFunction"),e("script.redirect",t.script.redirect,"Script::Redirect"),e("script.sleep",n.handler.sleep,"Handler::Sleep"),e("script.confirm",n.handler.confirm,"Handler::Confirm"),e("handler.event.set",t.event.setEventHandler,"Script::SetEventHandler"),e("handler.event.add",t.event.addEventHandler,"Script::AddEventHandler"),e("handler.add",t.event.addHandler,"Script::AddHandler"),e("handler.remove",t.event.removeHandler,"Script::RemoveHandler"),e("script.debug",(({message:e})=>(console.log(e),!0)),"Debug message"),e("jquery.call",t.script.jquery,"JQuery::CallSelector"),e("pg.paginate",t.script.paginate,"Paginator::Paginate"),e("databag.set",t.script.databag,"Databag:SetValues"),e("dialog.message",o.cmd.showMessage,"Dialog:ShowMessage"),e("dialog.modal.show",o.cmd.showModal,"Dialog:ShowModal"),e("dialog.modal.hide",o.cmd.hideModal,"Dialog:HideModal")}(jaxon.register,jaxon.cmd,jaxon.ajax,jaxon.dialog); \ No newline at end of file +var jaxon={version:{major:"5",minor:"0",patch:"0rc-2"},debug:{verbose:{}},ajax:{callback:{},handler:{},parameters:{},request:{},response:{}},cmd:{body:{},script:{},event:{}},call:{json:{},query:{}},utils:{dom:{},form:{},queue:{},types:{},string:{},upload:{}},dom:{},dialog:{cmd:{},lib:{}},config:{}};!function(e){e.commonHeaders={"If-Modified-Since":"Sat, 1 Jan 2000 00:00:00 GMT"},e.postHeaders={},e.getHeaders={},e.waitCursor=!1,e.statusMessages=!1,e.baseDocument=document,e.requestURI=document.URL,e.defaultMode="asynchronous",e.defaultHttpVersion="HTTP/1.1",e.defaultContentType="application/x-www-form-urlencoded",e.defaultResponseDelayTime=1e3,e.convertResponseToJson=!0,e.defaultExpirationTime=1e4,e.defaultMethod="POST",e.defaultRetry=5,e.defaultReturnValue=!1,e.maxObjectDepth=20,e.maxObjectSize=2e3,e.commandQueueSize=1e3,e.requestQueueSize=1e3,e.httpRequestOptions={mode:"cors",cache:"no-cache",credentials:"same-origin",redirect:"manual"},e.setRequestOptions=t=>{if(void 0===e.requestURI)throw{code:10005};["commonHeaders","postHeaders","getHeaders"].forEach((n=>t[n]={...e[n],...t[n]}));const n={statusMessages:e.statusMessages,waitCursor:e.waitCursor,mode:e.defaultMode,method:e.defaultMethod,URI:e.requestURI,httpVersion:e.defaultHttpVersion,contentType:e.defaultContentType,convertResponseToJson:e.convertResponseToJson,retry:e.defaultRetry,returnValue:e.defaultReturnValue,maxObjectDepth:e.maxObjectDepth,maxObjectSize:e.maxObjectSize,context:window,upload:!1,aborted:!1};Object.keys(n).forEach((e=>t[e]=t[e]??n[e])),t.method=t.method.toUpperCase(),"GET"!==t.method&&(t.method="POST"),t.requestRetry=t.retry},e.status={update:{onRequest:()=>console.log("Sending Request..."),onWaiting:()=>console.log("Waiting for Response..."),onProcessing:()=>console.log("Processing..."),onComplete:()=>console.log("Done.")},dontUpdate:{onRequest:()=>{},onWaiting:()=>{},onProcessing:()=>{},onComplete:()=>{}}},e.cursor={update:{onWaiting:()=>{jaxon.config.baseDocument.body&&(jaxon.config.baseDocument.body.style.cursor="wait")},onComplete:()=>{jaxon.config.baseDocument.body&&(jaxon.config.baseDocument.body.style.cursor="auto")}},dontUpdate:{onWaiting:()=>{},onComplete:()=>{}}}}(jaxon.config),window.jaxon=jaxon,function(e,t,n){e.$=e=>e?t.isString(e)?n.getElementById(e):e:null;e.getBrowserHTML=t=>{const o=(()=>{const t=e.$("jaxon_temp_workspace");if(t)return t;if(!n.body)return null;const o=n.createElement("div");return o.setAttribute("id","jaxon_temp_workspace"),o.style.display="none",o.style.visibility="hidden",n.body.appendChild(o),o})();o.innerHTML=t;const r=o.innerHTML;return o.innerHTML="",r},e.willChange=(t,n,o)=>!!(t=e.$(t))&&o!=t[n],e.removeElement=t=>{(t=e.$(t))&&t.parentNode&&t.parentNode.removeChild&&t.parentNode.removeChild(t)},e.findFunction=(e,n=window)=>{if("toInt"===e&&n===window)return t.toInt;const o=e.split("."),r=o.length;for(let e=0;e{const n=e.split(".");e=n.pop();const o=n.length;for(let e=0;e{t.forEach((t=>{void 0!==t.childNodes&&"select-one"!==t.type&&"select-multiple"!==t.type&&n(e,t.childNodes,o,r),((e,t,n,o)=>{if(!t.name||"PARAM"===t.tagName)return;if(!n&&t.disabled)return;if(o!==t.name.substring(0,o.length))return;if(("radio"===t.type||"checkbox"===t.type)&&!t.checked)return;if("file"===t.type)return;const r=t.name,a="select-multiple"!==t.type?t.value:t.options.filter((({selected:e})=>e)).map((({value:e})=>e)),s=r.indexOf("[");if(s<0)return void(e[r]=a);let l=r.substring(0,s),i=r.substring(s);void 0===e[l]&&(e[l]={});let u=e;for(;i.length>0;){const e=i.substring(0,i.indexOf("]")+1),n=l,o=u;i=i.substring(i.indexOf("]")+1),u=u[l],l=e.substring(1,e.length-1),""===l&&("select-multiple"===t.type?(l=n,u=o):l=u.length),void 0===l&&(l=Object.keys(o[n]).length),u[l]=u[l]||{}}u[l]=a})(e,t,o,r)}))};e.getValues=(e,o,r="")=>{const a=!0===o,s=r??"",l=t.$(e),i={};return l&&l.childNodes&&n(i,l.childNodes,a,s),i}}(jaxon.utils.form,jaxon.utils.dom),function(e){e.create=e=>({start:0,count:0,size:e,end:0,elements:[],paused:!1}),e.empty=e=>e.count<=0,e.full=e=>e.count>=e.size,e.push=(t,n)=>{if(e.full(t))throw{code:10003};return t.elements[t.end]=n,++t.end>=t.size&&(t.end=0),++t.count},e.pushFront=(t,n)=>{if(e.full(t))throw{code:10003};return e.empty(t)?e.push(t,n):(--t.start<0&&(t.start=t.size-1),t.elements[t.start]=n,++t.count)},e.pop=t=>{if(e.empty(t))return null;let n=t.elements[t.start];return delete t.elements[t.start],++t.start>=t.size&&(t.start=0),t.count--,n},e.peek=t=>e.empty(t)?null:t.elements[t.start]}(jaxon.utils.queue),function(e){"use strict";let t=[],n=!1,o=!1;const r=()=>{n||(n=!0,t.forEach((e=>e.fn.call(window,e.ctx))),t=[])};e.ready=function(e,a){n?setTimeout((function(){e(a)}),1):(t.push({fn:e,ctx:a}),"complete"===document.readyState||!document.attachEvent&&"interactive"===document.readyState?setTimeout(r,1):o||(document.addEventListener("DOMContentLoaded",r,!1),window.addEventListener("load",r,!1),o=!0))}}(jaxon.utils.dom),function(e){e.doubleQuotes=e=>void 0!==e&&e.replace(new RegExp("'","g"),'"'),e.singleQuotes=e=>void 0!==e&&e.replace(new RegExp('"',"g"),"'"),e.stripOnPrefix=e=>0===(e=e.toLowerCase()).indexOf("on")?e.replace(/on/,""):e,e.addOnPrefix=e=>0!==(e=e.toLowerCase()).indexOf("on")?"on"+e:e,String.prototype.supplant||(String.prototype.supplant=function(e){return this.replace(/\{([^{}]*)\}/g,((t,n)=>{const o=e[n],r=typeof o;return"string"===r||"number"===r?o:t}))})}(jaxon.utils.string),function(e){e.of=e=>Object.prototype.toString.call(e).slice(8,-1).toLowerCase(),e.isObject=t=>"object"===e.of(t),e.isArray=t=>"array"===e.of(t),e.isString=t=>"string"===e.of(t),e.isFunction=t=>"function"===e.of(t),e.toInt=e=>parseInt(e),Array.prototype.top||(Array.prototype.top=function(){return this.length>0?this[this.length-1]:void 0})}(jaxon.utils.types),function(e,t,n){e.initialize=e=>{(e=>{if(!e.upload)return!1;e.upload={id:e.upload,input:null,form:null};const o=t.$(e.upload.id);return o?"file"!==o.type?(n.log("The upload input field with id "+e.upload.id+" is not of type file"),!1):0===o.files.length?(n.log("There is no file selected for upload in input field with id "+e.upload.id),!1):void 0===o.name?(n.log("The upload input field with id "+e.upload.id+" has no name attribute"),!1):(e.upload.input=o,e.upload.form=o.form,!0):(n.log("Unable to find input field for file upload with id "+e.upload.id),!1)})(e)||(e.postHeaders["content-type"]=e.contentType)}}(jaxon.utils.upload,jaxon.utils.dom,console),function(e,t,n,o,r,a){const s={comparator:()=>!1,command:e=>{console.error("Unexpected command: "+JSON.stringify({call:e}))}},l={eq:(e,t)=>e==t,teq:(e,t)=>e===t,ne:(e,t)=>e!=t,nte:(e,t)=>e!==t,gt:(e,t)=>e>t,ge:(e,t)=>e>=t,lt:(e,t)=>ee<=t},i=e=>a.isObject(e)&&e._type,u=(e,t)=>{if(!i(e))return e;const{_type:n,_name:a}=e;switch(n){case"form":return r.getValues(a);case"html":return o.$(a).innerHTML;case"input":return o.$(a).value;case"checked":return o.$(a).checked;case"expr":return g(e,{target:window});case"_":return"this"===a?t:void 0;default:return}},c=(e,t)=>e.map((e=>u(e,t))),d={select:({_name:e,context:n=null},o)=>{switch(e){case"this":return t.select(o.target);case"event":return o.event;default:return t.select(e,n)}},event:({_name:e,func:t},n,o)=>(o.on(e,(e=>g(t,{...n,event:e,target:e.currentTarget}))),o),func:({_name:e,args:t=[]},n,r)=>{const a=o.findFunction(e);return a?a.apply(n,c(t,r)):void 0},method:({_name:e,args:t=[]},n,r)=>{const s=o.findFunction(e,r);return s?s.apply(r,c(t,r)):"toInt"===e?a.toInt(r):void 0},attr:({_name:e,value:t},n,r)=>{const a=o.getInnerObject(e,r||n.target);if(a)return void 0!==t&&(a.node[a.attr]=u(t,r)),a.node[a.attr]}},p=(e,t,n)=>(i(e)?d[e._type]:s.command)(e,t,n);e.execCall=(e,t)=>p(e,{target:window,...t});const m=(e,t)=>{let n;const o=e.length;for(let r=0;r{const n={};let o=1;return t.forEach((e=>n[o++]=u(e))),e.supplant(n)};const f=t=>{if(t){const{lib:o,type:r,content:{title:a,phrase:s}}=t;n.get(o).alert(r,e.makePhrase(s),a)}},g=(t,o)=>{const{calls:r,question:a,condition:i,message:c}=t;if(a)((t,o,r,a)=>{const{lib:s,phrase:l}=o;n.get(s).confirm(e.makePhrase(l),"",(()=>m(t,a)),(()=>f(r)))})(r,a,c,o);else{if(!i)return m(r,o);((e,t,n,o)=>{const[r,a,i]=t;(l[r]??s.comparator)(u(a),u(i))?m(e,o):f(n)})(r,i,c,o)}};e.execExpr=(e,t)=>a.isObject(e)?g(e,{target:window,...t}):null}(jaxon.call.json,jaxon.call.query,jaxon.dialog.lib,jaxon.utils.dom,jaxon.utils.form,jaxon.utils.types),function(e,t){e.jq=t,e.select=(t,n=null)=>n?e.jq(t,n):e.jq(t)}(jaxon.call.query,window.jQuery),function(e,t,n){const o=e=>({timer:null,delay:e}),r=["onInitialize","onProcessParams","onPrepare","onRequest","onResponseDelay","onExpiration","beforeResponseProcessing","onFailure","onRedirect","onSuccess","onComplete"];e.create=(e,t)=>({timers:{onResponseDelay:o(e??n.defaultResponseDelayTime),onExpiration:o(t??n.defaultExpirationTime)},onInitialize:null,onProcessParams:null,onPrepare:null,onRequest:null,onResponseDelay:null,onExpiration:null,beforeResponseProcessing:null,onFailure:null,onRedirect:null,onSuccess:null,onComplete:null}),e.callback=e.create(),e.initCallbacks=t=>{const n=e.create();let o=!1;r.forEach((e=>{void 0!==t[e]&&(n[e]=t[e],o=!0,delete t[e])})),void 0!==t.callback?(void 0===t.callback.timers&&(t.callback.timers={}),o&&(t.callback=[t.callback,n])):t.callback=n};const a=n=>n.callback?t.isArray(n.callback)?[e.callback,...n.callback]:[e.callback,n.callback]:[e.callback];e.execute=(e,n)=>a(e).forEach((o=>((e,n,o)=>{const r=e[n],a=e.timers?e.timers[n]:null;r&&t.isFunction(r)&&(a?a.timer=setTimeout((()=>r(o)),a.delay):r(o))})(o,n,e)));e.clearTimer=(e,t)=>a(e).forEach((e=>((e,t)=>{const n=e.timers[t];void 0!==n&&null!==n.timer&&clearTimeout(n.timer)})(e,t)))}(jaxon.ajax.callback,jaxon.utils.types,jaxon.config),function(e,t,n,o,r,a,s){const l={};e.q={send:r.create(t.requestQueueSize),recv:r.create(2*t.requestQueueSize)},e.register=(e,t,n="")=>l[e]={desc:n,func:t},e.unregister=e=>{const t=l[e];return t?(delete l[e],t.func):null},e.isRegistered=({name:e})=>void 0!==e&&void 0!==l[e];e.execute=t=>{const{name:n,args:o}=t;if(!e.isRegistered({name:n}))return!0;const r=o?.id;return r&&(o.target=a.$(r)),((e,t,n)=>{const{func:o,desc:r}=l[e];return o(t,{...n,desc:r})})(n,o,t)},e.popAsyncRequest=e=>r.empty(e)||"synchronous"===r.peek(e).mode?null:r.pop(e),e.sleep=({duration:e},{commandQueue:t})=>(t.paused=!0,setTimeout((()=>{t.paused=!1,n.processCommands(t)}),100*e),!0);const i=(e,t=0)=>{for(;t>0&&e.count>1&&null!==r.pop(e);)--t;e.paused=!1,n.processCommands(e)};e.confirm=({count:e,question:{lib:t,phrase:n}},{commandQueue:r})=>{r.paused=!0;return s.get(t).confirm(o.makePhrase(n),"",(()=>i(r)),(()=>i(r,e))),!0}}(jaxon.ajax.handler,jaxon.config,jaxon.ajax.response,jaxon.call.json,jaxon.utils.queue,jaxon.utils.dom,jaxon.dialog.lib),function(e,t,n){e.bags={};const o=({func:o,parameters:r,bags:a=[]},s)=>{const l=new Date;var i;s("jxnr",l.getTime()),s("jxnv",`${n.major}.${n.minor}.${n.patch}`),Object.keys(o).forEach((e=>s(e,encodeURIComponent(o[e])))),[...r].forEach((e=>s("jxnargs[]",(e=>{if(null==e)return"*";const n=t.of(e);if("object"===n||"array"===n)try{return encodeURIComponent(JSON.stringify(e))}catch(t){e=""}return e=encodeURIComponent(e),"string"===n?"S"+e:"boolean"===n?"B"+e:"number"===n?"N"+e:e})(e)))),a.length>0&&s("jxnbags",encodeURIComponent((i=a,JSON.stringify(i.reduce(((t,n)=>({...t,[n]:e.bags[n]??"*"})),{})))))};e.process=e=>{e.requestURI=e.URI,e.requestData=(({upload:e})=>e&&e.ajax&&e.input)(e)?(e=>{const t=new FormData;o(e,((e,n)=>t.append(e,n)));const n=e.upload.input;return n.files&&n.files.forEach((e=>t.append(n.name,e))),t})(e):(e=>{const t=[];return o(e,((e,n)=>t.push(e+"="+n))),"POST"===e.method?t.join("&"):(e.requestURI+=-1===e.requestURI.indexOf("?")?"?":"&",e.requestURI+=t.join("&"),"")})(e)}}(jaxon.ajax.parameters,jaxon.utils.types,jaxon.version),function(e,t,n,o,r,a,s,l){const i=e=>{r.execute(e,"onPrepare"),e.httpRequestOptions={...t.httpRequestOptions,method:e.method,headers:{...e.commonHeaders,..."POST"===e.method?e.postHeaders:e.getHeaders},body:e.requestData},e.responseConverter=t=>(e.response=t,e.convertResponseToJson?t.json():t.text()),e.responseHandler=t=>{e.responseContent=t,l.empty(a.q.send)||"synchronous"===e.mode?o.received(e):l.push(a.q.recv,e)},e.errorHandler=t=>{throw r.execute(e,"onFailure"),t},e.responseProcessor||(e.responseProcessor=o.jsonProcessor)},u=e=>(--e.requestRetry,e.status.onRequest(),r.execute(e,"onResponseDelay"),r.execute(e,"onExpiration"),r.execute(e,"onRequest"),e.cursor.onWaiting(),e.status.onWaiting(),fetch(e.requestURI,e.httpRequestOptions).then(e.responseConverter).then(e.responseHandler).catch(e.errorHandler),e.returnValue);e.complete=e=>{if(r.execute(e,"onComplete"),e.cursor.onComplete(),e.status.onComplete(),(e=>{delete e.func,delete e.URI,delete e.requestURI,delete e.requestData,delete e.requestRetry,delete e.httpRequestOptions,delete e.responseHandler,delete e.responseConverter,delete e.responseContent,delete e.response,delete e.errorHandler})(e),"synchronous"===e.mode){for(l.pop(a.q.send),l.pop(a.q.recv);null!==(recvRequest=a.popAsyncRequest(a.q.recv));)o.received(recvRequest);for(;null!==(nextRequest=a.popAsyncRequest(a.q.send));)u(nextRequest);null!==(nextRequest=l.peek(a.q.send))&&u(nextRequest)}},e.abort=t=>{t.aborted=!0,e.complete(t)},e.execute=(e,o)=>{if(void 0===e)return!1;const c=o??{};for(c.func=e,(e=>{r.execute(e,"onInitialize"),t.setRequestOptions(e),r.initCallbacks(e),e.status=e.statusMessages?t.status.update:t.status.dontUpdate,e.cursor=e.waitCursor?t.cursor.update:t.cursor.dontUpdate,s.initialize(e),e.submit=l.empty(a.q.send),"synchronous"===e.mode&&(l.push(a.q.send,e),l.push(a.q.recv,e)),e.submit||l.push(a.q.send,e)})(c),r.execute(c,"onProcessParams"),n.process(c);c.requestRetry>0;)try{return i(c),c.submit?u(c):null}catch(e){if(r.execute(c,"onFailure"),0===c.requestRetry)throw e}return!0}}(jaxon.ajax.request,jaxon.config,jaxon.ajax.parameters,jaxon.ajax.response,jaxon.ajax.callback,jaxon.ajax.handler,jaxon.utils.upload,jaxon.utils.queue),function(e,t,n,o,r,a,s){const l=[0,200],i=[400,401,402,403,404,500,501,502,503],u=[301,302,307],c=e=>{try{return n.execute(e)}catch(e){console.log(e)}return!0};e.processCommands=e=>{let t=null;for(;!e.paused&&null!==(t=a.pop(e));)if(!c(t))return!1;return!0},e.jsonProcessor=t=>l.indexOf(t.response.status)>=0?(r.execute(t,"onSuccess"),(e=>{if(!s.isObject(e.responseContent))return;const{debug:{message:t}={},jxn:{value:n,commands:o=[]}={}}=e.responseContent;e.status.onProcessing(),n&&(e.returnValue=n),t&&console.log(t);let r=0;o.forEach((t=>a.push(e.commandQueue,{fullName:"*unknown*",...t,sequence:r++,commandQueue:e.commandQueue,request:e,context:e.context}))),a.push(e.commandQueue,{name:"response.complete",fullName:"Response Complete",sequence:r,commandQueue:e.commandQueue,request:e,context:e.context})})(t),e.processCommands(t.commandQueue),t.returnValue):u.indexOf(t.response.status)>=0?(r.execute(t,"onRedirect"),o.complete(t),window.location=t.response.headers.get("location"),t.returnValue):i.indexOf(t.response.status)>=0?(r.execute(t,"onFailure"),o.complete(t),t.returnValue):t.returnValue,e.received=e=>e.aborted?null:(e.commandQueue=a.create(t.commandQueueSize),r.clearTimer(e,"onExpiration"),r.clearTimer(e,"onResponseDelay"),r.execute(e,"beforeResponseProcessing"),e.responseProcessor(e))}(jaxon.ajax.response,jaxon.config,jaxon.ajax.handler,jaxon.ajax.request,jaxon.ajax.callback,jaxon.utils.queue,jaxon.utils.types),function(e,t,n,o){e.assign=({target:e,attr:n,value:o})=>{if("innerHTML"===n)return e.innerHTML=o,!0;if("outerHTML"===n)return e.outerHTML=o,!0;const r=t.getInnerObject(n,e);return null!==r&&(r.node[r.attr]=o),!0},e.append=({target:e,attr:n,value:o})=>{if("innerHTML"===n)return e.innerHTML=e.innerHTML+o,!0;if("outerHTML"===n)return e.outerHTML=e.outerHTML+o,!0;const r=t.getInnerObject(n,e);return null!==r&&(r.node[r.attr]=r.node[r.attr]+o),!0},e.prepend=({target:e,attr:n,value:o})=>{if("innerHTML"===n)return e.innerHTML=o+e.innerHTML,!0;if("outerHTML"===n)return e.outerHTML=o+e.outerHTML,!0;const r=t.getInnerObject(n,e);return null!==r&&(r.node[r.attr]=o+r.node[r.attr]),!0};e.replace=({target:e,attr:o,search:r,replace:a})=>{const s="innerHTML"===o?t.getBrowserHTML(r):r,l=t.getInnerObject(o,e);return null!==l&&((e,o,r,a)=>{const s=n.isFunction(e[o]),l=(s?e[o].join(""):e[o]).replaceAll(r,a);(s||t.willChange(e,o,l))&&(e[o]=l)})(l.node,l.attr,s,a),!0},e.clear=({target:t,attr:n})=>(e.assign({target:t,attr:n,value:""}),!0),e.remove=({target:e})=>(t.removeElement(e),!0);const r=(e,t)=>{const n=o.createElement(e);return n.setAttribute("id",t),n};e.create=({target:e,tag:{id:t,name:n}})=>(e&&e.appendChild(r(n,t)),!0),e.insert=({target:e,tag:{id:t,name:n}})=>(e&&e.parentNode&&e.parentNode.insertBefore(r(n,t),e),!0),e.insertAfter=({target:e,tag:{id:t,name:n}})=>(e&&e.parentNode&&e.parentNode.insertBefore(r(n,t),e.nextSibling),!0)}(jaxon.cmd.body,jaxon.utils.dom,jaxon.utils.types,jaxon.config.baseDocument),function(e,t,n,o){e.addHandler=({target:e,event:t,func:r})=>(e.addEventListener(o.stripOnPrefix(t),n.findFunction(r),!1),!0),e.removeHandler=({target:e,event:t,func:r})=>(e.removeEventListener(o.stripOnPrefix(t),n.findFunction(r),!1),!0);const r=(e,n,o)=>{t.execExpr({_type:"expr",...o},{event:e,target:n})};e.addEventHandler=({target:e,event:t,func:n,options:a})=>(e.addEventListener(o.stripOnPrefix(t),(t=>r(t,e,n)),a??!1),!0),e.setEventHandler=({target:e,event:t,func:n})=>(e[o.addOnPrefix(t)]=t=>r(t,e,n),!0)}(jaxon.cmd.event,jaxon.call.json,jaxon.utils.dom,jaxon.utils.string),function(e,t,n,o){e.call=({func:e,args:n},{context:o={}})=>(t.execCall({_type:"func",_name:e,args:n},o),!0),e.redirect=({url:e,delay:t})=>t<=0?(window.location=e,!0):(window.setTimeout((()=>window.location=e),1e3*t),!0),e.databag=({values:e})=>{for(const t in e)n.bags[t]=e[t];return!0},e.jquery=({selector:e})=>(t.execExpr(e),!0);const r=(e,t)=>e.map((e=>o.isObject(e)&&"page"===e._type?parseInt(t.parentNode.getAttribute("data-page")):e));e.paginate=({target:e,func:{calls:[n]}})=>{const o=e.querySelectorAll("li.enabled > a"),{args:a}=n;return o.forEach((e=>e.addEventListener("click",(()=>t.execCall({...n,_type:"func",args:r(a,e)}))))),!0}}(jaxon.cmd.script,jaxon.call.json,jaxon.ajax.parameters,jaxon.utils.types),function(e,t,n){const o=(e,n)=>{t.has(e)||console.warn(`Unable to find a Jaxon dialog library with name "${e}".`);const o=t.get(e);return o[n]?o:(console.error(`The chosen Jaxon dialog library doesn't implement the "${n}" function.`),null)};e.showMessage=({lib:e,type:t,content:r})=>{const{title:a,phrase:s}=r,l=o(e,"alert");return l&&l.alert(t,n.makePhrase(s),a),!0},e.showModal=({lib:e,dialog:{title:t,content:n,buttons:r,options:a}})=>{const s=o(e,"show");return s&&s.show(t,n,r,a),!0},e.hideModal=({lib:e})=>{const t=o(e,"hide");return t&&t.hide(),!0}}(jaxon.dialog.cmd,jaxon.dialog.lib,jaxon.call.json),function(e,t,n,o,r){const a={yes:"Yes",no:"No"};e.default={},e.has=t=>!!e[t],e.get=t=>e[t]??e.default,e.register=(s,l)=>{e[s]={},l(e[s],{types:t,dom:n,js:o,jq:r,labels:a})}}(jaxon.dialog.lib,jaxon.utils.types,jaxon.dom,jaxon.call.json,window.jQuery),jaxon.dialog.lib.register("default",(e=>{e.alert=(e,t,n)=>alert(n?`${n}
${t}`:t),e.confirm=(e,t,n,o)=>{confirm(t?`${t}
${e}`:e)?n():o&&o()}})),jaxon.request=jaxon.ajax.request.execute,jaxon.register=jaxon.ajax.handler.register,jaxon.$=jaxon.utils.dom.$,jaxon.jq=jaxon.call.query.jq,jaxon.exec=jaxon.call.json.execExpr,jaxon.dom.ready=jaxon.utils.dom.ready,jaxon.getFormValues=jaxon.utils.form.getValues,jaxon.isLoaded=!0,function(e,t,n,o){e("response.complete",((e,{request:t})=>(n.request.complete(t),!0)),"Response complete"),e("dom.assign",t.body.assign,"Dom::Assign"),e("dom.append",t.body.append,"Dom::Append"),e("dom.prepend",t.body.prepend,"Dom::Prepend"),e("dom.replace",t.body.replace,"Dom::Replace"),e("dom.clear",t.body.clear,"Dom::Clear"),e("dom.remove",t.body.remove,"Dom::Remove"),e("dom.create",t.body.create,"Dom::Create"),e("dom.insert.before",t.body.insert,"Dom::InsertBefore"),e("dom.insert.after",t.body.insertAfter,"Dom::InsertAfter"),e("script.call",t.script.call,"Script::CallJsFunction"),e("script.redirect",t.script.redirect,"Script::Redirect"),e("script.sleep",n.handler.sleep,"Handler::Sleep"),e("script.confirm",n.handler.confirm,"Handler::Confirm"),e("handler.event.set",t.event.setEventHandler,"Script::SetEventHandler"),e("handler.event.add",t.event.addEventHandler,"Script::AddEventHandler"),e("handler.add",t.event.addHandler,"Script::AddHandler"),e("handler.remove",t.event.removeHandler,"Script::RemoveHandler"),e("script.debug",(({message:e})=>(console.log(e),!0)),"Debug message"),e("jquery.call",t.script.jquery,"JQuery::CallSelector"),e("pg.paginate",t.script.paginate,"Paginator::Paginate"),e("databag.set",t.script.databag,"Databag:SetValues"),e("dialog.message",o.cmd.showMessage,"Dialog:ShowMessage"),e("dialog.modal.show",o.cmd.showModal,"Dialog:ShowModal"),e("dialog.modal.hide",o.cmd.hideModal,"Dialog:HideModal")}(jaxon.register,jaxon.cmd,jaxon.ajax,jaxon.dialog); \ No newline at end of file diff --git a/dist/jaxon.module.js b/dist/jaxon.module.js index eabd783..2937546 100644 --- a/dist/jaxon.module.js +++ b/dist/jaxon.module.js @@ -430,22 +430,22 @@ window.jaxon = jaxon; * Given an element and an attribute with 0 or more dots, * get the inner object and the corresponding attribute name. * - * @param {object} xElement The outer element. - * @param {string} attribute The attribute name. + * @param {string} sAttrName The attribute name. + * @param {object=} xElement The outer element. * * @returns {object|null} The inner object and the attribute name in an object. */ - self.getInnerObject = (xElement, attribute) => { - const aNames = attribute.split('.'); + self.getInnerObject = (sAttrName, xElement = window) => { + const aNames = sAttrName.split('.'); // Get the last element in the array. - attribute = aNames.pop(); + sAttrName = aNames.pop(); // Move to the inner object. const nLength = aNames.length; for (let i = 0; i < nLength && (xElement); i++) { // The real name for the "css" object is "style". xElement = xElement[aNames[i] === 'css' ? 'style' : aNames[i]]; } - return !xElement ? null : { node: xElement, attr: attribute }; + return !xElement ? null : { node: xElement, attr: sAttrName }; }; })(jaxon.utils.dom, jaxon.utils.types, jaxon.config.baseDocument); @@ -975,7 +975,10 @@ window.jaxon = jaxon; */ const xErrors = { comparator: () => false, // The default comparison operator. - command: (xCall) => console.error('Unexpected command: ' + JSON.stringify({ call: xCall })), + command: (xCall) => { + console.error('Unexpected command: ' + JSON.stringify({ call: xCall })); + return undefined; + }, }; /** @@ -1001,7 +1004,7 @@ window.jaxon = jaxon; * * @returns {boolean} */ - const isExpression = xArg => types.isObject(xArg) && (xArg._type); + const isValidCall = xArg => types.isObject(xArg) && (xArg._type); /** * Get the value of a single argument. @@ -1012,7 +1015,7 @@ window.jaxon = jaxon; * @returns {mixed} */ const getValue = (xArg, xCurrValue) => { - if (!isExpression(xArg)) { + if (!isValidCall(xArg)) { return xArg; } const { _type: sType, _name: sName } = xArg; @@ -1021,8 +1024,8 @@ window.jaxon = jaxon; case 'html': return dom.$(sName).innerHTML; case 'input': return dom.$(sName).value; case 'checked': return dom.$(sName).checked; - case 'expr': return execExpression(xArg); - case '_': return sName === 'this' ? xCurrValue : undefined + case 'expr': return execExpression(xArg, { target: window }); + case '_': return sName === 'this' ? xCurrValue : undefined; default: return undefined; } }; @@ -1043,42 +1046,42 @@ window.jaxon = jaxon; * @var {object} */ const xCommands = { - select: ({ _name: sName, context: xSelectContext = null }, xCurrValue, oCallContext) => { + select: ({ _name: sName, context: xSelectContext = null }, oCallContext) => { switch(sName) { case 'this': return query.select(oCallContext.target); // The last event target. case 'event': return oCallContext.event; // The last event - case 'window': - return window; default: // Call the selector. - return query.select(sName, getValue(xSelectContext, xCurrValue)); + return query.select(sName, xSelectContext); } }, - event: ({ _name: sName, func: xExpression }, xCurrValue, oCallContext) => { + event: ({ _name: sName, func: xExpression }, oCallContext, xCurrValue) => { // Set an event handler. Takes an expression as argument. xCurrValue.on(sName, (event) => execExpression(xExpression, { ...oCallContext, event, target: event.currentTarget, - value: null, })); return xCurrValue; }, - func: ({ _name: sName, args: aArgs = [] }, xCurrValue, oCallContext) => { + func: ({ _name: sName, args: aArgs = [] }, oCallContext, xCurrValue) => { // Call a "global" function with the current context as "this". const func = dom.findFunction(sName); - return !func ? null : func.apply(oCallContext, getArgs(aArgs, xCurrValue)); + return !func ? undefined : func.apply(oCallContext, getArgs(aArgs, xCurrValue)); }, - method: ({ _name: sName, args: aArgs = [] }, xCurrValue) => { + method: ({ _name: sName, args: aArgs = [] }, oCallContext, xCurrValue) => { // Call a function with the current value as "this". const func = dom.findFunction(sName, xCurrValue); // toInt() is a peudo-method that converts the current value to int. - return !func ? (sName === 'toInt' ? types.toInt(xCurrValue) : null) : + return !func ? (sName === 'toInt' ? types.toInt(xCurrValue) : undefined) : func.apply(xCurrValue, getArgs(aArgs, xCurrValue)); }, - attr: ({ _name: sName, value: xValue }, xCurrValue) => { - const xElt = dom.getInnerObject(xCurrValue, sName); + attr: ({ _name: sName, value: xValue }, oCallContext, xCurrValue) => { + const xElt = dom.getInnerObject(sName, xCurrValue || oCallContext.target); + if (!xElt) { + return undefined; + } if (xValue !== undefined) { // Assign an attribute. xElt.node[xElt.attr] = getValue(xValue, xCurrValue); @@ -1092,13 +1095,13 @@ window.jaxon = jaxon; * * @param {object} xCall * @param {object} oCallContext The context to execute calls in. + * @param {mixed=} xCurrValue The current expression value. * * @returns {void} */ - const execCall = (xCall, oCallContext) => { - const { value: xCurrValue } = oCallContext; - const xCommand = xCommands[xCall._type] ?? xErrors.command; - return xCommand(xCall, xCurrValue, oCallContext); + const execCall = (xCall, oCallContext, xCurrValue) => { + const xCommand = isValidCall(xCall) ? xCommands[xCall._type] : xErrors.command; + return xCommand(xCall, oCallContext, xCurrValue); }; /** @@ -1109,8 +1112,7 @@ window.jaxon = jaxon; * * @returns {mixed} */ - self.execCall = (xCall, oCallContext) => !types.isObject(xCall) ? null : - execCall(xCall, oCallContext || { target: window, value: null }); + self.execCall = (xCall, oCallContext) => execCall(xCall, { target: window, ...oCallContext }); /** * Execute the javascript code represented by an expression object. @@ -1120,8 +1122,17 @@ window.jaxon = jaxon; * * @returns {mixed} */ - const execCalls = (aCalls, oCallContext) => - aCalls.reduce((xValue, xCall) => execCall(xCall, { ...oCallContext, value: xValue }), null); + const execCalls = (aCalls, oCallContext) => { + let xCurrValue = undefined; + const nLength = aCalls.length; + for (let i = 0; i < nLength; i++) { + xCurrValue = execCall(aCalls[i], oCallContext, xCurrValue); + if (xCurrValue === undefined) { + return xCurrValue; // Exit the loop if a call return an undefined value. + } + } + return xCurrValue; + }; /** * Replace placeholders in a given string with values @@ -1218,7 +1229,7 @@ window.jaxon = jaxon; * @returns {mixed} */ self.execExpr = (xExpression, oCallContext) => !types.isObject(xExpression) ? null : - execExpression(xExpression, oCallContext || { target: window, value: null }); + execExpression(xExpression, { target: window, ...oCallContext }); })(jaxon.call.json, jaxon.call.query, jaxon.dialog.lib, jaxon.utils.dom, jaxon.utils.form, jaxon.utils.types); @@ -2208,7 +2219,7 @@ window.jaxon = jaxon; return true; } - const xElt = dom.getInnerObject(target, attr); + const xElt = dom.getInnerObject(attr, target); if (xElt !== null) { xElt.node[xElt.attr] = value; } @@ -2236,7 +2247,7 @@ window.jaxon = jaxon; return true; } - const xElt = dom.getInnerObject(target, attr); + const xElt = dom.getInnerObject(attr, target); if (xElt !== null) { xElt.node[xElt.attr] = xElt.node[xElt.attr] + value; } @@ -2264,7 +2275,7 @@ window.jaxon = jaxon; return true; } - const xElt = dom.getInnerObject(target, attr); + const xElt = dom.getInnerObject(attr, target); if (xElt !== null) { xElt.node[xElt.attr] = value + xElt.node[xElt.attr]; } @@ -2304,7 +2315,7 @@ window.jaxon = jaxon; */ self.replace = ({ target, attr, search, replace }) => { const sSearch = attr === 'innerHTML' ? dom.getBrowserHTML(search) : search; - const xElt = dom.getInnerObject(target, attr); + const xElt = dom.getInnerObject(attr, target); if (xElt !== null) { replaceText(xElt.node, xElt.attr, sSearch, replace); } diff --git a/src/call/json.js b/src/call/json.js index f655ac9..0510fc3 100644 --- a/src/call/json.js +++ b/src/call/json.js @@ -10,7 +10,10 @@ */ const xErrors = { comparator: () => false, // The default comparison operator. - command: (xCall) => console.error('Unexpected command: ' + JSON.stringify({ call: xCall })), + command: (xCall) => { + console.error('Unexpected command: ' + JSON.stringify({ call: xCall })); + return undefined; + }, }; /** @@ -36,7 +39,7 @@ * * @returns {boolean} */ - const isExpression = xArg => types.isObject(xArg) && (xArg._type); + const isValidCall = xArg => types.isObject(xArg) && (xArg._type); /** * Get the value of a single argument. @@ -47,7 +50,7 @@ * @returns {mixed} */ const getValue = (xArg, xCurrValue) => { - if (!isExpression(xArg)) { + if (!isValidCall(xArg)) { return xArg; } const { _type: sType, _name: sName } = xArg; @@ -56,8 +59,8 @@ case 'html': return dom.$(sName).innerHTML; case 'input': return dom.$(sName).value; case 'checked': return dom.$(sName).checked; - case 'expr': return execExpression(xArg); - case '_': return sName === 'this' ? xCurrValue : undefined + case 'expr': return execExpression(xArg, { target: window }); + case '_': return sName === 'this' ? xCurrValue : undefined; default: return undefined; } }; @@ -78,42 +81,42 @@ * @var {object} */ const xCommands = { - select: ({ _name: sName, context: xSelectContext = null }, xCurrValue, oCallContext) => { + select: ({ _name: sName, context: xSelectContext = null }, oCallContext) => { switch(sName) { case 'this': return query.select(oCallContext.target); // The last event target. case 'event': return oCallContext.event; // The last event - case 'window': - return window; default: // Call the selector. - return query.select(sName, getValue(xSelectContext, xCurrValue)); + return query.select(sName, xSelectContext); } }, - event: ({ _name: sName, func: xExpression }, xCurrValue, oCallContext) => { + event: ({ _name: sName, func: xExpression }, oCallContext, xCurrValue) => { // Set an event handler. Takes an expression as argument. xCurrValue.on(sName, (event) => execExpression(xExpression, { ...oCallContext, event, target: event.currentTarget, - value: null, })); return xCurrValue; }, - func: ({ _name: sName, args: aArgs = [] }, xCurrValue, oCallContext) => { + func: ({ _name: sName, args: aArgs = [] }, oCallContext, xCurrValue) => { // Call a "global" function with the current context as "this". const func = dom.findFunction(sName); - return !func ? null : func.apply(oCallContext, getArgs(aArgs, xCurrValue)); + return !func ? undefined : func.apply(oCallContext, getArgs(aArgs, xCurrValue)); }, - method: ({ _name: sName, args: aArgs = [] }, xCurrValue) => { + method: ({ _name: sName, args: aArgs = [] }, oCallContext, xCurrValue) => { // Call a function with the current value as "this". const func = dom.findFunction(sName, xCurrValue); // toInt() is a peudo-method that converts the current value to int. - return !func ? (sName === 'toInt' ? types.toInt(xCurrValue) : null) : + return !func ? (sName === 'toInt' ? types.toInt(xCurrValue) : undefined) : func.apply(xCurrValue, getArgs(aArgs, xCurrValue)); }, - attr: ({ _name: sName, value: xValue }, xCurrValue) => { - const xElt = dom.getInnerObject(xCurrValue, sName); + attr: ({ _name: sName, value: xValue }, oCallContext, xCurrValue) => { + const xElt = dom.getInnerObject(sName, xCurrValue || oCallContext.target); + if (!xElt) { + return undefined; + } if (xValue !== undefined) { // Assign an attribute. xElt.node[xElt.attr] = getValue(xValue, xCurrValue); @@ -127,13 +130,13 @@ * * @param {object} xCall * @param {object} oCallContext The context to execute calls in. + * @param {mixed=} xCurrValue The current expression value. * * @returns {void} */ - const execCall = (xCall, oCallContext) => { - const { value: xCurrValue } = oCallContext; - const xCommand = xCommands[xCall._type] ?? xErrors.command; - return xCommand(xCall, xCurrValue, oCallContext); + const execCall = (xCall, oCallContext, xCurrValue) => { + const xCommand = isValidCall(xCall) ? xCommands[xCall._type] : xErrors.command; + return xCommand(xCall, oCallContext, xCurrValue); }; /** @@ -144,8 +147,7 @@ * * @returns {mixed} */ - self.execCall = (xCall, oCallContext) => !types.isObject(xCall) ? null : - execCall(xCall, oCallContext || { target: window, value: null }); + self.execCall = (xCall, oCallContext) => execCall(xCall, { target: window, ...oCallContext }); /** * Execute the javascript code represented by an expression object. @@ -155,8 +157,17 @@ * * @returns {mixed} */ - const execCalls = (aCalls, oCallContext) => - aCalls.reduce((xValue, xCall) => execCall(xCall, { ...oCallContext, value: xValue }), null); + const execCalls = (aCalls, oCallContext) => { + let xCurrValue = undefined; + const nLength = aCalls.length; + for (let i = 0; i < nLength; i++) { + xCurrValue = execCall(aCalls[i], oCallContext, xCurrValue); + if (xCurrValue === undefined) { + return xCurrValue; // Exit the loop if a call returns an undefined value. + } + } + return xCurrValue; + }; /** * Replace placeholders in a given string with values @@ -253,6 +264,6 @@ * @returns {mixed} */ self.execExpr = (xExpression, oCallContext) => !types.isObject(xExpression) ? null : - execExpression(xExpression, oCallContext || { target: window, value: null }); + execExpression(xExpression, { target: window, ...oCallContext }); })(jaxon.call.json, jaxon.call.query, jaxon.dialog.lib, jaxon.utils.dom, jaxon.utils.form, jaxon.utils.types); diff --git a/src/config.js b/src/config.js index c637021..a928934 100644 --- a/src/config.js +++ b/src/config.js @@ -17,7 +17,7 @@ var jaxon = { version: { major: '5', minor: '0', - patch: '0rc-2', + patch: '0rc-5', }, debug: { diff --git a/tests/call.json.test.js b/tests/call.json.test.js index 8f12099..20926b8 100644 --- a/tests/call.json.test.js +++ b/tests/call.json.test.js @@ -9,7 +9,7 @@ query.jq = $; test('Read str value from the DOM', () => { document.body.innerHTML = `
1024
`; - // JQuery code: const strValue = $('#integer')->text() + // Javascript code: const strValue = $('#integer')->text() const strValue = json.execExpr({ calls: [{ _type: 'select', @@ -26,7 +26,7 @@ test('Read str value from the DOM', () => { test('Read str value from the DOM', () => { document.body.innerHTML = `
1024
`; - // JQuery code: const strValue = $('#integer')->html() + // Javascript code: const strValue = $('#integer')->html() const strValue = json.execExpr({ calls: [{ _type: 'select', @@ -43,7 +43,7 @@ test('Read str value from the DOM', () => { test('Read int value from the DOM', () => { document.body.innerHTML = `
1024
`; - // JQuery code: const intValue = parseInt($('#integer')->text()) + // Javascript code: const intValue = parseInt($('#integer')->text()) const intValue = json.execExpr({ calls: [{ _type: 'func', @@ -67,7 +67,7 @@ test('Read int value from the DOM', () => { test('Read int value from the DOM, with the toInt() "method"', () => { document.body.innerHTML = `
1024
`; - // JQuery code: const intValue = parseInt($('#integer')->text()) + // Javascript code: const intValue = parseInt($('#integer')->text()) const intValue = json.execExpr({ calls: [{ _type: 'select', @@ -87,7 +87,7 @@ test('Read int value from the DOM, with the toInt() "method"', () => { test('Assign element inner html', () => { document.body.innerHTML = `
`; - // JQuery code: $('#username')->html('Mister Johnson') + // Javascript code: $('#username')->html('Mister Johnson') json.execExpr({ calls: [{ _type: 'select', @@ -105,7 +105,7 @@ test('Assign element inner html', () => { test('Assign element outer html', () => { document.body.innerHTML = `
Feuzeu
`; - // JQuery code: $('#username')->prop('outerHTML', 'Mister Johnson') + // Javascript code: $('#username')->prop('outerHTML', 'Mister Johnson') json.execExpr({ calls: [{ _type: 'select', @@ -124,7 +124,7 @@ test('Set an event handler', () => { document.body.innerHTML = `
`; // Set an event handler - // JQuery code: $('#username')->on('click', () => $('#username')->html('Mister Johnson')) + // Javascript code: $('#username')->on('click', () => $('#username')->html('Mister Johnson')) json.execExpr({ calls: [{ _type: 'select', @@ -158,7 +158,7 @@ test('Use "this" in an event handler', () => { document.body.innerHTML = `
`; // Set an event handler - // JQuery code: $('.username')->on('click', () => $(this)->html('Mister Johnson')) + // Javascript code: $('.username')->on('click', () => $(this)->html('Mister Johnson')) json.execExpr({ calls: [{ _type: 'select', @@ -188,14 +188,73 @@ test('Use "this" in an event handler', () => { expect($('.username').text()).toBe('Mister Johnson'); }); -test('Access to "window" with the selector', () => { +test('Access to undefined vars', () => { + expect(window.defValue).toBe(undefined); + + // Javascript code: const undefValue1 = window.defValue + const undefValue1 = json.execExpr({ + calls: [{ + _type: 'attr', + _name: 'defValue', + }], + }); + + expect(undefValue1).toBe(undefined); + + // Javascript code: window.defValue = '1024' + json.execExpr({ + calls: [{ + _type: 'attr', + _name: 'defValue', + value: '1024', + }], + }); + + expect(window.defValue).toBe('1024'); + + // Javascript code: const defValue = window.defValue + const defValue = json.execExpr({ + calls: [{ + _type: 'attr', + _name: 'defValue', + }], + }); + + expect(defValue).toBe('1024'); + + // Javascript code: const undefValue2 = window.defValue.intValue + const undefValue2 = json.execExpr({ + calls: [{ + _type: 'attr', + _name: 'defValue', + },{ + _type: 'attr', + _name: 'intValue', + }], + }); + + expect(undefValue2).toBe(undefined); + + // Javascript code: const undefValue3 = window.intValue.defValue + const undefValue3 = json.execExpr({ + calls: [{ + _type: 'attr', + _name: 'intValue', + },{ + _type: 'attr', + _name: 'defValue', + }], + }); + + expect(undefValue3).toBe(undefined); +}); + +test('Access to "global" vars', () => { expect(window.strValue).toBe(undefined); + // Javascript code: window.strValue = '1024' json.execExpr({ calls: [{ - _type: 'select', - _name: 'window', - }, { _type: 'attr', _name: 'strValue', value: '1024', @@ -203,4 +262,31 @@ test('Access to "window" with the selector', () => { }); expect(window.strValue).toBe('1024'); + + // Javascript code: const strValue = window.strValue + const strValue = json.execExpr({ + calls: [{ + _type: 'attr', + _name: 'strValue', + }], + }); + + expect(strValue).toBe('1024'); + + // Javascript code: const intValue = parseInt(window.strValue) + const intValue = json.execExpr({ + calls: [{ + _type: 'func', + _name: 'parseInt', + args: [{ + _type: 'expr', + calls: [{ + _type: 'attr', + _name: 'strValue', + }], + }], + }], + }); + + expect(intValue).toBe(1024); });