/** * app.utilB.js * JavaScript browser utilities * */ /*jslint browser : true, continue : true, devel : true, indent : 2, maxerr : 50, newcap : true, nomen : true, plusplus : true, regexp : true, sloppy : true, vars : false, white : true */ /*global $, app, getComputedStyle */ app.utilB = (function () { "use strict"; //---------------- BEGIN MODULE SCOPE VARIABLES -------------- var configMap = { regex_encode_html: /[&"'><]/g, regex_encode_noamp: /["'><]/g, html_encode_map: { "&": "&", '"': """, "'": "'", ">": ">", "<": "<" } }, decodeHtml, encodeHtml, getEmSize, getApiUrl, getUrlParams, formData, objectifyFormDataArray, getMediaSize, prepareObjectForClient, fixDatesToStrings, epochToShortDate, epochToLocalShortDate, epochToLocalShortDateTime, getCurrentDateTimeAsEpoch, genListColumn, genListColumnNoLink, autoComplete, prepareObjectDatesForServer, fixStringToServerDate; configMap.encode_noamp_map = $.extend({}, configMap.html_encode_map); delete configMap.encode_noamp_map["&"]; //----------------- END MODULE SCOPE VARIABLES --------------- //------------------- BEGIN UTILITY METHODS ------------------ // Begin decodeHtml // Decodes HTML entities in a browser-friendly way // See http://stackoverflow.com/questions/1912501/\ // unescape-html-entities-in-javascript // decodeHtml = function (str) { return $("
") .html(str || "") .text(); }; // End decodeHtml // Begin encodeHtml // This is single pass encoder for html entities and handles // an arbitrary number of characters // encodeHtml = function (input_arg_str, exclude_amp) { var input_str = String(input_arg_str), regex, lookup_map; if (exclude_amp) { lookup_map = configMap.encode_noamp_map; regex = configMap.regex_encode_noamp; } else { lookup_map = configMap.html_encode_map; regex = configMap.regex_encode_html; } return input_str.replace(regex, function (match, name) { return lookup_map[match] || ""; }); }; // End encodeHtml // Begin getEmSize // returns size of ems in pixels // getEmSize = function (elem) { return Number(getComputedStyle(elem, "").fontSize.match(/\d*\.?\d*/)[0]); }; // End getEmSize //Begin getApiUrl //returns url for api methods by parsing current window location url // getApiUrl = function () { var u = window.location.href .replace(window.location.hash, "") .replace("default.htm", "") + "api/"; //is it a dev local url? if (u.indexOf("localhost:8080") != -1) { u = u.replace("8080", "8081"); } // End getApiUrl //fix for random recurrence of extraneous ? on iPhone when using api //(Cannot post to http://gl-gztw.rhcloud.com/?api/list (404)) u = u.replace("?", ""); return u; }; // Begin formData // Get or set all form fields // formData = function (data) { //fix dates into strings prepareObjectForClient(data); var inps = $(":input").get(); if (typeof data != "object") { // return all data data = {}; $.each(inps, function () { if ( this.name && (this.checked || /select|textarea/i.test(this.nodeName) || /text|hidden|password/i.test(this.type)) ) { data[this.name] = $(this).val(); } }); return data; } else { $.each(inps, function () { if (this.name && data[this.name]) { if (this.type == "checkbox" || this.type == "radio") { $(this).prop("checked", data[this.name]); } else { $(this).val(data[this.name]); } } else if (this.type == "checkbox") { $(this).prop("checked", false); } }); return $(this); } }; // End formdata // Begin getMediaSize // Retrieves results of css media query in hidden pseudo element // :after body element //objectifyFormDataArray getMediaSize = function () { return window .getComputedStyle(document.querySelector("body"), ":after") .getPropertyValue("content") .replace(/\"/g, ""); }; // End getMediaSize //Begin objectifyFormDataArray //takes name value form input pairs in array and turns into a keyed object //suitable for sending as json object // objectifyFormDataArray = function (arr) { var rv = {}; for (var i = 0; i < arr.length; ++i) if (arr[i] !== undefined) { rv[arr[i].name] = arr[i].value.trim(); //case 3205 added trim } return prepareObjectDatesForServer(rv); }; //Prepare an object for server needed format before submission //called by objectifyFormDataArray prepareObjectDatesForServer = function (obj) { if (Array.isArray(obj)) { for (var i = 0; i < obj.length; i++) { fixStringToServerDate(obj[i]); } } else { fixStringToServerDate(obj); } return obj; }; // //Turn string date fields from client into server compatible format (Unix epoch like this: 1498262400 1499904000) fixStringToServerDate = function (obj) { var keys = Object.keys(obj); keys.forEach(function (key) { if (key.endsWith("Date") || key.startsWith("dt")) { var value = obj[key]; if (value == null) { obj[key] = ""; } else { //this is the sample format we will see: 2017-07-13 //TODO: is this assuming UTC? obj[key] = moment.utc(value, "YYYY-MM-DD").unix(); } } }); }; //This function exists to change the properties of the passed in object //to values compatible with jquery form filling functions (mostly dates to strings for now) // prepareObjectForClient = function (obj) { if (Array.isArray(obj)) { for (var i = 0; i < obj.length; i++) { fixDatesToStrings(obj[i]); } } else { fixDatesToStrings(obj); } return obj; }; // //Turn date fields of object coming from db into stringified values for consumption by client //turn null dates into empty strings and iso date values into strings in iso format fixDatesToStrings = function (obj) { var keys = Object.keys(obj); keys.forEach(function (key) { if (key.endsWith("Date") || key.startsWith("dt")) { var value = obj[key]; if (value == null) { obj[key] = ""; } else { //Now with sqlite they come and go as unix epoch seconds //needs to be yyyy-MM-dd obj[key] = moment.utc(new Date(value * 1000)).format("YYYY-MM-DD"); } } }); }; // //Turn date values coming in from server into displayable short date format //used to display dates in various lists (where the source epoch is already localized) epochToShortDate = function (epoch) { if (epoch == null || epoch == 0) return ""; return moment.utc(new Date(epoch * 1000)).format("YYYY-MM-DD"); }; // //LOCAL VERSION: Turn date values coming in from server into displayable short date format //used to display dates in various lists where the source epoch is in UTC epochToLocalShortDate = function (epoch) { if (epoch == null || epoch == 0) return ""; var utdate = moment.utc(new Date(epoch * 1000)); var localdate = moment(utdate).local(); return localdate.format("YYYY-MM-DD"); }; //LOCAL VERSION: Turn date values coming in from server into displayable short date AND TIME format //used to display dates in various lists where the source epoch is in UTC epochToLocalShortDateTime = function (epoch) { if (epoch == null || epoch == 0) return ""; var utdate = moment.utc(new Date(epoch * 1000)); var localdate = moment(utdate).local(); return localdate.format("YYYY-MM-DD LT"); }; ////////////////////////// //Get current date and time as a utc unix epoch getCurrentDateTimeAsEpoch = function () { return moment().utc().unix(); }; // Begin genListColumn // This function is used to demarcate 'columns' of fields in basic list forms by wrapping each column field in html // genListColumn = function (val) { return '' + val + ""; }; // End genListColumn // Begin genListColumnNoLink // This function is used to demarcate and style 'columns' of fields in basic list forms by wrapping each column field in html // that are not link columns genListColumnNoLink = function (val) { return '' + val + ""; }; // End genListColumn // Begin autoComplete // This function is used to attach an autocomplete method to an input // autoComplete = function (controlId, acGetToken) { $("#" + controlId).autocomplete({ serviceUrl: app.shell.stateMap.apiUrl + "autocomplete", params: { acget: acGetToken }, ajaxSettings: { headers: app.api.getAuthHeaderObject() } }); }; // End autoComplete // export methods return { decodeHtml: decodeHtml, encodeHtml: encodeHtml, getEmSize: getEmSize, getApiUrl: getApiUrl, getUrlParams: getUrlParams, formData: formData, getMediaSize: getMediaSize, objectifyFormDataArray: objectifyFormDataArray, epochToShortDate: epochToShortDate, epochToLocalShortDate: epochToLocalShortDate, epochToLocalShortDateTime: epochToLocalShortDateTime, getCurrentDateTimeAsEpoch: getCurrentDateTimeAsEpoch, genListColumn: genListColumn, genListColumnNoLink: genListColumnNoLink, autoComplete: autoComplete }; //------------------- END PUBLIC METHODS --------------------- })();