// Sgx version 1.03. Dropped a lot of fluff - basically anything JQuery does is left to JQuery now. var sgx = {}; sgx.strpos = function(haystack, needle, offset) { // Finds position of first occurrence of a string within another // // version: 909.322 // discuss at: http://phpjs.org/functions/strpos // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Onno Marsman // + bugfixed by: Daniel Esteban // * example 1: strpos('Kevin van Zonneveld', 'e', 5); // * returns 1: 14 var i = (haystack+'').indexOf(needle, (offset ? offset : 0)); return i === -1 ? false : i; } sgx.int = function(v) { return sgx.cast(v, 'int'); } sgx.currency = function(v) { return sgx.cast(v, 'currency'); } sgx.float = function(v, num_dec) { num_dec = num_dec ? num_dec : false; if (num_dec === false) { return sgx.cast(v, 'float'); } else { return sgx.cast(v, 'f' + num_dec); } } sgx.cast_date = function(v) { return sgx.cast(v, 'da'); } sgx.cast_datetime = function(v) { return sgx.cast(v, 'dt'); } sgx.cast = function(v, t) { /* Function: cast * Parameters: v - The value to be formatted * t - The type to apply. Can be full type name or any of the listed equivalents see typelist * dropdown - (Optional). If type is l, a dropdown definition should be sent * Returns: {'value': val, 'string': str, 'sortval': sortval} * Typelist (The leftmost value is returned): c / $ / currency 2 decimal currency i / int / integer standard integer with no decimals f / float float number f# float number fixed to # decimal places (up to 9) da / date parsed date where value component is unix timestamp dt / datetime parsed date and time of day where value component is unix timestamp s / str / string standard string sic / str_ic / string_ignore_case standard string except sortval is always lowercase so sorts won't care about case * Description: Takes a value and returns a properly formatted value for dropdown selects and inputs, * a properly formatted string for html display, and a sortval for use in numeric/string sorting */ var str = v; var val = v; var sortval = v; if(t !== false) { // Match the type based on the Typelist above var typeMap = { 'b':'b', 'boolean': 'b', 'bool': 'b', 'a':'a', 'array': 'a', 'ar': 'a', 'o':'o', 'obj': 'o', 'object': 'o', 'c':'c', '$':'c', 'currency':'c', // Currency: c 'i':'i', 'int':'i', 'integer': 'i', // Integer: i 'f':'f', 'float':'f', // Floating Point: f 'da': 'da', 'date':'da', 'dt':'dt', 'datetime':'dt', // Dates: da or dt 's':'s', 'str':'s', 'string':'s', // Strings: s 'sic':'sic', 'str_ic': 'sic', 'string_ignore_case': 'sic', // String (Ignore Case): sic 'dr':'l', 'dropdown':'l', 'list':'l', 'dr':'l', 'cmb':'l', 'combo': 'l', 'l':'l', // List / Dropdown Combo Box : l 'lo': 'lo', 'lookup':'lo', // Lookup: lo 'func': 'func', 'function': 'func' // Function } strType = t.toLowerCase(); if (typeof(typeMap[strType]) != 'undefined') { t = typeMap[strType]; } else if (strType.match(/^f[0-9]*$/)) { t = strType; } else { // Default type is string t = 's'; } if (t == 'b') { val = v ? true : false; str = val ? 'true' : 'false'; } else if (t == 'a') { if(typeof v != 'object') { val = []; } else { val = v; } str = 'object'; } else if (t == 'o') { if(typeof v != 'object') { val = {}; } else { val = v; } str = 'object'; } else if (t == 'func') { if(typeof v != 'function') { val = function() {}; } else { val = v; } str = 'function'; } else if (t == 'c') { val = isNaN(parseFloat(v)) ? '0.00' : parseFloat(v).toFixed(2); if (val < 0) { str = '(' + val + ')'; } else { str = val; } sortval = val; } else if (t == 'i') { val = isNaN(parseFloat(v)) ? 0 : parseFloat(v).toFixed(0); str = val; sortval = val; } else if (t == 'f') { val = isNaN(parseFloat(v)) ? 0 : parseFloat(v); str = val; sortval = val; } else if (t.charAt(0) == 'f') { var dec = t.substring(1); val = isNaN(parseFloat(v)) ? 0 : parseFloat(v); val = val.toFixed(dec); str = val; sortval = val; } else if ((t == 'da') || (t == 'dt')) { // Typing now or today if ((val.toLowerCase() == 'today') || (val.toLowerCase() == 'now')) { // If user types today or now, it is an alias for today's date val = Date(); } else { // Replace dash (-) characters from mysql database with forward slashes since javascript can't recognize them val = val.replace(/-/g, '/'); } sortval = Date.parse(val); if (isNaN(sortval)) { // Either an invalid datestring or a string that evaluates to before 1970 was entered str = ''; val = ''; sortval = 0; } else { var dt = new Date(sortval); var mons = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; val = mons[dt.getMonth()] + ' ' + dt.getDate() + ', ' + dt.getFullYear(); if (t == 'dt') { val += ' ' + dt.getHours() + ':' + dt.getMinutes() + ':' + dt.getSeconds(); } str = val; } } else if (t == 'sic') { val = (typeof val == 'undefined') ? '' : val; sortval = val.toLowerCase(); } else if (t == 'l') { if (typeof dropdown == 'object') { var ind = dropdown.get_option(val); if (ind == -1) { sortval = ''; } else { sortval = dropdown.list[ind].string; } } else { sortval = str = val; } } } return { 'value' : val, // Input and select values 'string': str, // Displayed as string when not editing 'sortval': sortval, // Used to sort data 'type': t }; }; sgx.time = {}; sgx.time.utc_to_gmt = function(time, using_seconds) { if (typeof using_seconds != 'boolean') { using_seconds = true; } if (using_seconds) { var offset = (new Date()).getTimezoneOffset() * 60; } else { var offset = (new Date()).getTimezoneOffset() * 60000; } return (time - offset); } sgx.time.getTime = function(use_seconds) { if (typeof use_seconds != 'boolean') { use_seconds = true; } return (sgx.time.utc_to_gmt(sgx.time.getUTCTime(use_seconds), use_seconds)); } sgx.time.getUTCTime = function(use_seconds) { if (typeof use_seconds != 'boolean') { use_seconds = true; } if (use_seconds) { return Math.floor((new Date()).getTime() / 1000); } else { return (new Date()).getTime(); } } sgx.utils = {}; sgx.utils.id_prefix = 'sgx-'; sgx.utils.id_seed = 0; sgx.generate_id = function() { return (sgx.utils.id_prefix + sgx.utils.id_seed++); }; sgx.conf = function(o, d, t) { // Take the user supplied config object o, default config d, and object t // d = {fieldname: {type: typeval, default: value}, etc.} var t = t ? t : {}; var n; for (n in d) { d[n]['default'] = (typeof d[n]['default'] != 'undefined') ? d[n]['default'] : ''; d[n]['type'] = (typeof d[n]['type'] != 'undefined') ? d[n]['type'] : 's'; //d[n]['value'] = (typeof o[n] == 'undefined') ? d[n]['default'] : o[n]; if(typeof o[n] != 'undefined') { // User defined this value d[n]['value'] = o[n]; } else if(typeof d[n]['default'] == 'undefined') { d[n]['value'] = ''; } else { d[n]['value'] = d[n]['default']; } t[n] = sgx.cast(d[n]['value'], d[n]['type']).value; } return t; }; sgx.math = {}; sgx.math.log = function(base, value) { return (Math.log(value) / Math.log(base)); } sgx.math.log10 = function(value) { return sgx.math.log(10, value); } sgx.string = {}; sgx.string.trim = function(str) { return sgx.string.ltrim(sgx.string.rtrim(str)); }; sgx.string.ltrim = function(str) { return str.replace(/[\n\s]*$/g, ''); }; sgx.string.rtrim = function(str) { return str.replace(/^[\n\s]*/g, ''); }; sgx.string.str_repeat = function(i, m) { for (var o = []; m > 0; o[--m] = i); return(o.join('')); } sgx.string.sprintf = function() { var i = 0, a, f = arguments[i++], o = [], m, p, c, x; while (f) { if (m = /^[^\x25]+/.exec(f)) o.push(m[0]); else if (m = /^\x25{2}/.exec(f)) o.push('%'); else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) { if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) throw("Too few arguments."); if (/[^s]/.test(m[7]) && (typeof(a) != 'number')) throw("Expecting number but found " + typeof(a)); switch (m[7]) { case 'b': a = a.toString(2); break; case 'c': a = String.fromCharCode(a); break; case 'd': a = parseInt(a); break; case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break; case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break; case 'o': a = a.toString(8); break; case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break; case 'u': a = Math.abs(a); break; case 'x': a = a.toString(16); break; case 'X': a = a.toString(16).toUpperCase(); break; } a = (/[def]/.test(m[7]) && m[2] && a > 0 ? '+' + a : a); c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' '; x = m[5] - String(a).length; p = m[5] ? sgx.string.str_repeat(c, x) : ''; o.push(m[4] ? a + p : p + a); } else throw ("Huh ?!"); f = f.substring(m[0].length); } return o.join(''); } /* sgx.string.simple_sprintf = function(str, ar) { // Similar to php's sprintf but only formats string data ie just inserts parameters in an array) var reg; for(var n in ar) { reg = new RegExp('%' + n + '\$s', 'g'); str = str.replace(reg, ar[n]); alert(ar[n]); } return str; } */ sgx.jquery_escape = function(id) { var strEsc = '#;&,.+*~\':"!^$[]()=>|/'; var len = strEsc.length; var chr = ''; for (var i = 0; i < len; i++) { chr = strEsc.substr(i, 1); id = id.replace(chr, '\\' + chr); } return id; } sgx.post = function(o) { var opts = sgx.conf(o, { url: {'default': false, 'required': true, 'type': 'sic'}, data: {'default': false, 'required': true, 'type': 'object'}, error: {'default': function() {}, 'required': false, 'type': 'function'}, success: {'default': function() {}, 'required': false, 'type': 'function'}, method: {'default': 'POST', 'required': false, 'type': 'string'}, responseType: {'default': 'json', 'required': false, 'type': 'string'} }, opts); $.ajax({ url: opts.url, type: opts.method, data: opts.data, dataType: opts.responseType, error: opts.error, success: opts.success }); } /** * Requires an ajax script for processing and form posting. The request style and json response should be used * * Requests include: * - sgx.fDialog.info * - sgx.fDialog.upload * - sgx.fDialog.delete * * The image source should be a path that can have an ID appended to the url to get the specific picture uploaded. */ sgx.file_dialog = function(o) { var t = this; sgx.conf(o, { 'input': {'default': {}, 'required': true, 'type': 'object'}, // The html element that is the hidden file_id input 'image': {'default': false, 'required': false, 'type': 'bool'}, // Whether this is an image upload or not. Adds a preview pane and thumbnail 'download_script': {'default': '', 'required': false, 'type': 'sic'}, // Script that processes the image for thumbs (takes an id as GET input) 'handler_script': {'default': '', 'required': true, 'type': 'sic'}, // Script that processes info, upload and delete requests 'custom_fields': {'default': [], 'required': false, 'type': 'a'}, // Additional fields to add to the file upload dialog 'error_handler': {'default': function() {}, 'required': false, 'type': 'func'}, // Special function that processes error messages 'strings': {'default': {}, 'required': false, 'type': 'obj'}, // Allow setting of all output strings for multilingual support 'img_max_width': {'default': 300, 'required': false, 'type': 'int'} // Maximum width of the image, applied through CSS max-width }, this); // Assign default values to the strings object if they are not supplied this.strings = sgx.conf(this.strings, { 'lbl_file': {'default': 'Select a File', 'required': false, 'type': 'sic'}, 'ttl_image': {'default': 'Image Upload', 'required': false, 'type': 'sic'}, 'btn_change': {'default': 'Change', 'required': false, 'type': 'sic'}, 'btn_upload': {'default': 'Upload', 'required': false, 'type': 'sic'}, 'btn_clear': {'default': 'Clear', 'required': false, 'type': 'sic'}, 'btn_cancel': {'default': 'Cancel', 'required': false, 'type': 'sic'}, 'btn_close': {'default': 'Close', 'required': false, 'type': 'sic'}, 'err_parse': {'default': 'Upload failed: Could not parse server response', 'required': false, 'type': 'sic'}, 'ttl_dialog_file' : {'default': 'Upload File', 'required': false, 'type': 'sic'}, 'ttl_dialog_img' : {'default': 'Upload Image', 'required': false, 'type': 'sic'}, 'ttl_download': {'default': 'Download', 'required': false, 'type': 'sic'} }); if(this.view_script == '') { this.view_script = this.handler_script; } this.events = {}; this.enable_upload = true; this.core_id = sgx.generate_id(); this.$input = $(this.input); // Starts as a hidden input field. Surround it in the canvas div and then add all kinds of stuff to it this.build = function() { var esc = this.id_esc; // Quick ID function var file_type = this.image ? 'image' : 'file'; this.$input.wrap('
'); $(esc('_object')).append('
' + '
' + // ''); ''); $('body').append('
' + '
'); $(esc('_inner')).append('
' + '
' + '
' + '
'); if(this.image) { $(esc('_inner')).append('
' + '' + '
'); $(esc('_inner')).find('img.sgx-fDialog-content').css('max-width', t.img_max_width); } // Build the visible input lines of the form. The file input is first, followed by any custom fields in this.custom_fields var form_lines = '
' + '
' + t.strings.lbl_file + ':
' + '
' + '
'; for (var i = 0; i < this.custom_fields.length; i++) { if(typeof this.custom_fields[i] == 'object') { form_lines += '
' + '
' + this.custom_fields[i].label + ':
' + '
' + this.custom_fields[i].input + '
' + '
'; } else { form_lines += '
' + this.custom_fields[i] + '
'; } } $(esc('_append') + ' > .sgx-fDialog-append').append('
' + '
' + '' + '' + '' + form_lines + '
' + '
'); }; this.events.thumb_hover = function (el, enterExit) { if(enterExit) { $(el).addClass('sgx-fDialog-thumbhover'); } else { $(el).removeClass('sgx-fDialog-thumbhover'); } } this.events.browse = function () { // Set the upload dialog ID as the main ID $(t.id_esc('_dialog') + " > input[name='id']").val(t.file_id()); // Open the dialog $(t.id_esc('_dialog')).dialog('open'); } this.events.upload = function(dialog, success_function, error_function) { var func_s = typeof success_function == 'function' ? success_function : function() {}; var func_e = typeof error_function == 'function' ? error_function : function() {}; if(t.enable_upload) { t.enable_upload = false; var iframe_name = t.core_id + '_iframe'; var $iframe = $('