UNPKG

adxutil

Version:

Utilities tools for Askia Design eXtension

334 lines (299 loc) 12.4 kB
(function () { function CustomEvent ( event, params ) { params = params || { bubbles: false, cancelable: false, detail: undefined }; var evt = document.createEvent( 'CustomEvent' ); evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail ); return evt; }; CustomEvent.prototype = window.Event.prototype; window.CustomEvent = CustomEvent; })(); (function () { if (!window.arrLiveRoutingInputCode || window.arrLiveRoutingInputCode.length <= 0 ) { return; } if (window.AskiaScript) { AskiaScript.executeLiveRouting = function () {}; } // Augment or create the public `askia` namespace var askia = window.askia || {}; if (!window.askia) { window.askia = askia; } /* ---======== Utilities ========--- */ /** * Capitalize the first letter of the string and return the new string * * @param {String} str String to capitalize */ function capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1); } /** * Iterate over all submittable elements of a form * )This method was inspired from jQuery.serializeArray) * * @param {HTMLElement} elForm Form element to parse * @param {Function} fn Function called for each submittable elements * @param {HTMLElement} fn.element Submittable element */ function forEachSubmittableElements(elForm, fn) { if (typeof fn !== 'function') { return; } // Don't submit all input submittable var rgSubmitter = /^(?:submit|button|image|reset|file)$/i, // Submittable elements rgSubmittable = /^(?:input|select|textarea|keygen)/i, // Elements that have a checked state rgCheckable = /^(?:checkbox|radio)$/i, // List of elements els = elForm.elements, i, l; for (i = 0, l = els.length; i < l; i += 1) { var el = els[i]; if (!el.name || el.disabled || el.value === null || rgSubmitter.test(el.type) || !rgSubmittable.test(el.nodeName) || (rgCheckable.test(el.type) && !el.checked)) { continue; } fn(el); } } /** * Serialize the Askia Form to an object * * @param {HTMLElement} elForm Form element to serialize * @param {String} [action] Action to use instead of the regular form action * @return {String} Return the form data that should normally be send to the server-side */ askia.serializeForm = function serializeForm(elForm, action) { var params = []; forEachSubmittableElements(elForm, function (el) { var name = el.name var value = el.value.replace(/\r?\n/gi, "\r\n"); if (action && /^(?:action)$/i.test(el.name)) { value = action.replace(/\r?\n/gi, "\r\n"); } params.push(encodeURIComponent(name) + "=" + encodeURIComponent(value)); }); return params.join('&'); }; /** * Execute an AJAX query * * @param {Object} query AJAX query to execute * @param {String} query.url URL of the server-side management * @param {"GET"|"POST"|string} [query.method="POST"] Request method to use * @param {String} [query.data=null] Data to send to the server side * @param {Function} [query.success] Callback on success * @param {String} query.success.text Text of the response * @param {XMLHttpRequest} query.success.xhr XMLHTTPRequest used * @param {Function} [query.error] Callback on error * @param {String} query.error.text Text of the response * @param {XMLHttpRequest} query.error.xhr XMLHTTPRequest used * @param {Function} [query.complete] Callback on query complete (success or error) * @param {String} query.complete.text Text of the response * @param {XMLHttpRequest} query.complete.xhr XMLHTTPRequest used */ askia.ajax = function ajax(query) { if (!query) { (console && console.warn("The `query` argument must be a valid object for askia.ajax()")); return; } if (!query.url || typeof query.url !== 'string') { (console && console.warn("The `query.url` argument must be a valid string for askia.ajax()")); return; } query.method = ((query.method && query.method.toString()) || "POST").toUpperCase(); if (!/^(?:GET|POST|PUT|DELETE|HEAD|OPTIONS|TRACE|CONNECT)$/.test(query.method)) { (console && console.warn("The `query.method` argument must be a valid HTTP method for askia.ajax()")); return; } var xhr = new XMLHttpRequest(); xhr.open(query.method, query.url, true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); xhr.onload = function onXhrLoad() { var text = xhr.responseText; if (xhr.status >= 200 && xhr.status < 400) { if (typeof query.success === 'function') { query.success(text, xhr); } } else { if (typeof query.error === 'function') { query.error(text, xhr); } } if (typeof query.complete === 'function') { query.complete(text, xhr); } }; xhr.onerror = function () { if (typeof query.error === 'function') { query.error(text, xhr); } if (typeof query.complete === 'function') { query.complete(text, xhr); } }; xhr.send(query.data || null); }; /* ---======== Askia Events Management ========--- */ askia.defaultEventActions = { askiaAnswer: executeLiveRouting, askiaShowQuestion: executeShowHideQuestion, askiaHideQuestion: executeShowHideQuestion, askiaShowResponses: null, askiaHideResponses: null, askiaReload: executeReload, askiaSetValue: null, askiaShowMessage: null, askiaChangeQuestionsOrder: null, askiaChangeResponsesOrder: null, askiaInfo: null }; /** * Trigger an arbitrary event * * @param {String} eventName Name of the event to trigger * @param {Object} detail Detail associated with the event */ askia.triggerEvent = function triggerEvent(eventName, detail) { var eventInit = detail !== undefined ? { detail: detail } : undefined; var event = new CustomEvent(eventName, eventInit); return document.dispatchEvent(event); }; /** * Trigger an event when the respondent is answering */ askia.triggerAnswer = function triggerAnswer() { if (!askia.triggerEvent("askiaAnswer")) { return false; // preventDefault() has been called } // Default behaviour askia.defaultEventActions.askiaAnswer(); }; /* ---======== Default Events Management ========--- */ /** * Show or hide an entire question * * @param {Object} data Definition of the action to do * @param {"showQuestion"|"hideQuestion"} data.action Action to execute * @param {Number} data.inputCode Input code associated with the question */ function executeShowHideQuestion(data) { if (!(data.question.inputCode >= 0)) { return; } var isShow = /^(?:show)/i.test(data.action), className = '.askia-question-' + data.question.inputCode, elements = document.querySelectorAll(className), i, l; for (i = 0, l = elements.length; i < l; i += 1) { elements[i].style.display = isShow ? '' : 'none'; } } /** * Reload the page */ function executeReload() { if (isPreventReload) return; window.location.reload(); } /* ---======== Live Routing Management ========--- */ var isExecutingLiveRouting = false, // Flag to avoid several live routing request shouldReExecuteLiveRouting = false, // Flag to re-execute the live routing isPreventReload = true; // Flag to prevent the page to reload on loop /** * Execute the AJAX query to do a live routing */ function executeLiveRouting() { if (isExecutingLiveRouting) { shouldReExecuteLiveRouting = true; return; } isExecutingLiveRouting = true; shouldReExecuteLiveRouting = false; askia.ajax({ url: 'AskiaExt.dll', data: askia.serializeForm(document.forms[0], "DoLiveRouting"), success: onLiveRoutingSuccess, complete: onLiveRoutingComplete }); } /** * Manage the live routing AJAX - success */ function onLiveRoutingSuccess(text) { var json = JSON.parse(text); var actions = json.actions || []; var i, l, itemAction, eventName; for (i = 0, l = actions.length; i < l; i += 1) { itemAction = actions[i]; eventName = "askia" + capitalize(itemAction.action); if (!askia.triggerEvent(eventName, itemAction)) { continue; // preventDefault(); } // Default behaviour if (typeof askia.defaultEventActions[eventName] === 'function') { askia.defaultEventActions[eventName](itemAction); } } } /** * Manage the live routing AJAX - complete */ function onLiveRoutingComplete() { isExecutingLiveRouting = false; isPreventReload = false; if (!shouldReExecuteLiveRouting) { return; } setTimeout(executeLiveRouting, 250); } document.addEventListener("DOMContentLoaded", function(){ /** * Change event listener for the closed question form controls */ document.addEventListener("change", function(event){ var el = event.target || event.srcElement; // Retrieve the InputCode number of the question var rg = /^[a-z]+([0-9]+)(?:\s*|\_*)/i.exec(el.name); if (rg && (window.arrLiveRoutingInputCode.indexOf(rg[1]) > -1) && (((el.nodeName === "INPUT") && (el.parentElement.className.indexOf("askia-response") >= 0 || el.parentElement.className.indexOf("askia-control") >= 0 || el.parentElement.className.indexOf("askia-grid-row") >= 0 || el.parentElement.parentElement.className.indexOf("askia-grid-row") >= 0) && (el.type === "radio" || el.type === "checkbox")) || el.nodeName === "SELECT")) { askia.triggerAnswer(); } }); /** * Input event listener for the numerical and open ended question form controls */ document.addEventListener("input", function(event){ var el = event.target || event.srcElement; // Retrieve the InputCode number of the question var rg = /^[a-z]+([0-9]+)(?:\s*|\_*)/i.exec(el.name); if (rg && (window.arrLiveRoutingInputCode.indexOf(rg[1]) > -1) && (((el.nodeName === "TEXTAREA") || ((el.nodeName === "INPUT") && (el.type === "color" || el.type === "date" || el.type === "datetime" || el.type === "email" || el.type === "month" || el.type === "number" || el.type === "password" || el.type === "range" || el.type === "search" || el.type === "tel" || el.type === "text" || el.type === "time" || el.type === "url" || el.type === "week"))) && (el.parentElement.className.indexOf("askia-response") >= 0 || el.parentElement.className.indexOf("askia-control") >= 0 || el.parentElement.className.indexOf("askia-grid-row") >= 0 || el.parentElement.parentElement.className.indexOf("askia-grid-row") >= 0 || el.className.indexOf("askia-live") >= 0))) { askia.triggerAnswer(); } }); askia.triggerAnswer(); }); }());