/* -*- js-indent-level: 8 -*- */ /* w2ui 1.5.rc1 (nightly) (c) http://w2ui.com, vitmalina@gmail.com */ var w2ui = w2ui || {}; var w2obj = w2obj || {}; // expose object to be able to overwrite default functions /************************************************ * Library: Web 2.0 UI for jQuery * - Following objects are defines * - w2ui - object that will contain all widgets * - w2obj - object with widget prototypes * - w2utils - basic utilities * - $().w2render - common render * - $().w2destroy - common destroy * - $().w2marker - marker plugin * - $().w2tag - tag plugin * - $().w2overlay - overlay plugin * - $().w2menu - menu plugin * - w2utils.event - generic event object * - Dependencies: jQuery * * == NICE TO HAVE == * - overlay should be displayed where more space (on top or on bottom) * - write and article how to replace certain framework functions * - add maxHeight for the w2menu * - add time zone * - TEST On IOS * - $().w2marker() -- only unmarks first instance * - subitems for w2menus() * - add w2utils.lang wrap for all captions in all buttons. * - $().w2date(), $().w2dateTime() * ************************************************/ var w2utils = (function ($) { var tmp = {}; // for some temp variables var obj = { version : '1.5.RC1', settings : { "locale" : "en-us", "dateFormat" : "m/d/yyyy", "timeFormat" : "hh:mi pm", "datetimeFormat" : "m/d/yyyy|hh:mi pm", "currencyPrefix" : "$", "currencySuffix" : "", "currencyPrecision" : 2, "groupSymbol" : ",", "decimalSymbol" : ".", "shortmonths" : ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], "fullmonths" : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], "shortdays" : ["M", "T", "W", "T", "F", "S", "S"], "fulldays" : ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], "weekStarts" : "M", // can be "M" for Monday or "S" for Sunday "dataType" : 'HTTPJSON', // can be HTTP, HTTPJSON, RESTFULL, RESTFULLJSON, JSON (case sensitive) "phrases" : {}, // empty object for english phrases "dateStartYear" : 1950, // start year for date-picker "dateEndYear" : 2020 // end year for date picker }, isBin : isBin, isInt : isInt, isFloat : isFloat, isMoney : isMoney, isHex : isHex, isAlphaNumeric : isAlphaNumeric, isEmail : isEmail, isDate : isDate, isTime : isTime, isDateTime : isDateTime, age : age, interval : interval, date : date, formatSize : formatSize, formatNumber : formatNumber, formatDate : formatDate, formatTime : formatTime, formatDateTime : formatDateTime, stripTags : stripTags, encodeTags : encodeTags, decodeTags : decodeTags, escapeId : escapeId, base64encode : base64encode, base64decode : base64decode, md5 : md5, transition : transition, lock : lock, unlock : unlock, message : message, lang : lang, locale : locale, getSize : getSize, getStrWidth : getStrWidth, scrollBarSize : scrollBarSize, checkName : checkName, checkUniqueId : checkUniqueId, parseRoute : parseRoute, cssPrefix : cssPrefix, getCursorPosition : getCursorPosition, setCursorPosition : setCursorPosition, testLocalStorage : testLocalStorage, hasLocalStorage : testLocalStorage(), // some internal variables isIOS : ((navigator.userAgent.toLowerCase().indexOf('iphone') != -1 || navigator.userAgent.toLowerCase().indexOf('ipod') != -1 || navigator.userAgent.toLowerCase().indexOf('ipad') != -1) ? true : false), isIE : ((navigator.userAgent.toLowerCase().indexOf('msie') != -1 || navigator.userAgent.toLowerCase().indexOf('trident') != -1 ) ? true : false) }; return obj; function isBin (val) { var re = /^[0-1]+$/; return re.test(val); } function isInt (val) { var re = /^[-+]?[0-9]+$/; return re.test(val); } function isFloat (val) { if (typeof val == 'string') val = val.replace(/\s+/g, '').replace(w2utils.settings.groupSymbol, '').replace(w2utils.settings.decimalSymbol, '.'); return (typeof val === 'number' || (typeof val === 'string' && val !== '')) && !isNaN(Number(val)); } function isMoney (val) { var se = w2utils.settings; var re = new RegExp('^'+ (se.currencyPrefix ? '\\' + se.currencyPrefix + '?' : '') + '[-+]?'+ (se.currencyPrefix ? '\\' + se.currencyPrefix + '?' : '') + '[0-9]*[\\'+ se.decimalSymbol +']?[0-9]+'+ (se.currencySuffix ? '\\' + se.currencySuffix + '?' : '') +'$', 'i'); if (typeof val === 'string') { val = val.replace(new RegExp(se.groupSymbol, 'g'), ''); } if (typeof val === 'object' || val === '') return false; return re.test(val); } function isHex (val) { var re = /^[a-fA-F0-9]+$/; return re.test(val); } function isAlphaNumeric (val) { var re = /^[a-zA-Z0-9_-]+$/; return re.test(val); } function isEmail (val) { var email = /^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/; return email.test(val); } function isDate (val, format, retDate) { if (!val) return false; var dt = 'Invalid Date'; var month, day, year; if (format == null) format = w2utils.settings.dateFormat; if (typeof val.getUTCFullYear === 'function') { // date object year = val.getUTCFullYear(); month = val.getUTCMonth() + 1; day = val.getUTCDate(); } else if (parseInt(val) == val && parseInt(val) > 0) { val = new Date(parseInt(val)); year = val.getUTCFullYear(); month = val.getUTCMonth() + 1; day = val.getUTCDate(); } else { val = String(val); // convert month formats if (new RegExp('mon', 'ig').test(format)) { format = format.replace(/month/ig, 'm').replace(/mon/ig, 'm').replace(/dd/ig, 'd').replace(/[, ]/ig, '/').replace(/\/\//g, '/').toLowerCase(); val = val.replace(/[, ]/ig, '/').replace(/\/\//g, '/').toLowerCase(); for (var m = 0, len = w2utils.settings.fullmonths.length; m < len; m++) { var t = w2utils.settings.fullmonths[m]; val = val.replace(new RegExp(t, 'ig'), (parseInt(m) + 1)).replace(new RegExp(t.substr(0, 3), 'ig'), (parseInt(m) + 1)); } } // format date var tmp = val.replace(/-/g, '/').replace(/\./g, '/').toLowerCase().split('/'); var tmp2 = format.replace(/-/g, '/').replace(/\./g, '/').toLowerCase(); if (tmp2 === 'mm/dd/yyyy') { month = tmp[0]; day = tmp[1]; year = tmp[2]; } if (tmp2 === 'm/d/yyyy') { month = tmp[0]; day = tmp[1]; year = tmp[2]; } if (tmp2 === 'dd/mm/yyyy') { month = tmp[1]; day = tmp[0]; year = tmp[2]; } if (tmp2 === 'd/m/yyyy') { month = tmp[1]; day = tmp[0]; year = tmp[2]; } if (tmp2 === 'yyyy/dd/mm') { month = tmp[2]; day = tmp[1]; year = tmp[0]; } if (tmp2 === 'yyyy/d/m') { month = tmp[2]; day = tmp[1]; year = tmp[0]; } if (tmp2 === 'yyyy/mm/dd') { month = tmp[1]; day = tmp[2]; year = tmp[0]; } if (tmp2 === 'yyyy/m/d') { month = tmp[1]; day = tmp[2]; year = tmp[0]; } if (tmp2 === 'mm/dd/yy') { month = tmp[0]; day = tmp[1]; year = tmp[2]; } if (tmp2 === 'm/d/yy') { month = tmp[0]; day = tmp[1]; year = parseInt(tmp[2]) + 1900; } if (tmp2 === 'dd/mm/yy') { month = tmp[1]; day = tmp[0]; year = parseInt(tmp[2]) + 1900; } if (tmp2 === 'd/m/yy') { month = tmp[1]; day = tmp[0]; year = parseInt(tmp[2]) + 1900; } if (tmp2 === 'yy/dd/mm') { month = tmp[2]; day = tmp[1]; year = parseInt(tmp[0]) + 1900; } if (tmp2 === 'yy/d/m') { month = tmp[2]; day = tmp[1]; year = parseInt(tmp[0]) + 1900; } if (tmp2 === 'yy/mm/dd') { month = tmp[1]; day = tmp[2]; year = parseInt(tmp[0]) + 1900; } if (tmp2 === 'yy/m/d') { month = tmp[1]; day = tmp[2]; year = parseInt(tmp[0]) + 1900; } } if (!isInt(year)) return false; if (!isInt(month)) return false; if (!isInt(day)) return false; year = +year; month = +month; day = +day; dt = new Date(year, month - 1, day); // do checks if (month == null) return false; if (String(dt) == 'Invalid Date') return false; if ((dt.getMonth() + 1 !== month) || (dt.getDate() !== day) || (dt.getFullYear() !== year)) return false; if (retDate === true) return dt; else return true; } function isTime (val, retTime) { // Both formats 10:20pm and 22:20 if (val == null) return false; var max, am, pm; // -- process american format val = String(val); val = val.toUpperCase(); am = val.indexOf('AM') >= 0; pm = val.indexOf('PM') >= 0; var ampm = (pm || am); if (ampm) max = 12; else max = 24; val = val.replace('AM', '').replace('PM', ''); val = $.trim(val); // --- var tmp = val.split(':'); var h = parseInt(tmp[0] || 0), m = parseInt(tmp[1] || 0), s = parseInt(tmp[2] || 0); // accept edge case: 3PM is a good timestamp, but 3 (without AM or PM) is NOT: if ((!ampm || tmp.length !== 1) && tmp.length !== 2 && tmp.length !== 3) { return false; } if (tmp[0] === '' || h < 0 || h > max || !this.isInt(tmp[0]) || tmp[0].length > 2) { return false; } if (tmp.length > 1 && (tmp[1] === '' || m < 0 || m > 59 || !this.isInt(tmp[1]) || tmp[1].length !== 2)) { return false; } if (tmp.length > 2 && (tmp[2] === '' || s < 0 || s > 59 || !this.isInt(tmp[2]) || tmp[2].length !== 2)) { return false; } // check the edge cases: 12:01AM is ok, as is 12:01PM, but 24:01 is NOT ok while 24:00 is (midnight; equivalent to 00:00). // meanwhile, there is 00:00 which is ok, but 0AM nor 0PM are okay, while 0:01AM and 0:00AM are. if (!ampm && max === h && (m !== 0 || s !== 0)) { return false; } if (ampm && tmp.length === 1 && h === 0) { return false; } if (retTime === true) { if (pm && h !== 12) h += 12; // 12:00pm - is noon if (am && h === 12) h += 12; // 12:00am - is midnight return { hours: h, minutes: m, seconds: s }; } return true; } function isDateTime (val, format, retDate) { if (format == null) format = w2utils.settings.datetimeFormat; var formats = format.split('|'); if (typeof val.getUTCFullYear === 'function') { // date object if (retDate !== true) return true; return val; } else if (parseInt(val) == val && parseInt(val) > 0) { val = new Date(parseInt(val)); if (retDate !== true) return true; return val; } else { var tmp = String(val).indexOf(' '); var values = [val.substr(0, tmp), val.substr(tmp).trim()]; formats[0] = formats[0].trim(); if (formats[1]) formats[1] = formats[1].trim(); // check var tmp1 = w2utils.isDate(values[0], formats[0], true); var tmp2 = w2utils.isTime(values[1], true); if (tmp1 !== false && tmp2 !== false) { if (retDate !== true) return true; tmp1.setHours(tmp2.hours); tmp1.setMinutes(tmp2.minutes); tmp1.setSeconds(tmp2.seconds); return tmp1; } else { return false; } } } function age(dateStr) { var d1; if (dateStr === '' || dateStr == null) return ''; if (typeof dateStr.getUTCFullYear === 'function') { // date object d1 = dateStr; } else if (parseInt(dateStr) == dateStr && parseInt(dateStr) > 0) { d1 = new Date(parseInt(dateStr)); } else { d1 = new Date(dateStr); } if (String(d1) == 'Invalid Date') return ''; var d2 = new Date(); var sec = (d2.getTime() - d1.getTime()) / 1000; var amount = ''; var type = ''; if (sec < 0) { amount = 0; type = 'sec'; } else if (sec < 60) { amount = Math.floor(sec); type = 'sec'; if (sec < 0) { amount = 0; type = 'sec'; } } else if (sec < 60*60) { amount = Math.floor(sec/60); type = 'min'; } else if (sec < 24*60*60) { amount = Math.floor(sec/60/60); type = 'hour'; } else if (sec < 30*24*60*60) { amount = Math.floor(sec/24/60/60); type = 'day'; } else if (sec < 365*24*60*60) { amount = Math.floor(sec/30/24/60/60*10)/10; type = 'month'; } else if (sec < 365*4*24*60*60) { amount = Math.floor(sec/365/24/60/60*10)/10; type = 'year'; } else if (sec >= 365*4*24*60*60) { // factor in leap year shift (only older then 4 years) amount = Math.floor(sec/365.25/24/60/60*10)/10; type = 'year'; } return amount + ' ' + type + (amount > 1 ? 's' : ''); } function interval (value) { var ret = ''; if (value < 1000) { ret = "< 1 sec"; } else if (value < 60000) { ret = Math.floor(value / 1000) + " secs"; } else if (value < 3600000) { ret = Math.floor(value / 60000) + " mins"; } else if (value < 86400000) { ret = Math.floor(value / 3600000 * 10) / 10 + " hours"; } else if (value < 2628000000) { ret = Math.floor(value / 86400000 * 10) / 10 + " days"; } else if (value < 3.1536e+10) { ret = Math.floor(value / 2628000000 * 10) / 10 + " months"; } else { ret = Math.floor(value / 3.1536e+9) / 10 + " years"; } return ret; } function date (dateStr) { if (dateStr === '' || dateStr == null || (typeof dateStr == 'object' && !dateStr.getMonth)) return ''; var d1 = new Date(dateStr); if (w2utils.isInt(dateStr)) d1 = new Date(Number(dateStr)); // for unix timestamps if (String(d1) == 'Invalid Date') return ''; var months = w2utils.settings.shortmonths; var d2 = new Date(); // today var d3 = new Date(); d3.setTime(d3.getTime() - 86400000); // yesterday var dd1 = months[d1.getMonth()] + ' ' + d1.getDate() + ', ' + d1.getFullYear(); var dd2 = months[d2.getMonth()] + ' ' + d2.getDate() + ', ' + d2.getFullYear(); var dd3 = months[d3.getMonth()] + ' ' + d3.getDate() + ', ' + d3.getFullYear(); var time = (d1.getHours() - (d1.getHours() > 12 ? 12 :0)) + ':' + (d1.getMinutes() < 10 ? '0' : '') + d1.getMinutes() + ' ' + (d1.getHours() >= 12 ? 'pm' : 'am'); var time2= (d1.getHours() - (d1.getHours() > 12 ? 12 :0)) + ':' + (d1.getMinutes() < 10 ? '0' : '') + d1.getMinutes() + ':' + (d1.getSeconds() < 10 ? '0' : '') + d1.getSeconds() + ' ' + (d1.getHours() >= 12 ? 'pm' : 'am'); var dsp = dd1; if (dd1 === dd2) dsp = time; if (dd1 === dd3) dsp = w2utils.lang('Yesterday'); return ''+ dsp +''; } function formatSize (sizeStr) { if (!w2utils.isFloat(sizeStr) || sizeStr === '') return ''; sizeStr = parseFloat(sizeStr); if (sizeStr === 0) return 0; var sizes = ['Bt', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB']; var i = parseInt( Math.floor( Math.log(sizeStr) / Math.log(1024) ) ); return (Math.floor(sizeStr / Math.pow(1024, i) * 10) / 10).toFixed(i === 0 ? 0 : 1) + ' ' + (sizes[i] || '??'); } function formatNumber (val, fraction, useGrouping) { if (val == null || val === '' || typeof val == 'object') return ''; var options = { minimumFractionDigits : fraction, maximumFractionDigits : fraction, useGrouping : useGrouping }; if (fraction == null || fraction < 0) { options.minimumFractionDigits = 0; options.maximumFractionDigits = 20; } return parseFloat(val).toLocaleString(w2utils.settings.locale, options); } function formatDate (dateStr, format) { // IMPORTANT dateStr HAS TO BE valid JavaScript Date String if (!format) format = this.settings.dateFormat; if (dateStr === '' || dateStr == null || (typeof dateStr == 'object' && !dateStr.getMonth)) return ''; var dt = new Date(dateStr); if (w2utils.isInt(dateStr)) dt = new Date(Number(dateStr)); // for unix timestamps if (String(dt) == 'Invalid Date') return ''; var year = dt.getFullYear(); var month = dt.getMonth(); var date = dt.getDate(); return format.toLowerCase() .replace('month', w2utils.settings.fullmonths[month]) .replace('mon', w2utils.settings.shortmonths[month]) .replace(/yyyy/g, year) .replace(/yyy/g, year) .replace(/yy/g, year > 2000 ? 100 + parseInt(String(year).substr(2)) : String(year).substr(2)) .replace(/(^|[^a-z$])y/g, '$1' + year) // only y's that are not preceded by a letter .replace(/mm/g, (month + 1 < 10 ? '0' : '') + (month + 1)) .replace(/dd/g, (date < 10 ? '0' : '') + date) .replace(/th/g, (date == 1 ? 'st' : 'th')) .replace(/th/g, (date == 2 ? 'nd' : 'th')) .replace(/th/g, (date == 3 ? 'rd' : 'th')) .replace(/(^|[^a-z$])m/g, '$1' + (month + 1)) // only y's that are not preceded by a letter .replace(/(^|[^a-z$])d/g, '$1' + date); // only y's that are not preceded by a letter } function formatTime (dateStr, format) { // IMPORTANT dateStr HAS TO BE valid JavaScript Date String if (!format) format = this.settings.timeFormat; if (dateStr === '' || dateStr == null || (typeof dateStr == 'object' && !dateStr.getMonth)) return ''; var dt = new Date(dateStr); if (w2utils.isInt(dateStr)) dt = new Date(Number(dateStr)); // for unix timestamps if (w2utils.isTime(dateStr)) { var tmp = w2utils.isTime(dateStr, true); dt = new Date(); dt.setHours(tmp.hours); dt.setMinutes(tmp.minutes); } if (String(dt) == 'Invalid Date') return ''; var type = 'am'; var hour = dt.getHours(); var h24 = dt.getHours(); var min = dt.getMinutes(); var sec = dt.getSeconds(); if (min < 10) min = '0' + min; if (sec < 10) sec = '0' + sec; if (format.indexOf('am') !== -1 || format.indexOf('pm') !== -1) { if (hour >= 12) type = 'pm'; if (hour > 12) hour = hour - 12; } return format.toLowerCase() .replace('am', type) .replace('pm', type) .replace('hhh', (hour < 10 ? '0' + hour : hour)) .replace('hh24', (h24 < 10 ? '0' + h24 : h24)) .replace('h24', h24) .replace('hh', hour) .replace('mm', min) .replace('mi', min) .replace('ss', sec) .replace(/(^|[^a-z$])h/g, '$1' + hour) // only y's that are not preceded by a letter .replace(/(^|[^a-z$])m/g, '$1' + min) // only y's that are not preceded by a letter .replace(/(^|[^a-z$])s/g, '$1' + sec); // only y's that are not preceded by a letter } function formatDateTime(dateStr, format) { var fmt; if (dateStr === '' || dateStr == null || (typeof dateStr == 'object' && !dateStr.getMonth)) return ''; if (typeof format !== 'string') { fmt = [this.settings.dateFormat, this.settings.timeFormat]; } else { fmt = format.split('|'); fmt[0] = fmt[0].trim(); fmt[1] = fmt[1].trim(); } // older formats support if (fmt[1] == 'h12') fmt[1] = 'h:m pm'; if (fmt[1] == 'h24') fmt[1] = 'h24:m'; return this.formatDate(dateStr, fmt[0]) + ' ' + this.formatTime(dateStr, fmt[1]); } function stripTags (html) { if (html == null) return html; switch (typeof html) { case 'number': break; case 'string': html = String(html).replace(/(<([^>]+)>)/ig, ""); break; case 'object': // does not modify original object, but creates a copy if (Array.isArray(html)) { html = $.extend(true, [], html); for (var i = 0; i < html.length; i++) html[i] = this.stripTags(html[i]); } else { html = $.extend(true, {}, html); for (var i in html) html[i] = this.stripTags(html[i]); } break; } return html; } function encodeTags (html) { if (html == null) return html; switch (typeof html) { case 'number': break; case 'string': html = String(html).replace(/&/g, "&").replace(/>/g, ">").replace(/").replace(/</g, "<").replace(/"/g, '"').replace(/&/g, "&"); break; case 'object': // does not modify original object, but creates a copy if (Array.isArray(html)) { html = $.extend(true, [], html); for (var i = 0; i < html.length; i++) html[i] = this.decodeTags(html[i]); } else { html = $.extend(true, {}, html); for (var i in html) html[i] = this.decodeTags(html[i]); } break; } return html; } function escapeId (id) { if (id === '' || id == null) return ''; return String(id).replace(/([;&,\.\+\*\~'`:"\!\^#$%@\[\]\(\)=<>\|\/? {}\\])/g, '\\$1'); } function base64encode (input) { var output = ""; var chr1, chr2, chr3, enc1, enc2, enc3, enc4; var i = 0; var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; input = utf8_encode(input); while (i < input.length) { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); } function utf8_encode (string) { string = String(string).replace(/\r\n/g,"\n"); var utftext = ""; for (var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); } else if((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } return utftext; } return output; } function base64decode (input) { var output = ""; var chr1, chr2, chr3; var enc1, enc2, enc3, enc4; var i = 0; var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); while (i < input.length) { enc1 = keyStr.indexOf(input.charAt(i++)); enc2 = keyStr.indexOf(input.charAt(i++)); enc3 = keyStr.indexOf(input.charAt(i++)); enc4 = keyStr.indexOf(input.charAt(i++)); chr1 = (enc1 << 2) | (enc2 >> 4); chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); chr3 = ((enc3 & 3) << 6) | enc4; output = output + String.fromCharCode(chr1); if (enc3 !== 64) { output = output + String.fromCharCode(chr2); } if (enc4 !== 64) { output = output + String.fromCharCode(chr3); } } output = utf8_decode(output); function utf8_decode (utftext) { var string = ""; var i = 0; var c = 0, c2, c3; while ( i < utftext.length ) { c = utftext.charCodeAt(i); if (c < 128) { string += String.fromCharCode(c); i++; } else if((c > 191) && (c < 224)) { c2 = utftext.charCodeAt(i+1); string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); i += 2; } else { c2 = utftext.charCodeAt(i+1); c3 = utftext.charCodeAt(i+2); string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); i += 3; } } return string; } return output; } function md5(input) { /* * Based on http://pajhome.org.uk/crypt/md5 */ var hexcase = 0; var b64pad = ""; function __pj_crypt_hex_md5(s) { return __pj_crypt_rstr2hex(__pj_crypt_rstr_md5(__pj_crypt_str2rstr_utf8(s))); } function __pj_crypt_b64_md5(s) { return __pj_crypt_rstr2b64(__pj_crypt_rstr_md5(__pj_crypt_str2rstr_utf8(s))); } function __pj_crypt_any_md5(s, e) { return __pj_crypt_rstr2any(__pj_crypt_rstr_md5(__pj_crypt_str2rstr_utf8(s)), e); } function __pj_crypt_hex_hmac_md5(k, d) { return __pj_crypt_rstr2hex(__pj_crypt_rstr_hmac_md5(__pj_crypt_str2rstr_utf8(k), __pj_crypt_str2rstr_utf8(d))); } function __pj_crypt_b64_hmac_md5(k, d) { return __pj_crypt_rstr2b64(__pj_crypt_rstr_hmac_md5(__pj_crypt_str2rstr_utf8(k), __pj_crypt_str2rstr_utf8(d))); } function __pj_crypt_any_hmac_md5(k, d, e) { return __pj_crypt_rstr2any(__pj_crypt_rstr_hmac_md5(__pj_crypt_str2rstr_utf8(k), __pj_crypt_str2rstr_utf8(d)), e); } /* * Calculate the MD5 of a raw string */ function __pj_crypt_rstr_md5(s) { return __pj_crypt_binl2rstr(__pj_crypt_binl_md5(__pj_crypt_rstr2binl(s), s.length * 8)); } /* * Calculate the HMAC-MD5, of a key and some data (raw strings) */ function __pj_crypt_rstr_hmac_md5(key, data) { var bkey = __pj_crypt_rstr2binl(key); if (bkey.length > 16) bkey = __pj_crypt_binl_md5(bkey, key.length * 8); var ipad = Array(16), opad = Array(16); for (var i = 0; i < 16; i++) { ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5C5C5C5C; } var hash = __pj_crypt_binl_md5(ipad.concat(__pj_crypt_rstr2binl(data)), 512 + data.length * 8); return __pj_crypt_binl2rstr(__pj_crypt_binl_md5(opad.concat(hash), 512 + 128)); } /* * Convert a raw string to a hex string */ function __pj_crypt_rstr2hex(input) { try { hexcase } catch (e) { hexcase = 0; } var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var output = ""; var x; for (var i = 0; i < input.length; i++) { x = input.charCodeAt(i); output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F); } return output; } /* * Convert a raw string to a base-64 string */ function __pj_crypt_rstr2b64(input) { try { b64pad } catch (e) { b64pad = ''; } var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var output = ""; var len = input.length; for (var i = 0; i < len; i += 3) { var triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0); for (var j = 0; j < 4; j++) { if (i * 8 + j * 6 > input.length * 8) output += b64pad; else output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F); } } return output; } /* * Convert a raw string to an arbitrary string encoding */ function __pj_crypt_rstr2any(input, encoding) { var divisor = encoding.length; var i, j, q, x, quotient; /* Convert to an array of 16-bit big-endian values, forming the dividend */ var dividend = Array(Math.ceil(input.length / 2)); for (i = 0; i < dividend.length; i++) { dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); } /* * Repeatedly perform a long division. The binary array forms the dividend, * the length of the encoding is the divisor. Once computed, the quotient * forms the dividend for the next step. All remainders are stored for later * use. */ var full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2))); var remainders = Array(full_length); for (j = 0; j < full_length; j++) { quotient = Array(); x = 0; for (i = 0; i < dividend.length; i++) { x = (x << 16) + dividend[i]; q = Math.floor(x / divisor); x -= q * divisor; if (quotient.length > 0 || q > 0) quotient[quotient.length] = q; } remainders[j] = x; dividend = quotient; } /* Convert the remainders to the output string */ var output = ""; for (i = remainders.length - 1; i >= 0; i--) output += encoding.charAt(remainders[i]); return output; } /* * Encode a string as utf-8. * For efficiency, this assumes the input is valid utf-16. */ function __pj_crypt_str2rstr_utf8(input) { var output = ""; var i = -1; var x, y; while (++i < input.length) { /* Decode utf-16 surrogate pairs */ x = input.charCodeAt(i); y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) { x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); i++; } /* Encode output as utf-8 */ if (x <= 0x7F) output += String.fromCharCode(x); else if (x <= 0x7FF) output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F), 0x80 | (x & 0x3F)); else if (x <= 0xFFFF) output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), 0x80 | ((x >>> 6) & 0x3F), 0x80 | (x & 0x3F)); else if (x <= 0x1FFFFF) output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), 0x80 | ((x >>> 12) & 0x3F), 0x80 | ((x >>> 6) & 0x3F), 0x80 | (x & 0x3F)); } return output; } /* * Encode a string as utf-16 */ function __pj_crypt_str2rstr_utf16le(input) { var output = ""; for (var i = 0; i < input.length; i++) output += String.fromCharCode(input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF); return output; } function __pj_crypt_str2rstr_utf16be(input) { var output = ""; for (var i = 0; i < input.length; i++) output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF); return output; } /* * Convert a raw string to an array of little-endian words * Characters >255 have their high-byte silently ignored. */ function __pj_crypt_rstr2binl(input) { var output = Array(input.length >> 2); for (var i = 0; i < output.length; i++) output[i] = 0; for (var i = 0; i < input.length * 8; i += 8) output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32); return output; } /* * Convert an array of little-endian words to a string */ function __pj_crypt_binl2rstr(input) { var output = ""; for (var i = 0; i < input.length * 32; i += 8) output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); return output; } /* * Calculate the MD5 of an array of little-endian words, and a bit length. */ function __pj_crypt_binl_md5(x, len) { /* append padding */ x[len >> 5] |= 0x80 << ((len) % 32); x[(((len + 64) >>> 9) << 4) + 14] = len; var a = 1732584193; var b = -271733879; var c = -1732584194; var d = 271733878; for (var i = 0; i < x.length; i += 16) { var olda = a; var oldb = b; var oldc = c; var oldd = d; a = __pj_crypt_md5_ff(a, b, c, d, x[i + 0], 7, -680876936); d = __pj_crypt_md5_ff(d, a, b, c, x[i + 1], 12, -389564586); c = __pj_crypt_md5_ff(c, d, a, b, x[i + 2], 17, 606105819); b = __pj_crypt_md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); a = __pj_crypt_md5_ff(a, b, c, d, x[i + 4], 7, -176418897); d = __pj_crypt_md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); c = __pj_crypt_md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); b = __pj_crypt_md5_ff(b, c, d, a, x[i + 7], 22, -45705983); a = __pj_crypt_md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); d = __pj_crypt_md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); c = __pj_crypt_md5_ff(c, d, a, b, x[i + 10], 17, -42063); b = __pj_crypt_md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); a = __pj_crypt_md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); d = __pj_crypt_md5_ff(d, a, b, c, x[i + 13], 12, -40341101); c = __pj_crypt_md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); b = __pj_crypt_md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); a = __pj_crypt_md5_gg(a, b, c, d, x[i + 1], 5, -165796510); d = __pj_crypt_md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); c = __pj_crypt_md5_gg(c, d, a, b, x[i + 11], 14, 643717713); b = __pj_crypt_md5_gg(b, c, d, a, x[i + 0], 20, -373897302); a = __pj_crypt_md5_gg(a, b, c, d, x[i + 5], 5, -701558691); d = __pj_crypt_md5_gg(d, a, b, c, x[i + 10], 9, 38016083); c = __pj_crypt_md5_gg(c, d, a, b, x[i + 15], 14, -660478335); b = __pj_crypt_md5_gg(b, c, d, a, x[i + 4], 20, -405537848); a = __pj_crypt_md5_gg(a, b, c, d, x[i + 9], 5, 568446438); d = __pj_crypt_md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); c = __pj_crypt_md5_gg(c, d, a, b, x[i + 3], 14, -187363961); b = __pj_crypt_md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); a = __pj_crypt_md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); d = __pj_crypt_md5_gg(d, a, b, c, x[i + 2], 9, -51403784); c = __pj_crypt_md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); b = __pj_crypt_md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); a = __pj_crypt_md5_hh(a, b, c, d, x[i + 5], 4, -378558); d = __pj_crypt_md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); c = __pj_crypt_md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); b = __pj_crypt_md5_hh(b, c, d, a, x[i + 14], 23, -35309556); a = __pj_crypt_md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); d = __pj_crypt_md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); c = __pj_crypt_md5_hh(c, d, a, b, x[i + 7], 16, -155497632); b = __pj_crypt_md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); a = __pj_crypt_md5_hh(a, b, c, d, x[i + 13], 4, 681279174); d = __pj_crypt_md5_hh(d, a, b, c, x[i + 0], 11, -358537222); c = __pj_crypt_md5_hh(c, d, a, b, x[i + 3], 16, -722521979); b = __pj_crypt_md5_hh(b, c, d, a, x[i + 6], 23, 76029189); a = __pj_crypt_md5_hh(a, b, c, d, x[i + 9], 4, -640364487); d = __pj_crypt_md5_hh(d, a, b, c, x[i + 12], 11, -421815835); c = __pj_crypt_md5_hh(c, d, a, b, x[i + 15], 16, 530742520); b = __pj_crypt_md5_hh(b, c, d, a, x[i + 2], 23, -995338651); a = __pj_crypt_md5_ii(a, b, c, d, x[i + 0], 6, -198630844); d = __pj_crypt_md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); c = __pj_crypt_md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); b = __pj_crypt_md5_ii(b, c, d, a, x[i + 5], 21, -57434055); a = __pj_crypt_md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); d = __pj_crypt_md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); c = __pj_crypt_md5_ii(c, d, a, b, x[i + 10], 15, -1051523); b = __pj_crypt_md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); a = __pj_crypt_md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); d = __pj_crypt_md5_ii(d, a, b, c, x[i + 15], 10, -30611744); c = __pj_crypt_md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); b = __pj_crypt_md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); a = __pj_crypt_md5_ii(a, b, c, d, x[i + 4], 6, -145523070); d = __pj_crypt_md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); c = __pj_crypt_md5_ii(c, d, a, b, x[i + 2], 15, 718787259); b = __pj_crypt_md5_ii(b, c, d, a, x[i + 9], 21, -343485551); a = __pj_crypt_safe_add(a, olda); b = __pj_crypt_safe_add(b, oldb); c = __pj_crypt_safe_add(c, oldc); d = __pj_crypt_safe_add(d, oldd); } return Array(a, b, c, d); } /* * These functions implement the four basic operations the algorithm uses. */ function __pj_crypt_md5_cmn(q, a, b, x, s, t) { return __pj_crypt_safe_add(__pj_crypt_bit_rol(__pj_crypt_safe_add(__pj_crypt_safe_add(a, q), __pj_crypt_safe_add(x, t)), s), b); } function __pj_crypt_md5_ff(a, b, c, d, x, s, t) { return __pj_crypt_md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); } function __pj_crypt_md5_gg(a, b, c, d, x, s, t) { return __pj_crypt_md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); } function __pj_crypt_md5_hh(a, b, c, d, x, s, t) { return __pj_crypt_md5_cmn(b ^ c ^ d, a, b, x, s, t); } function __pj_crypt_md5_ii(a, b, c, d, x, s, t) { return __pj_crypt_md5_cmn(c ^ (b | (~d)), a, b, x, s, t); } /* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */ function __pj_crypt_safe_add(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } /* * Bitwise rotate a 32-bit number to the left. */ function __pj_crypt_bit_rol(num, cnt) { return (num << cnt) | (num >>> (32 - cnt)); } return __pj_crypt_hex_md5(input); } function transition (div_old, div_new, type, callBack) { var width = $(div_old).width(); var height = $(div_old).height(); var time = 0.5; if (!div_old || !div_new) { console.log('ERROR: Cannot do transition when one of the divs is null'); return; } div_old.parentNode.style.cssText += 'perspective: 900px; overflow: hidden;'; div_old.style.cssText += '; position: absolute; z-index: 1019; backface-visibility: hidden'; div_new.style.cssText += '; position: absolute; z-index: 1020; backface-visibility: hidden'; switch (type) { case 'slide-left': // init divs div_old.style.cssText += 'overflow: hidden; transform: translate3d(0, 0, 0)'; div_new.style.cssText += 'overflow: hidden; transform: translate3d('+ width + 'px, 0, 0)'; $(div_new).show(); // -- need a timing function because otherwise not working window.setTimeout(function() { div_new.style.cssText += 'transition: '+ time +'s; transform: translate3d(0, 0, 0)'; div_old.style.cssText += 'transition: '+ time +'s; transform: translate3d(-'+ width +'px, 0, 0)'; }, 1); break; case 'slide-right': // init divs div_old.style.cssText += 'overflow: hidden; transform: translate3d(0, 0, 0)'; div_new.style.cssText += 'overflow: hidden; transform: translate3d(-'+ width +'px, 0, 0)'; $(div_new).show(); // -- need a timing function because otherwise not working window.setTimeout(function() { div_new.style.cssText += 'transition: '+ time +'s; transform: translate3d(0px, 0, 0)'; div_old.style.cssText += 'transition: '+ time +'s; transform: translate3d('+ width +'px, 0, 0)'; }, 1); break; case 'slide-down': // init divs div_old.style.cssText += 'overflow: hidden; z-index: 1; transform: translate3d(0, 0, 0)'; div_new.style.cssText += 'overflow: hidden; z-index: 0; transform: translate3d(0, 0, 0)'; $(div_new).show(); // -- need a timing function because otherwise not working window.setTimeout(function() { div_new.style.cssText += 'transition: '+ time +'s; transform: translate3d(0, 0, 0)'; div_old.style.cssText += 'transition: '+ time +'s; transform: translate3d(0, '+ height +'px, 0)'; }, 1); break; case 'slide-up': // init divs div_old.style.cssText += 'overflow: hidden; transform: translate3d(0, 0, 0)'; div_new.style.cssText += 'overflow: hidden; transform: translate3d(0, '+ height +'px, 0)'; $(div_new).show(); // -- need a timing function because otherwise not working window.setTimeout(function() { div_new.style.cssText += 'transition: '+ time +'s; transform: translate3d(0, 0, 0)'; div_old.style.cssText += 'transition: '+ time +'s; transform: translate3d(0, 0, 0)'; }, 1); break; case 'flip-left': // init divs div_old.style.cssText += 'overflow: hidden; transform: rotateY(0deg)'; div_new.style.cssText += 'overflow: hidden; transform: rotateY(-180deg)'; $(div_new).show(); // -- need a timing function because otherwise not working window.setTimeout(function() { div_new.style.cssText += 'transition: '+ time +'s; transform: rotateY(0deg)'; div_old.style.cssText += 'transition: '+ time +'s; transform: rotateY(180deg)'; }, 1); break; case 'flip-right': // init divs div_old.style.cssText += 'overflow: hidden; transform: rotateY(0deg)'; div_new.style.cssText += 'overflow: hidden; transform: rotateY(180deg)'; $(div_new).show(); // -- need a timing function because otherwise not working window.setTimeout(function() { div_new.style.cssText += 'transition: '+ time +'s; transform: rotateY(0deg)'; div_old.style.cssText += 'transition: '+ time +'s; transform: rotateY(-180deg)'; }, 1); break; case 'flip-down': // init divs div_old.style.cssText += 'overflow: hidden; transform: rotateX(0deg)'; div_new.style.cssText += 'overflow: hidden; transform: rotateX(180deg)'; $(div_new).show(); // -- need a timing function because otherwise not working window.setTimeout(function() { div_new.style.cssText += 'transition: '+ time +'s; transform: rotateX(0deg)'; div_old.style.cssText += 'transition: '+ time +'s; transform: rotateX(-180deg)'; }, 1); break; case 'flip-up': // init divs div_old.style.cssText += 'overflow: hidden; transform: rotateX(0deg)'; div_new.style.cssText += 'overflow: hidden; transform: rotateX(-180deg)'; $(div_new).show(); // -- need a timing function because otherwise not working window.setTimeout(function() { div_new.style.cssText += 'transition: '+ time +'s; transform: rotateX(0deg)'; div_old.style.cssText += 'transition: '+ time +'s; transform: rotateX(180deg)'; }, 1); break; case 'pop-in': // init divs div_old.style.cssText += 'overflow: hidden; transform: translate3d(0, 0, 0)'; div_new.style.cssText += 'overflow: hidden; transform: translate3d(0, 0, 0); transform: scale(.8); opacity: 0;'; $(div_new).show(); // -- need a timing function because otherwise not working window.setTimeout(function() { div_new.style.cssText += 'transition: '+ time +'s; transform: scale(1); opacity: 1;'; div_old.style.cssText += 'transition: '+ time +'s;'; }, 1); break; case 'pop-out': // init divs div_old.style.cssText += 'overflow: hidden; transform: translate3d(0, 0, 0); transform: scale(1); opacity: 1;'; div_new.style.cssText += 'overflow: hidden; transform: translate3d(0, 0, 0); opacity: 0;'; $(div_new).show(); // -- need a timing function because otherwise not working window.setTimeout(function() { div_new.style.cssText += 'transition: '+ time +'s; opacity: 1;'; div_old.style.cssText += 'transition: '+ time +'s; transform: scale(1.7); opacity: 0;'; }, 1); break; default: // init divs div_old.style.cssText += 'overflow: hidden; transform: translate3d(0, 0, 0)'; div_new.style.cssText += 'overflow: hidden; translate3d(0, 0, 0); opacity: 0;'; $(div_new).show(); // -- need a timing function because otherwise not working window.setTimeout(function() { div_new.style.cssText += 'transition: '+ time +'s; opacity: 1;'; div_old.style.cssText += 'transition: '+ time +'s'; }, 1); break; } setTimeout(function () { if (type === 'slide-down') { $(div_old).css('z-index', '1019'); $(div_new).css('z-index', '1020'); } if (div_new) { $(div_new).css({ 'opacity': '1' }).css(w2utils.cssPrefix({ 'transition': '', 'transform' : '' })); } if (div_old) { $(div_old).css({ 'opacity': '1' }).css(w2utils.cssPrefix({ 'transition': '', 'transform' : '' })); } if (typeof callBack === 'function') callBack(); }, time * 1000); } function lock (box, msg, spinner) { var options = {}; if (typeof msg === 'object') { options = msg; } else { options.msg = msg; options.spinner = spinner; } if (!options.msg && options.msg !== 0) options.msg = ''; w2utils.unlock(box); $(box).prepend( '
'+ '
' ); var $lock = $(box).find('.w2ui-lock'); var mess = $(box).find('.w2ui-lock-msg'); if (!options.msg) mess.css({ 'background-color': 'transparent', 'border': '0px' }); if (options.spinner === true) options.msg = '
' + options.msg; if (options.opacity != null) $lock.css('opacity', options.opacity); if (typeof $lock.fadeIn == 'function') { $lock.fadeIn(200); mess.html(options.msg).fadeIn(200); mess.css({ 'display': 'flex', 'justify-content': 'center', 'align-items': 'center' }); } else { $lock.show(); mess.html(options.msg).show(0); } } function unlock (box, speed) { if (isInt(speed)) { $(box).find('.w2ui-lock').fadeOut(speed); setTimeout(function () { $(box).find('.w2ui-lock').remove(); $(box).find('.w2ui-lock-msg').remove(); }, speed); } else { $(box).find('.w2ui-lock').remove(); $(box).find('.w2ui-lock-msg').remove(); } } /** * Used in w2popup, w2grid, w2form, w2layout * should be called with .call(...) method */ function message(where, options) { var obj = this, closeTimer, edata; // var where.path = 'w2popup'; // var where.title = '.w2ui-popup-title'; // var where.body = '.w2ui-box'; $().w2tag(); // hide all tags if (!options) options = { width: 200, height: 100 }; if (options.on == null) $.extend(options, w2utils.event); if (options.width == null) options.width = 200; if (options.height == null) options.height = 100; var pWidth = parseInt($(where.box).width()); var pHeight = parseInt($(where.box).height()); var titleHeight = parseInt($(where.box).find(where.title).css('height') || 0); if (options.width > pWidth) options.width = pWidth - 10; if (options.height > pHeight - titleHeight) options.height = pHeight - 10 - titleHeight; options.originalWidth = options.width; options.originalHeight = options.height; if (parseInt(options.width) < 0) options.width = pWidth + options.width; if (parseInt(options.width) < 10) options.width = 10; if (parseInt(options.height) < 0) options.height = pHeight + options.height - titleHeight; if (parseInt(options.height) < 10) options.height = 10; if (options.hideOnClick == null) options.hideOnClick = false; var poptions = $(where.box).data('options') || {}; if (options.width == null || options.width > poptions.width - 10) { options.width = poptions.width - 10; } if (options.height == null || options.height > poptions.height - titleHeight - 5) { options.height = poptions.height - titleHeight - 5; // need margin from bottom only } // negative value means margin if (options.originalHeight < 0) options.height = pHeight + options.originalHeight - titleHeight; if (options.originalWidth < 0) options.width = pWidth + options.originalWidth * 2; // x 2 because there is left and right margin var head = $(where.box).find(where.title); // if some messages are closing, insta close them var $tmp = $(where.box).find('.w2ui-message.w2ui-closing'); if ($(where.box).find('.w2ui-message.w2ui-closing').length > 0) { clearTimeout(closeTimer); closeCB($tmp, $tmp.data('options') || {}); } var msgCount = $(where.box).find('.w2ui-message').length; // remove message if ($.trim(options.html) === '' && $.trim(options.body) === '' && $.trim(options.buttons) === '') { if (msgCount === 0) return; // no messages at all var $msg = $(where.box).find('#w2ui-message'+ (msgCount-1)); var options = $msg.data('options') || {}; // before event edata = options.trigger({ phase: 'before', type: 'close', target: 'self' }); if (edata.isCancelled === true) return; // default behavior $msg.css(w2utils.cssPrefix({ 'transition': '0.15s', 'transform': 'translateY(-' + options.height + 'px)' })).addClass('w2ui-closing'); if (msgCount == 1) { if (this.unlock) { if (where.param) this.unlock(where.param, 150); else this.unlock(150); } } else { $(where.box).find('#w2ui-message'+ (msgCount-2)).css('z-index', 1500); } closeTimer = setTimeout(function () { closeCB($msg, options) }, 150); } else { if ($.trim(options.body) !== '' || $.trim(options.buttons) !== '') { options.html = '
'+ (options.body || '') +'
'+ '
'+ (options.buttons || '') +'
'; } // hide previous messages $(where.box).find('.w2ui-message').css('z-index', 1390); head.data('old-z-index', head.css('z-index')); head.css('z-index', 1501); // add message $(where.box).find(where.body) .before(''); $(where.box).find('#w2ui-message'+ msgCount) .data('options', options) .data('prev_focus', $(':focus')); var display = $(where.box).find('#w2ui-message'+ msgCount).css('display'); $(where.box).find('#w2ui-message'+ msgCount).css(w2utils.cssPrefix({ 'transform': (display == 'none' ? 'translateY(-' + options.height + 'px)' : 'translateY(0px)') })); if (display == 'none') { $(where.box).find('#w2ui-message'+ msgCount).show().html(options.html); options.box = $(where.box).find('#w2ui-message'+ msgCount); // before event edata = options.trigger({ phase: 'before', type: 'open', target: 'self' }); if (edata.isCancelled === true) { head.css('z-index', head.data('old-z-index')); $(where.box).find('#w2ui-message'+ msgCount).remove(); return; } // timer needs to animation setTimeout(function () { $(where.box).find('#w2ui-message'+ msgCount).css(w2utils.cssPrefix({ 'transform': (display == 'none' ? 'translateY(0px)' : 'translateY(-' + options.height + 'px)') })); }, 1); // timer for lock if (msgCount === 0 && this.lock) { if (where.param) this.lock(where.param); else this.lock(); } setTimeout(function() { // has to be on top of lock $(where.box).find('#w2ui-message'+ msgCount).css(w2utils.cssPrefix({ 'transition': '0s' })); // event after options.trigger($.extend(edata, { phase: 'after' })); }, 350); } } function closeCB($msg, options) { if (edata == null) { // before event edata = options.trigger({ phase: 'before', type: 'open', target: 'self' }); if (edata.isCancelled === true) { head.css('z-index', head.data('old-z-index')); $(where.box).find('#w2ui-message'+ msgCount).remove(); return; } } var $focus = $msg.data('prev_focus'); $msg.remove(); if ($focus && $focus.length > 0) { $focus.focus(); } else { if (obj && obj.focus) obj.focus(); } head.css('z-index', head.data('old-z-index')); // event after options.trigger($.extend(edata, { phase: 'after' })); } } function getSize (el, type) { var $el = $(el); var bwidth = { left : parseInt($el.css('border-left-width')) || 0, right : parseInt($el.css('border-right-width')) || 0, top : parseInt($el.css('border-top-width')) || 0, bottom : parseInt($el.css('border-bottom-width')) || 0 }; var mwidth = { left : parseInt($el.css('margin-left')) || 0, right : parseInt($el.css('margin-right')) || 0, top : parseInt($el.css('margin-top')) || 0, bottom : parseInt($el.css('margin-bottom')) || 0 }; var pwidth = { left : parseInt($el.css('padding-left')) || 0, right : parseInt($el.css('padding-right')) || 0, top : parseInt($el.css('padding-top')) || 0, bottom : parseInt($el.css('padding-bottom')) || 0 }; switch (type) { case 'top' : return bwidth.top + mwidth.top + pwidth.top; case 'bottom' : return bwidth.bottom + mwidth.bottom + pwidth.bottom; case 'left' : return bwidth.left + mwidth.left + pwidth.left; case 'right' : return bwidth.right + mwidth.right + pwidth.right; case 'width' : return bwidth.left + bwidth.right + mwidth.left + mwidth.right + pwidth.left + pwidth.right + parseInt($el.width()); case 'height' : return bwidth.top + bwidth.bottom + mwidth.top + mwidth.bottom + pwidth.top + pwidth.bottom + parseInt($el.height()); case '+width' : return bwidth.left + bwidth.right + mwidth.left + mwidth.right + pwidth.left + pwidth.right; case '+height' : return bwidth.top + bwidth.bottom + mwidth.top + mwidth.bottom + pwidth.top + pwidth.bottom; } return 0; } function getStrWidth (str, styles) { var w, html = '
'+ encodeTags(str) + '
'; $('body').append(html); w = $('#_tmp_width').width(); $('#_tmp_width').remove(); return w; } function lang (phrase) { var translation = this.settings.phrases[phrase]; if (translation == null) return phrase; else return translation; } function locale (locale) { if (!locale) locale = 'en-us'; // if the locale is an object, not a string, than we assume it's a if(typeof locale !== "string" ) { w2utils.settings = $.extend(true, w2utils.settings, locale); return; } if (locale.length === 5) locale = 'locale/'+ locale +'.json'; // clear phrases from language before w2utils.settings.phrases = {}; // load from the file $.ajax({ url : locale, type : "GET", dataType : "JSON", async : false, success : function (data, status, xhr) { w2utils.settings = $.extend(true, w2utils.settings, data); }, error : function (xhr, status, msg) { console.log('ERROR: Cannot load locale '+ locale); } }); } function scrollBarSize () { if (tmp.scrollBarSize) return tmp.scrollBarSize; var html = '
'+ '
1
'+ '
'; $('body').append(html); tmp.scrollBarSize = 100 - $('#_scrollbar_width > div').width(); $('#_scrollbar_width').remove(); if (String(navigator.userAgent).indexOf('MSIE') >= 0) tmp.scrollBarSize = tmp.scrollBarSize / 2; // need this for IE9+ return tmp.scrollBarSize; } function checkName (params, component) { // was w2checkNameParam if (!params || params.name == null) { console.log('ERROR: The parameter "name" is required but not supplied in $().'+ component +'().'); return false; } if (w2ui[params.name] != null) { console.log('ERROR: The parameter "name" is not unique. There are other objects already created with the same name (obj: '+ params.name +').'); return false; } if (!w2utils.isAlphaNumeric(params.name)) { console.log('ERROR: The parameter "name" has to be alpha-numeric (a-z, 0-9, dash and underscore). '); return false; } return true; } function checkUniqueId (id, items, itemsDecription, objName) { // was w2checkUniqueId if (!$.isArray(items)) items = [items]; for (var i = 0; i < items.length; i++) { if (items[i].id === id) { console.log('ERROR: The parameter "id='+ id +'" is not unique within the current '+ itemsDecription +'. (obj: '+ objName +')'); return false; } } return true; } function parseRoute(route) { var keys = []; var path = route .replace(/\/\(/g, '(?:/') .replace(/\+/g, '__plus__') .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g, function(_, slash, format, key, capture, optional) { keys.push({ name: key, optional: !! optional }); slash = slash || ''; return '' + (optional ? '' : slash) + '(?:' + (optional ? slash : '') + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')' + (optional || ''); }) .replace(/([\/.])/g, '\\$1') .replace(/__plus__/g, '(.+)') .replace(/\*/g, '(.*)'); return { path : new RegExp('^' + path + '$', 'i'), keys : keys }; } function cssPrefix(field, value, returnString) { var css = {}; var newCSS = {}; var ret = ''; if (!$.isPlainObject(field)) { css[field] = value; } else { css = field; if (value === true) returnString = true; } for (var c in css) { newCSS[c] = css[c]; newCSS['-webkit-'+c] = css[c]; newCSS['-moz-'+c] = css[c].replace('-webkit-', '-moz-'); newCSS['-ms-'+c] = css[c].replace('-webkit-', '-ms-'); newCSS['-o-'+c] = css[c].replace('-webkit-', '-o-'); } if (returnString === true) { for (var c in newCSS) { ret += c + ': ' + newCSS[c] + '; '; } } else { ret = newCSS; } return ret; } function getCursorPosition(input) { if (input == null) return null; var caretOffset = 0; var doc = input.ownerDocument || input.document; var win = doc.defaultView || doc.parentWindow; var sel; if (input.tagName && input.tagName.toUpperCase() == 'INPUT' && input.selectionStart) { // standards browser caretOffset = input.selectionStart; } else { if (win.getSelection) { sel = win.getSelection(); if (sel.rangeCount > 0) { var range = sel.getRangeAt(0); var preCaretRange = range.cloneRange(); preCaretRange.selectNodeContents(input); preCaretRange.setEnd(range.endContainer, range.endOffset); caretOffset = preCaretRange.toString().length; } } else if ( (sel = doc.selection) && sel.type != "Control") { var textRange = sel.createRange(); var preCaretTextRange = doc.body.createTextRange(); preCaretTextRange.moveToElementText(input); preCaretTextRange.setEndPoint("EndToEnd", textRange); caretOffset = preCaretTextRange.text.length; } } return caretOffset; } function setCursorPosition(input, pos, posEnd) { var range = document.createRange(); var el, sel = window.getSelection(); if (input == null) return; for (var i = 0; i < input.childNodes.length; i++) { var tmp = $(input.childNodes[i]).text(); if (input.childNodes[i].tagName) { tmp = $(input.childNodes[i]).html(); tmp = tmp.replace(/</g, '<') .replace(/>/g, '>') .replace(/&/g, '&') .replace(/"/g, '"') .replace(/ /g, ' '); } if (pos <= tmp.length) { el = input.childNodes[i]; if (el.childNodes && el.childNodes.length > 0) el = el.childNodes[0]; if (el.childNodes && el.childNodes.length > 0) el = el.childNodes[0]; break; } else { pos -= tmp.length; } } if (el == null) return; if (pos > el.length) pos = el.length; range.setStart(el, pos); if (posEnd) { range.setEnd(el, posEnd); } else { range.collapse(true); } sel.removeAllRanges(); sel.addRange(range); } function testLocalStorage() { // test if localStorage is available, see issue #1282 // original code: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/storage/localstorage.js var str = 'w2ui_test'; try { localStorage.setItem(str, str); localStorage.removeItem(str); return true; } catch (e) { return false; } } })(jQuery); /*********************************************************** * Formatters object * --- Primariy used in grid * *********************************************************/ w2utils.formatters = { 'number': function (value, params) { if (parseInt(params) > 20) params = 20; if (parseInt(params) < 0) params = 0; if (value == null || value === '') return ''; return w2utils.formatNumber(parseFloat(value), params, true); }, 'float': function (value, params) { return w2utils.formatters['number'](value, params); }, 'int': function (value, params) { return w2utils.formatters['number'](value, 0); }, 'money': function (value, params) { if (value == null || value === '') return ''; var data = w2utils.formatNumber(Number(value), w2utils.settings.currencyPrecision || 2); return (w2utils.settings.currencyPrefix || '') + data + (w2utils.settings.currencySuffix || ''); }, 'currency': function (value, params) { return w2utils.formatters['money'](value, params); }, 'percent': function (value, params) { if (value == null || value === '') return ''; return w2utils.formatNumber(value, params || 1) + '%'; }, 'size': function (value, params) { if (value == null || value === '') return ''; return w2utils.formatSize(parseInt(value)); }, 'date': function (value, params) { if (params === '') params = w2utils.settings.dateFormat; if (value == null || value === 0 || value === '') return ''; var dt = w2utils.isDateTime(value, params, true); if (dt === false) dt = w2utils.isDate(value, params, true); return '' + w2utils.formatDate(dt, params) + ''; }, 'datetime': function (value, params) { if (params === '') params = w2utils.settings.datetimeFormat; if (value == null || value === 0 || value === '') return ''; var dt = w2utils.isDateTime(value, params, true); if (dt === false) dt = w2utils.isDate(value, params, true); return '' + w2utils.formatDateTime(dt, params) + ''; }, 'time': function (value, params) { if (params === '') params = w2utils.settings.timeFormat; if (params === 'h12') params = 'hh:mi pm'; if (params === 'h24') params = 'h24:mi'; if (value == null || value === 0 || value === '') return ''; var dt = w2utils.isDateTime(value, params, true); if (dt === false) dt = w2utils.isDate(value, params, true); return '' + w2utils.formatTime(value, params) + ''; }, 'timestamp': function (value, params) { if (params === '') params = w2utils.settings.datetimeFormat; if (value == null || value === 0 || value === '') return ''; var dt = w2utils.isDateTime(value, params, true); if (dt === false) dt = w2utils.isDate(value, params, true); return dt.toString ? dt.toString() : ''; }, 'gmt': function (value, params) { if (params === '') params = w2utils.settings.datetimeFormat; if (value == null || value === 0 || value === '') return ''; var dt = w2utils.isDateTime(value, params, true); if (dt === false) dt = w2utils.isDate(value, params, true); return dt.toUTCString ? dt.toUTCString() : ''; }, 'age': function (value, params) { if (value == null || value === 0 || value === '') return ''; var dt = w2utils.isDateTime(value, null, true); if (dt === false) dt = w2utils.isDate(value, null, true); return '' + w2utils.age(value) + (params ? (' ' + params) : '') + ''; }, 'interval': function (value, params) { if (value == null || value === 0 || value === '') return ''; return w2utils.interval(value) + (params ? (' ' + params) : ''); }, 'toggle': function (value, params) { return (value ? 'Yes' : ''); }, 'password': function (value, params) { var ret = ""; for (var i=0; i < value.length; i++) { ret += "*"; } return ret; } }; /*********************************************************** * Generic Event Object * --- This object is reused across all other * --- widgets in w2ui. * *********************************************************/ w2utils.event = { on: function (edata, handler) { var $ = jQuery; var scope; // allow 'eventName.scope' syntax if (typeof edata == 'string' && edata.indexOf('.') != -1) { var tmp = edata.split('.'); edata = tmp[0]; scope = tmp[1]; } // allow 'eventName:after' syntax if (typeof edata == 'string' && edata.indexOf(':') != -1) { var tmp = edata.split(':'); if (['complete', 'done'].indexOf(edata[1]) != -1) edata[1] = 'after'; edata = { type : tmp[0], execute : tmp[1] }; } if (!$.isPlainObject(edata)) edata = { type: edata, scope: scope }; edata = $.extend({ type: null, execute: 'before', target: null, onComplete: null }, edata); // errors if (!edata.type) { console.log('ERROR: You must specify event type when calling .on() method of '+ this.name); return; } if (!handler) { console.log('ERROR: You must specify event handler function when calling .on() method of '+ this.name); return; } if (!$.isArray(this.handlers)) this.handlers = []; // console.log('add', edata); this.handlers.push({ edata: edata, handler: handler }); }, off: function (edata, handler) { var $ = jQuery; var scope; // allow 'eventName.scope' syntax if (typeof edata == 'string' && edata.indexOf('.') != -1) { var tmp = edata.split('.'); edata = tmp[0]; scope = tmp[1]; } // allow 'eventName:after' syntax if (typeof edata == 'string' && edata.indexOf(':') != -1) { var tmp = edata.split(':'); if (['complete', 'done'].indexOf(edata[1]) != -1) edata[1] = 'after'; edata = { type : tmp[0], execute : tmp[1] } } if (!$.isPlainObject(edata)) edata = { type: edata }; edata = $.extend({}, { type: null, execute: 'before', target: null, onComplete: null }, edata); // errors if (!edata.type && !scope) { console.log('ERROR: You must specify event type when calling .off() method of '+ this.name); return; } if (!handler) { handler = null; } // remove handlers var newHandlers = []; for (var h = 0, len = this.handlers.length; h < len; h++) { var t = this.handlers[h]; if ((t.edata.type === edata.type || edata.type === '*' || (t.edata.scope != null && edata.type == '')) && (t.edata.target === edata.target || edata.target == null) && (t.edata.execute === edata.execute || edata.execute == null) && (t.handler === handler || handler == null || (scope != null && t.edata.scope == scope))) { // match } else { newHandlers.push(t); } } this.handlers = newHandlers; }, trigger: function (edata) { var $ = jQuery; var edata = $.extend({ type: null, phase: 'before', target: null, doneHandlers: [] }, edata, { isStopped : false, isCancelled : false, done : function (handler) { this.doneHandlers.push(handler); }, preventDefault : function () { this.isCancelled = true; }, stopPropagation : function () { this.isStopped = true; } }); if (edata.phase === 'before') edata.onComplete = null; var args, fun, tmp; if (edata.target == null) edata.target = null; if (!$.isArray(this.handlers)) this.handlers = []; // process events in REVERSE order for (var h = this.handlers.length-1; h >= 0; h--) { var item = this.handlers[h]; if ((item.edata.type === edata.type || item.edata.type === '*') && (item.edata.target === edata.target || item.edata.target == null) && (item.edata.execute === edata.phase || item.edata.execute === '*' || item.edata.phase === '*')) { edata = $.extend({}, item.edata, edata); // check handler arguments args = []; tmp = new RegExp(/\((.*?)\)/).exec(item.handler); if (tmp) args = tmp[1].split(/\s*,\s*/); if (args.length === 2) { item.handler.call(this, edata.target, edata); // old way for back compatibility } else { item.handler.call(this, edata); // new way } if (edata.isStopped === true || edata.stop === true) return edata; // back compatibility edata.stop === true } } // main object events var funName = 'on' + edata.type.substr(0,1).toUpperCase() + edata.type.substr(1); if (edata.phase === 'before' && typeof this[funName] === 'function') { fun = this[funName]; // check handler arguments args = []; tmp = new RegExp(/\((.*?)\)/).exec(fun); if (tmp) args = tmp[1].split(/\s*,\s*/); if (args.length === 2) { fun.call(this, edata.target, edata); // old way for back compatibility } else { fun.call(this, edata); // new way } if (edata.isStopped === true || edata.stop === true) return edata; // back compatibility edata.stop === true } // item object events if (edata.object != null && edata.phase === 'before' && typeof edata.object[funName] === 'function') { fun = edata.object[funName]; // check handler arguments args = []; tmp = new RegExp(/\((.*?)\)/).exec(fun); if (tmp) args = tmp[1].split(/\s*,\s*/); if (args.length === 2) { fun.call(this, edata.target, edata); // old way for back compatibility } else { fun.call(this, edata); // new way } if (edata.isStopped === true || edata.stop === true) return edata; } // execute onComplete if (edata.phase === 'after') { if (typeof edata.onComplete === 'function') edata.onComplete.call(this, edata); for (var i = 0; i < edata.doneHandlers.length; i++) { if (typeof edata.doneHandlers[i] == 'function') { edata.doneHandlers[i].call(this, edata); } } } return edata; } }; /*********************************************************** * Commonly used plugins * --- used primarily in grid and form * *********************************************************/ (function ($) { $.fn.w2render = function (name) { if ($(this).length > 0) { if (typeof name === 'string' && w2ui[name]) w2ui[name].render($(this)[0]); if (typeof name === 'object') name.render($(this)[0]); } }; $.fn.w2destroy = function (name) { if (!name && this.length > 0) name = this.attr('name'); if (typeof name === 'string' && w2ui[name]) w2ui[name].destroy(); if (typeof name === 'object') name.destroy(); }; $.fn.w2marker = function () { var str = Array.prototype.slice.call(arguments, 0); if (Array.isArray(str[0])) str = str[0]; if (str.length === 0 || !str[0]) { // remove marker return $(this).each(clearMarkedText); } else { // add marker return $(this).each(function (index, el) { clearMarkedText(index, el); for (var s = 0; s < str.length; s++) { var tmp = str[s]; if (typeof tmp !== 'string') tmp = String(tmp); // escape regex special chars tmp = tmp.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&").replace(/&/g, '&').replace(//g, '<'); var regex = new RegExp(tmp + '(?!([^<]+)?>)', "gi"); // only outside tags el.innerHTML = el.innerHTML.replace(regex, replaceValue); } function replaceValue(matched) { // mark new return '' + matched + ''; } }); } function clearMarkedText(index, el) { while (el.innerHTML.indexOf('') != -1) { el.innerHTML = el.innerHTML.replace(/\((.|\n|\r)*)\<\/span\>/ig, '$1'); // unmark } } }; // -- w2tag - there can be multiple on screen at a time $.fn.w2tag = function (text, options) { // only one argument if (arguments.length == 1 && typeof text == 'object') { options = text; if (options.html != null) text = options.html; } // default options options = $.extend({ id : null, // id for the tag, otherwise input id is used html : text, // or html position : 'right|top', // can be left, right, top, bottom align : 'none', // can be none, left, right (only works for position: top | bottom) left : 0, // delta for left coordinate top : 0, // delta for top coordinate style : '', // adition style for the tag css : {}, // add css for input when tag is shown className : '', // add class bubble inputClass : '', // add class for input when tag is shown onShow : null, // callBack when shown onHide : null, // callBack when hidden hideOnKeyPress : true, // hide tag if key pressed hideOnBlur : false, // hide tag on blur hideOnClick : false // hide tag on document click }, options); if (options.name != null && options.id == null) options.id = options.name; // for backward compatibility if (options['class'] !== '' && options.inputClass === '') options.inputClass = options['class']; // remove all tags if ($(this).length === 0) { $('.w2ui-tag').each(function (index, el) { var opt = $(el).data('options'); if (opt == null) opt = {}; $($(el).data('taged-el')) .removeClass(opt.inputClass) .removeData('w2tag') .removeData('checkIfMoved'); clearInterval($(el).data('timer')); $(el).remove(); }); return; } return $(this).each(function (index, el) { // show or hide tag var origID = (options.id ? options.id : el.id); var tagID = w2utils.escapeId(origID); var $tags = $('#w2ui-tag-'+tagID); if (text === '' || text == null) { // remove element $tags.css('opacity', 0); clearInterval($tags.data('timer')); $tags.remove(); return; } else if ($tags.length !== 0) { // if already present options = $.extend($tags.data('options'), options); $tags.data('options', options); $tags.find('.w2ui-tag-body') .attr('style', options.style) .addClass(options.className) .html(options.html); checkIfMoved(true); } else { var originalCSS = ''; if ($(el).length > 0) originalCSS = $(el)[0].style.cssText; // insert $('body').append( ''); $tags = $('#w2ui-tag-'+tagID); $(el).data('w2tag', $tags.get(0)).data('checkIfMoved', checkIfMoved); } // need time out to allow tag to be rendered setTimeout(function () { $tags.css('display', 'block'); if (!$(el).offset()) return; var pos = checkIfMoved(true); if (pos == null) return; $tags.css({ opacity : '1', left : pos.left + 'px', top : pos.top + 'px' }) .data('options', options) .data('taged-el', el) .data('position', pos.left + 'x' + pos.top) .data('timer', setTimeout(checkIfMoved, 100)) .find('.w2ui-tag-body').addClass(pos['posClass']); $(el).css(options.css) .off('.w2tag') .addClass(options.inputClass); if (options.hideOnKeyPress) { $(el).on('keypress.w2tag', hideTag); } if (options.hideOnBlur) { $(el).on('blur.w2tag', hideTag); } if (options.hideOnClick) { $(document).on('click.w2tag', hideTag) } if (typeof options.onShow === 'function') options.onShow(); }, 1); // bind event to hide it function hideTag() { $tags = $('#w2ui-tag-'+tagID); if ($tags.length <= 0) return; clearInterval($tags.data('timer')); $tags.remove(); $(document).off('.w2tag'); $(el).off('.w2tag', hideTag) .removeClass(options.inputClass) .removeData('w2tag') .removeData('checkIfMoved'); if ($(el).length > 0) $(el)[0].style.cssText = originalCSS; if (typeof options.onHide === 'function') options.onHide(); } function checkIfMoved(checkOnly, instant) { // monitor if destroyed var offset = $(el).offset(); if ($(el).length === 0 || (offset.left === 0 && offset.top === 0) || $tags.find('.w2ui-tag-body').length === 0) { clearInterval($tags.data('timer')); hideTag(); return; } if (!instant) setTimeout(checkIfMoved, 200); // monitor if moved var posClass = 'w2ui-tag-right'; var posLeft = parseInt(offset.left + el.offsetWidth + (options.left ? options.left : 0)); var posTop = parseInt(offset.top + (options.top ? options.top : 0)); var tagBody = $tags.find('.w2ui-tag-body'); var width = tagBody[0].offsetWidth; var height = tagBody[0].offsetHeight; if (typeof options.position == 'string' && options.position.indexOf('|') != -1) { options.position = options.position.split('|'); } if (options.position == 'top') { posClass = 'w2ui-tag-top'; posLeft = parseInt(offset.left + (options.left ? options.left : 0)) - 14; posTop = parseInt(offset.top + (options.top ? options.top : 0)) - height - 10; } else if (options.position == 'bottom') { posClass = 'w2ui-tag-bottom'; posLeft = parseInt(offset.left + (options.left ? options.left : 0)) - 14; posTop = parseInt(offset.top + el.offsetHeight + (options.top ? options.top : 0)) + 10; } else if (options.position == 'left') { posClass = 'w2ui-tag-left'; posLeft = parseInt(offset.left + (options.left ? options.left : 0)) - width - 20; posTop = parseInt(offset.top + (options.top ? options.top : 0)); } else if (Array.isArray(options.position)) { // try to fit the tag on screen in the order defined in the array var maxWidth = window.innerWidth; var maxHeight = window.innerHeight for (var i=0; i= 0) break; } else if (pos == 'top') { posClass = 'w2ui-tag-top'; posLeft = parseInt(offset.left + (options.left ? options.left : 0)) - 14; posTop = parseInt(offset.top + (options.top ? options.top : 0)) - height - 10; if(posLeft+width <= maxWidth && posTop >= 0) break; } else if (pos == 'bottom') { posClass = 'w2ui-tag-bottom'; posLeft = parseInt(offset.left + (options.left ? options.left : 0)) - 14; posTop = parseInt(offset.top + el.offsetHeight + (options.top ? options.top : 0)) + 10; if (posLeft+width <= maxWidth && posTop+height <= maxHeight) break; } } if (tagBody.data('posClass') !== posClass) { tagBody.removeClass('w2ui-tag-right w2ui-tag-left w2ui-tag-top w2ui-tag-bottom') .addClass(posClass) .data('posClass', posClass); } } if ($tags.data('position') !== posLeft + 'x' + posTop && checkOnly !== true) { $tags.css(w2utils.cssPrefix({ 'transition': (instant ? '0s' : '.2s') })).css({ left: posLeft + 'px', top : posTop + 'px' }).data('position', posLeft + 'x' + posTop); } return { left: posLeft, top: posTop, posClass: posClass }; } }); }; // w2overlay - appears under the element, there can be only one at a time $.fn.w2overlay = function (html, options) { var obj = this; var name = ''; var defaults = { name : null, // it not null, then allows multiple concurrent overlays html : '', // html text to display align : 'none', // can be none, left, right, both left : 0, // offset left top : 0, // offset top tipLeft : 30, // tip offset left noTip : false, // if true - no tip will be displayed selectable : false, width : 0, // fixed width height : 0, // fixed height maxWidth : null, // max width if any maxHeight : null, // max height if any contextMenu : false, // if true, it will be opened at mouse position pageX : null, pageY : null, originalEvent : null, style : '', // additional style for main div 'class' : '', // additional class name for main div overlayStyle: '', onShow : null, // event on show onHide : null, // event on hide openAbove : false, // show above control tmp : {} }; if (arguments.length == 1) { if (typeof html == 'object') { options = html; } else { options = { html: html }; } } if (arguments.length == 2) options.html = html; if (!$.isPlainObject(options)) options = {}; options = $.extend({}, defaults, options); if (options.name) name = '-' + options.name; // hide var tmp_hide; if (this.length === 0 || options.html === '' || options.html == null) { if ($('#w2ui-overlay'+ name).length > 0) { tmp_hide = $('#w2ui-overlay'+ name)[0].hide; if (typeof tmp_hide === 'function') tmp_hide(); } else { $('#w2ui-overlay'+ name).remove(); } return $(this); } // hide previous if any if ($('#w2ui-overlay'+ name).length > 0) { tmp_hide = $('#w2ui-overlay'+ name)[0].hide; $(document).off('.w2overlayHide'); if (typeof tmp_hide === 'function') tmp_hide(); } if (obj.length > 0 && (obj[0].tagName == null || obj[0].tagName.toUpperCase() == 'BODY')) options.contextMenu = true; if (options.contextMenu && options.originalEvent) { options.pageX = options.originalEvent.pageX; options.pageY = options.originalEvent.pageY; } if (options.contextMenu && (options.pageX == null || options.pageY == null)) { console.log('ERROR: to display menu at mouse location, pass options.pageX and options.pageY.'); } // append $('body').append( '' ); // init var div1 = $('#w2ui-overlay'+ name); var div2 = div1.find(' > div'); div2.html(options.html); // pick bg color of first div var bc = div2.css('background-color'); if (bc != null && bc !== 'rgba(0, 0, 0, 0)' && bc !== 'transparent') div1.css({ 'background-color': bc, 'border-color': bc }); var offset = $(obj).offset() || {}; div1.data('element', obj.length > 0 ? obj[0] : null) .data('options', options) .data('position', offset.left + 'x' + offset.top) .fadeIn('fast') .on('click', function (event) { // if there is label for input, it will produce 2 click events if (event.target.tagName.toUpperCase() == 'LABEL') event.stopPropagation(); }) .on('mousedown', function (event) { $('#w2ui-overlay'+ name).data('keepOpen', true); if (['INPUT', 'TEXTAREA', 'SELECT'].indexOf(event.target.tagName.toUpperCase()) == -1 && !options.selectable) { event.preventDefault(); } }); div1[0].hide = hide; div1[0].resize = resize; // need time to display setTimeout(function () { resize(); $(document).off('.w2overlayHide').on('click.w2overlayHide', hide); if (typeof options.onShow === 'function') options.onShow(); }, 10); monitor(); return $(this); // monitor position function monitor() { var tmp = $('#w2ui-overlay'+ name); if (tmp.data('element') !== obj[0]) return; // it if it different overlay if (tmp.length === 0) return; var offset = $(obj).offset() || {}; var pos = offset.left + 'x' + offset.top; if (tmp.data('position') !== pos) { hide(); } else { setTimeout(monitor, 250); } } // click anywhere else hides the drop down function hide(event) { if (event && event.button !== 0) return; // only for left click button var div1 = $('#w2ui-overlay'+ name); if (div1.data('keepOpen') === true) { div1.removeData('keepOpen'); return; } var result; if (typeof options.onHide === 'function') result = options.onHide(); if (result === false) return; div1.remove(); $(document).off('click', hide); clearInterval(div1.data('timer')); } function resize () { var div1 = $('#w2ui-overlay'+ name); var div2 = div1.find(' > div'); var menu = $('#w2ui-overlay'+ name +' div.menu'); menu.css('overflow-y', 'hidden'); // if goes over the screen, limit height and width if (div1.length > 0) { div2.height('auto').width('auto'); // width/height var overflowX = false; var overflowY = false; var h = div2.height(); var w = div2.width(); if (options.width && options.width < w) w = options.width; if (w < 30) w = 30; // if content of specific height if (options.tmp.contentHeight) { h = parseInt(options.tmp.contentHeight); if (h > $(".leaflet-container").height()) h = $(".leaflet-container").height(); div2.height(h); setTimeout(function () { var $div = div2.find('div.menu'); if (h > $div.height()) { div2.find('div.menu').css('overflow-y', 'hidden'); } }, 1); setTimeout(function () { var $div = div2.find('div.menu'); if ($div.css('overflow-y') != 'auto') $div.css('overflow-y', 'auto'); }, 10); } if (options.tmp.contentWidth && options.align != 'both') { w = parseInt(options.tmp.contentWidth); div2.width(w); setTimeout(function () { if (w > div2.find('div.menu > table').width()) { div2.find('div.menu > table').css('overflow-x', 'hidden'); } }, 1); setTimeout(function () { div2.find('div.menu > table').css('overflow-x', 'auto'); }, 10); } // adjust position var boxLeft = options.left; var boxWidth = options.width; var tipLeft = options.tipLeft; // alignment switch (options.align) { case 'both': boxLeft = 17; if (options.width === 0) options.width = w2utils.getSize($(obj), 'width'); if (options.maxWidth && options.width > options.maxWidth) options.width = options.maxWidth; break; case 'left': boxLeft = 17; break; case 'right': boxLeft = w2utils.getSize($(obj), 'width') - w + 10; tipLeft = w - 40; break; } if (w === 30 && !boxWidth) boxWidth = 30; else boxWidth = (options.width ? options.width : 'auto'); var tmp = (w - 17) / 2; if (boxWidth != 'auto') tmp = (boxWidth - 17) / 2; if (tmp < 25) { boxLeft = 25 - tmp; tipLeft = Math.floor(tmp); } // Y coord var X, Y, offsetTop; if (options.contextMenu) { // context menu X = options.pageX + 8; Y = options.pageY - 0; offsetTop = options.pageY; } else { var offset = obj.offset() || {}; X = ((offset.left > 25 ? offset.left : 25) + boxLeft); Y = (offset.top + w2utils.getSize(obj, 'height') + options.top + 7); offsetTop = offset.top; } div1.css({ left : X + 'px', top : Y + 'px', 'min-width' : boxWidth, 'min-height': (options.height ? options.height : 'auto') }); // $(window).height() - has a problem in FF20 var offset = div2.offset() || {}; var maxHeight = window.innerHeight + $(document).scrollTop() - offset.top - 7; var maxWidth = window.innerWidth + $(document).scrollLeft() - offset.left - 7; if (options.contextMenu) { // context menu maxHeight = window.innerHeight + $(document).scrollTop() - options.pageY - 15; maxWidth = window.innerWidth + $(document).scrollLeft() - options.pageX; } if ((maxHeight > -50 && maxHeight < 210) || options.openAbove === true) { var tipOffset; // show on top if (options.contextMenu) { // context menu maxHeight = options.pageY - 7; tipOffset = 5; } else { maxHeight = offset.top - $(document).scrollTop() - 7; tipOffset = 24; } if (options.maxHeight && maxHeight > options.maxHeight) maxHeight = options.maxHeight; if (h > maxHeight) { overflowY = true; div2.height(maxHeight).width(w).css({ 'overflow-y': 'auto' }); h = maxHeight; } div1.addClass('bottom-arrow'); div1.css('top', (offsetTop - h - tipOffset + options.top) + 'px'); div1.find('>style').html( '#w2ui-overlay'+ name +':before { margin-left: '+ parseInt(tipLeft) +'px; }'+ '#w2ui-overlay'+ name +':after { margin-left: '+ parseInt(tipLeft) +'px; }' ); } else { // show under if (options.maxHeight && maxHeight > options.maxHeight) maxHeight = options.maxHeight; if (h > maxHeight) { overflowY = true; div2.height(maxHeight).width(w).css({ 'overflow-y': 'auto' }); } div1.addClass('top-arrow'); div1.find('>style').html( '#w2ui-overlay'+ name +':before { margin-left: '+ parseInt(tipLeft) +'px; }'+ '#w2ui-overlay'+ name +':after { margin-left: '+ parseInt(tipLeft) +'px; }' ); } // check width w = div2.width(); maxWidth = window.innerWidth + $(document).scrollLeft() - offset.left - 7; if (options.maxWidth && maxWidth > options.maxWidth) maxWidth = options.maxWidth; if (w > maxWidth && options.align !== 'both') { options.align = 'right'; setTimeout(function () { resize(); }, 1); } // don't show tip if (options.contextMenu || options.noTip) { // context menu div1.find('>style').html( '#w2ui-overlay'+ name +':before { display: none; }'+ '#w2ui-overlay'+ name +':after { display: none; }' ); } // check scroll bar (needed to avoid horizontal scrollbar) if (overflowY && options.align != 'both') div2.width(w + w2utils.scrollBarSize() + 2); } menu.css('overflow-y', 'auto'); } }; $.fn.w2menu = function (menu, options) { /* ITEM STRUCTURE item : { id : null, text : '', style : '', img : '', icon : '', count : '', tooltip : '', hidden : false, checked : null, disabled : false ... } */ // if items is a function if (options && typeof options.items == 'function') { options.items = options.items(); } var defaults = { type : 'normal', // can be normal, radio, check index : null, // current selected items : [], render : null, msgNoItems : 'No items', onSelect : null, tmp : {} }; var obj = this; var name = ''; if (menu === 'refresh') { // if not show - call blur if ($('#w2ui-overlay'+ name).length > 0) { options = $.extend($.fn.w2menuOptions, options); var scrTop = $('#w2ui-overlay'+ name +' div.menu').scrollTop(); $('#w2ui-overlay'+ name +' div.menu').html(getMenuHTML()); $('#w2ui-overlay'+ name +' div.menu').scrollTop(scrTop); mresize(); } else { $(this).w2menu(options); } } else if (menu === 'refresh-index') { var $menu = $('#w2ui-overlay'+ name +' div.menu'); var cur = $menu.find('tr[index='+ options.index +']'); var scrTop = $menu.scrollTop(); $menu.find('tr.w2ui-selected').removeClass('w2ui-selected'); // clear all cur.addClass('w2ui-selected'); // select current // scroll into view if (cur.length > 0) { var top = cur[0].offsetTop - 5; // 5 is margin top var height = $menu.height(); $menu.scrollTop(scrTop); if (top < scrTop || top + cur.height() > scrTop + height) { $menu.animate({ 'scrollTop': top - (height - cur.height() * 2) / 2 }, 200, 'linear'); } } mresize(); } else { if (arguments.length === 1) options = menu; else options.items = menu; if (typeof options !== 'object') options = {}; options = $.extend({}, defaults, options); $.fn.w2menuOptions = options; if (options.name) name = '-' + options.name; if (typeof options.select === 'function' && typeof options.onSelect !== 'function') options.onSelect = options.select; if (typeof options.onRender === 'function' && typeof options.render !== 'function') options.render = options.onRender; // since only one overlay can exist at a time $.fn.w2menuClick = function (event, index) { var keepOpen = options.keepOpen || false; if (['radio', 'check'].indexOf(options.type) != -1) { if (event.shiftKey || event.metaKey || event.ctrlKey) keepOpen = true; } if (typeof options.onSelect === 'function') { // need time so that menu first hides setTimeout(function () { options.onSelect({ index: index, item: options.items[index], keepOpen: keepOpen, originalEvent: event }); }, 10); } // do not uncomment (or enum search type is not working in grid) // setTimeout(function () { $(document).click(); }, 50); // -- hide var div = $('#w2ui-overlay'+ name); div.removeData('keepOpen'); if (typeof div[0].hide === 'function' && !keepOpen) { div[0].hide(); } }; $.fn.w2menuDown = function (event, index) { if (event.type === 'keydown') { if (event.code === 'ArrowDown') document.activeElement.nextElementSibling.focus(); else if (event.code === 'ArrowUp') document.activeElement.previousElementSibling.focus(); if (event.code === 'Enter' || event.code === 'Space') { document.activeElement.click(); return; } } var $el = $(event.target).parents('tr'); var tmp = $el.find('.w2ui-icon'); if ((options.type == 'check') || (options.type == 'radio')) { var item = options.items[index]; item.checked = !item.checked; if (item.checked) { if (options.type == 'radio') { tmp.parents('table').find('.w2ui-icon') .removeClass('w2ui-icon-check') .addClass('w2ui-icon-empty'); } tmp.removeClass('w2ui-icon-empty').addClass('w2ui-icon-check'); } else if (options.type == 'check') { tmp.removeClass('w2ui-icon-check').addClass('w2ui-icon-empty'); } } // highlight record $el.parent().find('tr').removeClass('w2ui-selected'); $el.addClass('w2ui-selected'); }; var html = ''; if (options.search) { html += '
'+ ' '+ ' '+ '
'; options.style += ';background-color: #ECECEC'; options.index = 0; for (var i = 0; i < options.items.length; i++) options.items[i].hidden = false; } html += ''; var ret = $(this).w2overlay(html, options); setTimeout(function () { $('#w2ui-overlay'+ name +' #menu-search') .on('keyup', change) .on('keydown', function (event) { // cancel tab key if (event.keyCode === 9) { event.stopPropagation(); event.preventDefault(); } }); if (options.search) { if (['text', 'password'].indexOf($(obj)[0].type) != -1 || $(obj)[0].tagName.toUpperCase() == 'TEXTAREA') return; $('#w2ui-overlay'+ name +' #menu-search').focus(); } mresize(); }, 200); mresize(); return ret; } return; function mresize() { setTimeout(function () { // show selected $('#w2ui-overlay'+ name +' tr.w2ui-selected').removeClass('w2ui-selected'); var cur = $('#w2ui-overlay'+ name +' tr[index='+ options.index +']'); var scrTop = $('#w2ui-overlay'+ name +' div.menu').scrollTop(); cur.addClass('w2ui-selected'); if (options.tmp) options.tmp.contentHeight = $('#w2ui-overlay'+ name +' table').height() + (options.search ? 50 : 10); if (options.tmp) options.tmp.contentWidth = $('#w2ui-overlay'+ name +' table').width(); if ($('#w2ui-overlay'+ name).length > 0) $('#w2ui-overlay'+ name)[0].resize(); // scroll into view if (cur.length > 0) { var top = cur[0].offsetTop - 5; // 5 is margin top var el = $('#w2ui-overlay'+ name +' div.menu'); var height = el.height(); $('#w2ui-overlay'+ name +' div.menu').scrollTop(scrTop); if (top < scrTop || top + cur.height() > scrTop + height) { $('#w2ui-overlay'+ name +' div.menu').animate({ 'scrollTop': top - (height - cur.height() * 2) / 2 }, 200, 'linear'); } } }, 1); } function change(event) { var search = this.value; var key = event.keyCode; var cancel = false; switch (key) { case 13: // enter $('#w2ui-overlay'+ name).remove(); $.fn.w2menuClick(event, options.index); break; case 9: // tab case 27: // escape $('#w2ui-overlay'+ name).remove(); $.fn.w2menuClick(event, -1); break; case 38: // up options.index = w2utils.isInt(options.index) ? parseInt(options.index) : 0; options.index--; while (options.index > 0 && options.items[options.index].hidden) options.index--; if (options.index === 0 && options.items[options.index].hidden) { while (options.items[options.index] && options.items[options.index].hidden) options.index++; } if (options.index < 0) options.index = 0; cancel = true; break; case 40: // down options.index = w2utils.isInt(options.index) ? parseInt(options.index) : 0; options.index++; while (options.index < options.items.length-1 && options.items[options.index].hidden) options.index++; if (options.index === options.items.length-1 && options.items[options.index].hidden) { while (options.items[options.index] && options.items[options.index].hidden) options.index--; } if (options.index >= options.items.length) options.index = options.items.length - 1; cancel = true; break; } // filter if (!cancel) { var shown = 0; for (var i = 0; i < options.items.length; i++) { var item = options.items[i]; var prefix = ''; var suffix = ''; if (['is', 'begins with'].indexOf(options.match) !== -1) prefix = '^'; if (['is', 'ends with'].indexOf(options.match) !== -1) suffix = '$'; try { var re = new RegExp(prefix + search + suffix, 'i'); if (re.test(item.text) || item.text === '...') item.hidden = false; else item.hidden = true; } catch (e) {} // do not show selected items if (obj.type === 'enum' && $.inArray(item.id, ids) !== -1) item.hidden = true; if (item.hidden !== true) shown++; } options.index = 0; while (options.index < options.items.length-1 && options.items[options.index].hidden) options.index++; if (shown <= 0) options.index = -1; } $(obj).w2menu('refresh', options); mresize(); } function getMenuHTML() { if (options.spinner) { return '
'+ '
'+ '
'+ w2utils.lang('Loading...') +'
'+ '
'; } var count = 0; var menu_html = ''; var img = null, icon = null; for (var f = 0; f < options.items.length; f++) { var mitem = options.items[f]; if (typeof mitem === 'string') { mitem = { id: mitem, text: mitem }; } else { if (mitem.text != null && mitem.id == null) mitem.id = mitem.text; if (mitem.text == null && mitem.id != null) mitem.text = mitem.id; if (mitem.caption != null) mitem.text = mitem.caption; img = mitem.img; icon = mitem.icon; if (img == null) img = null; // img might be undefined if (icon == null) icon = null; // icon might be undefined } if (['radio', 'check'].indexOf(options.type) != -1) { if (mitem.checked === true) icon = 'w2ui-icon-check'; else icon = 'w2ui-icon-empty'; } if (mitem.hidden !== true) { var imgd = ''; var txt = mitem.text; if (typeof options.render === 'function') txt = options.render(mitem, options); if (img) imgd = ''; if (icon) imgd = ''; // render only if non-empty if (txt != null && txt !== '' && !(/^-+$/.test(txt))) { var bg = (count % 2 === 0 ? 'w2ui-item-even' : 'w2ui-item-odd'); if (options.altRows !== true) bg = ''; var colspan = 1; if (imgd === '') colspan++; if (mitem.count == null && mitem.hotkey == null) colspan++; if (mitem.tooltip == null && mitem.hint != null) mitem.tooltip = mitem.hint; // for backward compatibility menu_html += ''+ imgd + ' '+ ' ' + ''; count++; } else { // horizontal line menu_html += ''; } } options.items[f] = mitem; } if (count === 0) { menu_html += ''; } menu_html += "
'+ options.msgNoItems +'
"; return menu_html; } }; var toW2Palette = function (corePalette) { var pal = []; if (!corePalette) return pal; for (var i = 0; i < corePalette.length; i++) { var row = []; for (var j = 0; j < corePalette[i].length; j++) { row.push(corePalette[i][j].Value); } pal.push(row); } return pal; }; var generatePalette = function (paletteName, options) { $.fn.w2colorPalette = toW2Palette(window.app.colorPalettes[paletteName].colors); var customColorRow = localStorage.customColor; var recentRow = localStorage.recentColor; if (typeof customColorRow !== 'undefined') { $.fn.w2colorPalette.push(JSON.parse(customColorRow)); } else { $.fn.w2colorPalette.push(['F2F2F2', 'F2F2F2', 'F2F2F2', 'F2F2F2', 'F2F2F2']); // custom colors (up to 4) } if (typeof recentRow !== 'undefined') { $.fn.w2colorPalette.push(JSON.parse(recentRow)); } else { $.fn.w2colorPalette.push(['F2F2F2', 'F2F2F2', 'F2F2F2', 'F2F2F2', 'F2F2F2', 'F2F2F2', 'F2F2F2', 'F2F2F2']); // recent colors (up to 8) } var pal = $.fn.w2colorPalette; if (typeof options == 'string') options = { color: options, transparent: true }; return pal; }; $.fn.w2color = function (options, callBack) { var el = $(this)[0]; var index = [-1, -1]; function getCurrentPaletteName() { return (localStorage && localStorage.colorPalette && window.app.colorPalettes[localStorage.colorPalette]) ? localStorage.colorPalette : 'StandardColors'; }; function bindEvents(pal) { $('#w2ui-overlay .color') .off('.w2color') .on('mousedown.w2color keydown.w2color', function (event) { if (event.type === 'keydown') { if (event.code !== 'Enter' && event.code !== 'Space') return; // Handle keydown but only for specific keys. } var color = $(event.originalEvent.target).attr('name'); index = $(event.originalEvent.target).attr('index').split(':'); var theme = $(event.originalEvent.target).attr('theme'); $(el).data('_color', color); $(el).data('_theme', theme); var recentRow = $.fn.w2colorPalette[pal.length - 1]; if (recentRow.indexOf(color) !== -1) { recentRow.splice(recentRow.indexOf(color), 1); } recentRow.unshift(color); localStorage.setItem('recentColor', JSON.stringify(recentRow)); }) .on('mouseup.w2color keyup.w2color', function (event) { setTimeout(function () { if (event.type === 'keyup') { if (event.code !== 'Enter' && event.code !== 'Space') return; // Handle keydown but only for specific keys. } if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay').removeData('keepOpen')[0].hide(); if (event.type === 'keyup') { if (event.code === 'Enter' || event.code === 'Space') app.map.focus(); // Focus back to document. } }, 10); }); $('#w2ui-overlay input') .off('.w2color') .on('mousedown.w2color', function (event) { $('#w2ui-overlay').data('keepOpen', true); setTimeout(function () { $('#w2ui-overlay').data('keepOpen', true); }, 10); event.stopPropagation(); }) .on('keyup.w2color', function (event) { if (this.value !== '' && this.value[0] !== '#') this.value = '#' + this.value; }) .on('change.w2color', function (event) { var tmp = this.value; if (tmp.substr(0, 1) == '#') tmp = tmp.substr(1); if (tmp.length != 6) { $(this).w2tag('Invalid color.'); return; } var customColorRow = $.fn.w2colorPalette[pal.length - 2]; if (customColorRow.indexOf(tmp) !== -1) { customColorRow.splice(customColorRow.indexOf(tmp), 1); } customColorRow.unshift(tmp.toUpperCase()); localStorage.setItem('customColor', JSON.stringify(customColorRow)); $(el).w2color(options, callBack); setTimeout(function() { $('#w2ui-overlay input')[0].focus(); }, 100); }) .w2field('hex'); $('#transparent-color-button') .on('mousedown.w2color keydown.w2color', function () { $(el).data('_color', ''); $(el).data('_theme', undefined); }); } var currentPalette = getCurrentPaletteName(); var pal = generatePalette(currentPalette, options); if (options.color) options.color = String(options.color).toUpperCase(); if ($('#w2ui-overlay').length === 0) { $(el).w2overlay(getColorHTML(pal, options), { onHide: function () { var data = $(el).data('_color'); var theme = $(el).data('_theme'); if (typeof callBack == 'function') callBack(data, theme); $(el).removeData('_color'); $(el).removeData('_theme'); } }); } else { // only refresh contents $('#w2ui-overlay .w2ui-color').parent().html(getColorHTML(pal, options)); } bindEvents(pal); var updatePalette = function () { var palette = $('#w2ui-overlay .color-palette-selector select option:selected').get(0).value; localStorage.setItem('colorPalette', palette); var pal = generatePalette(palette, options); $('#w2ui-overlay .w2ui-color').parent().html(getColorHTML(pal, options)); bindEvents(pal); $('#w2ui-overlay .color-palette-selector select') .on('change', updatePalette); }; $('#w2ui-overlay .color-palette-selector select') .on('change', updatePalette); el.nav = function (direction) { switch (direction) { case 'up': index[0]--; break; case 'down': index[0]++; break; case 'right': index[1]++; break; case 'left': index[1]--; break; } if (index[0] < 0) index[0] = 0; if (index[0] > pal.length - 2) index[0] = pal.length - 2; if (index[1] < 0) index[1] = 0; if (index[1] > pal[0].length - 1) index[1] = pal[0].length - 1; color = pal[index[0]][index[1]]; $(el).data('_color', color); return color; }; function getColorHTML(pal, options) { var html = ''; var currentPalette = getCurrentPaletteName(); var hasTransparent = options.transparent; var buttonText = hasTransparent ? _('No fill') : _('Automatic'); html += ''; html += '
' + '
'; var detailedPalette = window.app.colorPalettes[currentPalette].colors html += '
'+ // prevent default is needed otherwiser selection gets unselected ''; for (var i = 0; i < pal.length - 2; i++) { html += ''; for (var j = 0; j < pal[i].length; j++) { var themeData = detailedPalette[i][j].Data ? JSON.stringify(detailedPalette[i][j].Data) : undefined; html += ''; if (options.color == pal[i][j]) index = [i, j]; } html += ''; if (i < 2) html += ''; } var tmp1 = pal[pal.length - 2]; var tmp2 = pal[pal.length - 1]; html += ''+ ''+ ' '+ ' '+ ' '+ ' '+ ' '+ ''+ '' + '' + ''+ ' '+ ' '+ ' '+ ' '+ ' '+ ' '+ ' '+ ' '+ ''+ ''; html += '
'+ '
'+ (options.color == pal[i][j] ? '•' : ' ') + '
'+ '
'+ (options.color == tmp1[0] ? '•' : ' ') +'
'+ (options.color == tmp1[1] ? '•' : ' ') +'
'+ (options.color == tmp1[2] ? '•' : ' ') +'
'+ (options.color == tmp1[3] ? '•' : ' ') +'
' + _('Recent') + '
'+ (options.color == tmp2[0] ? '•' : ' ') +'
'+ (options.color == tmp2[1] ? '•' : ' ') +'
'+ (options.color == tmp2[2] ? '•' : ' ') +'
'+ (options.color == tmp2[3] ? '•' : ' ') +'
'+ (options.color == tmp2[4] ? '•' : ' ') +'
'+ (options.color == tmp2[5] ? '•' : ' ') +'
'+ (options.color == tmp2[6] ? '•' : ' ') +'
'+ (options.color == tmp2[7] ? '•' : ' ') +'
'; return html; } }; })(jQuery); /************************************************************************ * Library: Web 2.0 UI for jQuery (using prototypical inheritance) * - Following objects defined * - w2field - various field controls * - $().w2field - jQuery wrapper * - Dependencies: jQuery, w2utils * * == NICE TO HAVE == * - upload (regular files) * - BUG with prefix/postfix and arrows (test in different contexts) * - multiple date selection * - month selection, year selections * - arrows no longer work (for int) * - form to support custom types * - rewrite suffix and prefix positioning with translateY() * - prefix and suffix are slow (100ms or so) * - MultiSelect - Allow Copy/Paste for single and multi values * - add routeData to list/enum * - for type: list -> read value from attr('value') * - ENUM, LIST: should have same as grid (limit, offset, search, sort) * - ENUM, LIST: should support wild chars * - add selection of predefined times (used for appointments) * ************************************************************************/ (function ($) { var w2field = function (options) { // public properties this.el = null; this.helpers = {}; // object or helper elements this.type = options.type || 'text'; this.options = $.extend(true, {}, options); this.onSearch = options.onSearch || null; this.onRequest = options.onRequest || null; this.onLoad = options.onLoad || null; this.onError = options.onError || null; this.onClick = options.onClick || null; this.onAdd = options.onAdd || null; this.onNew = options.onNew || null; this.onRemove = options.onRemove || null; this.onMouseOver = options.onMouseOver || null; this.onMouseOut = options.onMouseOut || null; this.onIconClick = options.onIconClick || null; this.onScroll = options.onScroll || null; this.tmp = {}; // temp object // clean up some options delete this.options.type; delete this.options.onSearch; delete this.options.onRequest; delete this.options.onLoad; delete this.options.onError; delete this.options.onClick; delete this.options.onMouseOver; delete this.options.onMouseOut; delete this.options.onIconClick; delete this.options.onScroll; // extend with defaults $.extend(true, this, w2obj.field); }; // ==================================================== // -- Registers as a jQuery plugin $.fn.w2field = function (method, options) { // call direct if (this.length === 0) { var pr = w2field.prototype; if (pr[method]) { return pr[method].apply(pr, Array.prototype.slice.call(arguments, 1)); } } else { // if without arguments - return the object if (arguments.length === 0) { var obj = $(this).data('w2field'); return obj; } if (typeof method == 'string' && typeof options == 'object') { method = $.extend(true, {}, options, { type: method }); } if (typeof method == 'string' && options == null) { method = { type: method }; } method.type = String(method.type).toLowerCase(); return this.each(function (index, el) { var obj = $(el).data('w2field'); // if object is not defined, define it if (obj == null) { var obj = new w2field(method); $.extend(obj, { handlers: [] }); if (el) obj.el = $(el)[0]; obj.init(); $(el).data('w2field', obj); return obj; } else { // fully re-init obj.clear(); if (method.type == 'clear') return; var obj = new w2field(method); $.extend(obj, { handlers: [] }); if (el) obj.el = $(el)[0]; obj.init(); $(el).data('w2field', obj); return obj; } return null; }); } }; // ==================================================== // -- Implementation of core functionality /* To add custom types $().w2field('addType', 'myType', function (options) { $(this.el).on('keypress', function (event) { if (event.metaKey || event.ctrlKey || event.altKey || (event.charCode != event.keyCode && event.keyCode > 0)) return; var ch = String.fromCharCode(event.charCode); if (ch != 'a' && ch != 'b' && ch != 'c') { if (event.stopPropagation) event.stopPropagation(); else event.cancelBubble = true; return false; } }); $(this.el).on('blur', function (event) { // keyCode & charCode differ in FireFox var ch = this.value; if (ch != 'a' && ch != 'b' && ch != 'c') { $(this).w2tag(w2utils.lang("Not a single character from the set of 'abc'")); } }); }); */ w2field.prototype = { custom: {}, // map of custom types addType: function (type, handler) { type = String(type).toLowerCase(); this.custom[type] = handler; return true; }, removeType: function (type) { type = String(type).toLowerCase(); if (!this.custom[type]) return false; delete this.custom[type]; return true; }, init: function () { var obj = this; var options = this.options; var defaults; // Custom Types if (typeof this.custom[this.type] == 'function') { this.custom[this.type].call(this, options); return; } // only for INPUT or TEXTAREA if (['INPUT', 'TEXTAREA'].indexOf(this.el.tagName.toUpperCase()) == -1) { console.log('ERROR: w2field could only be applied to INPUT or TEXTAREA.', this.el); return; } switch (this.type) { case 'text': case 'int': case 'float': case 'money': case 'currency': case 'percent': case 'alphanumeric': case 'bin': case 'hex': defaults = { min : null, max : null, step : 1, autoFormat : true, currencyPrefix : w2utils.settings.currencyPrefix, currencySuffix : w2utils.settings.currencySuffix, currencyPrecision : w2utils.settings.currencyPrecision, decimalSymbol : w2utils.settings.decimalSymbol, groupSymbol : w2utils.settings.groupSymbol, arrows : false, keyboard : true, precision : null, silent : true, prefix : '', suffix : '' }; this.options = $.extend(true, {}, defaults, options); options = this.options; // since object is re-created, need to re-assign options.numberRE = new RegExp('['+ options.groupSymbol + ']', 'g'); options.moneyRE = new RegExp('['+ options.currencyPrefix + options.currencySuffix + options.groupSymbol +']', 'g'); options.percentRE = new RegExp('['+ options.groupSymbol + '%]', 'g'); // no keyboard support needed if (['text', 'alphanumeric', 'hex', 'bin'].indexOf(this.type) != -1) { options.arrows = false; options.keyboard = false; } this.addPrefix(); // only will add if needed this.addSuffix(); break; case 'color': defaults = { prefix : '#', suffix : '
 
', arrows : false, keyboard : false, transparent : true }; $.extend(options, defaults); this.addPrefix(); // only will add if needed this.addSuffix(); // only will add if needed // additional checks $(this.el).attr('maxlength', 6); if ($(this.el).val() !== '') setTimeout(function () { obj.change(); }, 1); break; case 'date': defaults = { format : w2utils.settings.dateFormat, // date format keyboard : true, silent : true, start : '', // string or jquery object end : '', // string or jquery object blocked : {}, // { '4/11/2011': 'yes' } colored : {}, // { '4/11/2011': 'red:white' } blockWeekDays : null // array of numbers of weekday to block }; this.options = $.extend(true, {}, defaults, options); options = this.options; // since object is re-created, need to re-assign if ($(this.el).attr('placeholder') == null) $(this.el).attr('placeholder', options.format); break; case 'time': defaults = { format : w2utils.settings.timeFormat, keyboard : true, silent : true, start : '', end : '', noMinutes : false }; this.options = $.extend(true, {}, defaults, options); options = this.options; // since object is re-created, need to re-assign if ($(this.el).attr('placeholder') == null) $(this.el).attr('placeholder', options.format); break; case 'datetime': defaults = { format : w2utils.settings.dateFormat + ' | ' + w2utils.settings.timeFormat, keyboard : true, silent : true, start : '', // string or jquery object or Date object end : '', // string or jquery object or Date object blocked : [], // [ '4/11/2011', '4/12/2011' ] or [ new Date(2011, 4, 11), new Date(2011, 4, 12) ] colored : {}, // { '12/17/2014': 'blue:green', '12/18/2014': 'gray:white' }; // key has to be formatted with w2utils.settings.dateFormat placeholder : null, // optional. will fall back to this.format if not specified. Only used if this.el has no placeholder attribute. btn_now : true, // show/hide the use-current-date-and-time button noMinutes : false }; this.options = $.extend(true, {}, defaults, options); options = this.options; // since object is re-created, need to re-assign if ($(this.el).attr('placeholder') == null) $(this.el).attr('placeholder', options.placeholder || options.format); break; case 'list': case 'combo': defaults = { items : [], selected : {}, url : null, // url to pull data from recId : null, // map retrieved data from url to id, can be string or function recText : null, // map retrieved data from url to text, can be string or function method : null, // default comes from w2utils.settings.dataType interval : 350, // number of ms to wait before sending server call on search postData : {}, minLength : 1, // min number of chars when trigger search cacheMax : 250, maxDropHeight : 350, // max height for drop down menu maxDropWidth : null, // if null then auto set match : 'begins', // ['contains', 'is', 'begins', 'ends'] silent : true, icon : null, iconStyle : '', onSearch : null, // when search needs to be performed onRequest : null, // when request is submitted onLoad : null, // when data is received onError : null, // when data fails to load due to server error or other failure modes onIconClick : null, renderDrop : null, // render function for drop down item compare : null, // compare function for filtering filter : true, // weather to filter at all prefix : '', suffix : '', openOnFocus : false, // if to show overlay onclick or when typing markSearch : false }; options.items = this.normMenu(options.items); // need to be first if (this.type == 'list') { // defaults.search = (options.items && options.items.length >= 10 ? true : false); defaults.openOnFocus = true; $(this.el).addClass('w2ui-select'); // if simple value - look it up if (!$.isPlainObject(options.selected) && options.items) { for (var i = 0; i< options.items.length; i++) { var item = options.items[i]; if (item && item.id == options.selected) { options.selected = $.extend(true, {}, item); break; } } } this.watchSize(); } options = $.extend({}, defaults, options, { align : 'both', // same width as control altRows : true // alternate row color }); this.options = options; if (!$.isPlainObject(options.selected)) options.selected = {}; $(this.el).data('selected', options.selected); if (options.url) { options.items = []; this.request(0); } if (this.type == 'list') this.addFocus(); this.addPrefix(); this.addSuffix(); setTimeout(function () { obj.refresh(); }, 10); // need this for icon refresh $(this.el).attr('autocomplete', 'off'); if (options.selected.text != null) $(this.el).val(options.selected.text); break; case 'enum': defaults = { items : [], selected : [], max : 0, // max number of selected items, 0 - unlim url : null, // not implemented recId : null, // map retrieved data from url to id, can be string or function recText : null, // map retrieved data from url to text, can be string or function interval : 350, // number of ms to wait before sending server call on search method : null, // default comes from w2utils.settings.dataType postData : {}, minLength : 1, // min number of chars when trigger search cacheMax : 250, maxWidth : 250, // max width for a single item maxHeight : 350, // max height for input control to grow maxDropHeight : 350, // max height for drop down menu maxDropWidth : null, // if null then auto set match : 'contains', // ['contains', 'is', 'begins', 'ends'] silent : true, openOnFocus : false, // if to show overlay onclick or when typing markSearch : true, renderDrop : null, // render function for drop down item renderItem : null, // render selected item compare : null, // compare function for filtering filter : true, // alias for compare style : '', // style for container div onSearch : null, // when search needs to be performed onRequest : null, // when request is submitted onLoad : null, // when data is received onError : null, // when data fails to load due to server error or other failure modes onClick : null, // when an item is clicked onAdd : null, // when an item is added onNew : null, // when new item should be added onRemove : null, // when an item is removed onMouseOver : null, // when an item is mouse over onMouseOut : null, // when an item is mouse out onScroll : null // when div with selected items is scrolled }; options = $.extend({}, defaults, options, { align : 'both', // same width as control suffix : '', altRows : true // alternate row color }); options.items = this.normMenu(options.items); options.selected = this.normMenu(options.selected); this.options = options; if (!$.isArray(options.selected)) options.selected = []; $(this.el).data('selected', options.selected); if (options.url) { options.items = []; this.request(0); } this.addSuffix(); this.addMulti(); this.watchSize(); break; case 'file': defaults = { selected : [], max : 0, maxSize : 0, // max size of all files, 0 - unlim maxFileSize : 0, // max size of a single file, 0 -unlim maxWidth : 250, // max width for a single item maxHeight : 350, // max height for input control to grow maxDropHeight : 350, // max height for drop down menu maxDropWidth : null, // if null then auto set readContent : true, // if true, it will readAsDataURL content of the file silent : true, renderItem : null, // render selected item style : '', // style for container div onClick : null, // when an item is clicked onAdd : null, // when an item is added onRemove : null, // when an item is removed onMouseOver : null, // when an item is mouse over onMouseOut : null // when an item is mouse out }; options = $.extend({}, defaults, options, { align : 'both', // same width as control altRows : true // alternate row color }); this.options = options; if (!$.isArray(options.selected)) options.selected = []; $(this.el).data('selected', options.selected); if ($(this.el).attr('placeholder') == null) { $(this.el).attr('placeholder', w2utils.lang('Attach files by dragging and dropping or Click to Select')); } this.addMulti(); this.watchSize(); break; } // attach events this.tmp = { onChange : function (event) { obj.change.call(obj, event); }, onClick : function (event) { obj.click.call(obj, event); }, onFocus : function (event) { obj.focus.call(obj, event); }, onBlur : function (event) { obj.blur.call(obj, event); }, onKeydown : function (event) { obj.keyDown.call(obj, event); }, onKeyup : function (event) { obj.keyUp.call(obj, event); }, onKeypress : function (event) { obj.keyPress.call(obj, event); } }; $(this.el) .addClass('w2field w2ui-input') .data('w2field', this) .on('change.w2field', this.tmp.onChange) .on('click.w2field', this.tmp.onClick) // ignore click because it messes overlays .on('focus.w2field', this.tmp.onFocus) .on('blur.w2field', this.tmp.onBlur) .on('keydown.w2field', this.tmp.onKeydown) .on('keyup.w2field', this.tmp.onKeyup) .on('keypress.w2field', this.tmp.onKeypress) .css(w2utils.cssPrefix('box-sizing', 'border-box')); // format initial value this.change($.Event('change')); }, watchSize: function () { var obj = this; var tmp = $(obj.el).data('tmp') || {}; tmp.sizeTimer = setInterval(function () { if ($(obj.el).parents('body').length > 0) { obj.resize(); } else { clearInterval(tmp.sizeTimer); } }, 200); $(obj.el).data('tmp', tmp); }, get: function () { var ret; if (['list', 'enum', 'file'].indexOf(this.type) != -1) { ret = $(this.el).data('selected'); } else { ret = $(this.el).val(); } return ret; }, set: function (val, append) { if (['list', 'enum', 'file'].indexOf(this.type) != -1) { if (this.type != 'list' && append) { if ($(this.el).data('selected') == null) $(this.el).data('selected', []); $(this.el).data('selected').push(val); $(this.el).change(); } else { var it = (this.type == 'enum' ? [val] : val); $(this.el).data('selected', it).change(); } this.refresh(); } else { $(this.el).val(val); } }, setIndex: function (ind, append) { if (['list', 'enum'].indexOf(this.type) != -1) { var items = this.options.items; if (items && items[ind]) { if (this.type != 'list' && append) { if ($(this.el).data('selected') == null) $(this.el).data('selected', []); $(this.el).data('selected').push(items[ind]); $(this.el).change(); } else { var it = (this.type == 'enum' ? [items[ind]] : items[ind]); $(this.el).data('selected', it).change(); } this.refresh(); return true; } } return false; }, clear: function () { var options = this.options; // if money then clear value if (['money', 'currency'].indexOf(this.type) != -1) { $(this.el).val($(this.el).val().replace(options.moneyRE, '')); } if (this.type == 'percent') { $(this.el).val($(this.el).val().replace(/%/g, '')); } if (this.type == 'color') { $(this.el).removeAttr('maxlength'); } if (this.type == 'list') { $(this.el).removeClass('w2ui-select'); } this.type = 'clear'; var tmp = $(this.el).data('tmp'); if (!this.tmp) return; // restore paddings if (tmp != null) { $(this.el).height('auto'); if (tmp && tmp['old-padding-left']) $(this.el).css('padding-left', tmp['old-padding-left']); if (tmp && tmp['old-padding-right']) $(this.el).css('padding-right', tmp['old-padding-right']); if (tmp && tmp['old-background-color']) $(this.el).css('background-color', tmp['old-background-color']); if (tmp && tmp['old-border-color']) $(this.el).css('border-color', tmp['old-border-color']); // remove resize watcher clearInterval(tmp.sizeTimer); } // remove events and (data) $(this.el) .val(this.clean($(this.el).val())) .removeClass('w2field') .removeData() // removes all attached data .off('.w2field'); // remove only events added by w2field // remove helpers for (var h in this.helpers) $(this.helpers[h]).remove(); this.helpers = {}; }, refresh: function () { var obj = this; var options = this.options; var selected = $(this.el).data('selected'); var time = (new Date()).getTime(); // enum if (['list'].indexOf(this.type) != -1) { $(obj.el).parent().css('white-space', 'nowrap'); // needs this for arrow always to appear on the right side // hide focus and show text if (obj.helpers.prefix) obj.helpers.prefix.hide(); setTimeout(function () { if (!obj.helpers.focus) return; // if empty show no icon if (!$.isEmptyObject(selected) && options.icon) { options.prefix = ''+ ''; obj.addPrefix(); } else { options.prefix = ''; obj.addPrefix(); } // focus helper var focus = obj.helpers.focus.find('input'); if ($(focus).val() === '') { $(focus).css('text-indent', '-9999em').prev().css('opacity', 0); $(obj.el).val(selected && selected.text != null ? w2utils.lang(selected.text) : ''); } else { $(focus).css('text-indent', 0).prev().css('opacity', 1); $(obj.el).val(''); setTimeout(function () { if (obj.helpers.prefix) obj.helpers.prefix.hide(); var tmp = 'position: absolute; opacity: 0; margin: 4px 0px 0px 2px; background-position: left !important;'; if (options.icon) { $(focus).css('margin-left', '17px'); $(obj.helpers.focus).find('.icon-search').attr('style', tmp + 'width: 11px !important; opacity: 1; display: block'); } else { $(focus).css('margin-left', '0px'); $(obj.helpers.focus).find('.icon-search').attr('style', tmp + 'width: 0px !important; opacity: 0; display: none'); } }, 1); } // if readonly or disabled if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) { setTimeout(function () { $(obj.helpers.prefix).css('opacity', '0.6'); $(obj.helpers.suffix).css('opacity', '0.6'); }, 1); } else { setTimeout(function () { $(obj.helpers.prefix).css('opacity', '1'); $(obj.helpers.suffix).css('opacity', '1'); }, 1); } }, 1); } if (['enum', 'file'].indexOf(this.type) != -1) { var html = ''; if (selected) { for (var s = 0; s < selected.length; s++) { var it = selected[s]; var ren = ''; if (typeof options.renderItem == 'function') { ren = options.renderItem(it, s, '
  
'); } else { ren = '
  
'+ (obj.type == 'enum' ? it.text : it.name + ' - '+ w2utils.formatSize(it.size) +''); } html += '
  • '+ ren +'
  • '; } } var div = obj.helpers.multi; var ul = div.find('ul'); div.attr('style', div.attr('style') + ';' + options.style); $(obj.el).css('z-index', '-1'); if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) { setTimeout(function () { div[0].scrollTop = 0; // scroll to the top div.addClass('w2ui-readonly') .find('li').css('opacity', '0.9') .parent().find('li.nomouse').hide() .find('input').prop('readonly', true) .parents('ul') .find('.w2ui-list-remove').hide(); }, 1); } else { setTimeout(function () { div.removeClass('w2ui-readonly') .find('li').css('opacity', '1') .parent().find('li.nomouse').show() .find('input').prop('readonly', false) .parents('ul') .find('.w2ui-list-remove').show(); }, 1); } // clean div.find('.w2ui-enum-placeholder').remove(); ul.find('li').not('li.nomouse').remove(); // add new list if (html !== '') { ul.prepend(html); } else if ($(obj.el).attr('placeholder') != null && div.find('input').val() === '') { var style = 'padding-top: ' + $(this.el).css('padding-top') + ';'+ 'padding-left: ' + $(this.el).css('padding-left') + '; ' + 'box-sizing: ' + $(this.el).css('box-sizing') + '; ' + 'line-height: ' + $(this.el).css('line-height') + '; ' + 'font-size: ' + $(this.el).css('font-size') + '; ' + 'font-family: ' + $(this.el).css('font-family') + '; '; div.prepend('
    '+ $(obj.el).attr('placeholder') +'
    '); } // ITEMS events div.off('scroll.w2field').on('scroll.w2field', function (event) { var edata = obj.trigger({ phase: 'before', type: 'scroll', target: obj.el, originalEvent: event }); if (edata.isCancelled === true) return; // event after obj.trigger($.extend(edata, { phase: 'after' })); }) .find('li') .data('mouse', 'out') .on('click', function (event) { var target = (event.target.tagName.toUpperCase() == 'LI' ? event.target : $(event.target).parents('LI')); var item = selected[$(target).attr('index')]; if ($(target).hasClass('nomouse')) return; event.stopPropagation(); // default behavior if ($(event.target).hasClass('w2ui-list-remove')) { if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; // trigger event var edata = obj.trigger({ phase: 'before', type: 'remove', target: obj.el, originalEvent: event.originalEvent, item: item }); if (edata.isCancelled === true) return; // default behavior $().w2overlay(); selected.splice($(event.target).attr('index'), 1); $(obj.el).trigger('change'); $(event.target).parent().fadeOut('fast'); setTimeout(function () { obj.refresh(); // event after obj.trigger($.extend(edata, { phase: 'after' })); }, 300); } else { // trigger event var edata = obj.trigger({ phase: 'before', type: 'click', target: obj.el, originalEvent: event.originalEvent, item: item }); if (edata.isCancelled === true) return; // if file - show image preview if (obj.type == 'file') { var preview = ''; if ((/image/i).test(item.type)) { // image preview = '
    '+ ' '+ '
    '; } var td1 = 'style="padding: 3px; text-align: right; color: #777;"'; var td2 = 'style="padding: 3px"'; preview += '
    '+ ' '+ ' '+ ' '+ ' '+ ' '+ '
    '+ w2utils.lang('Name') +':'+ item.name +'
    '+ w2utils.lang('Size') +':'+ w2utils.formatSize(item.size) +'
    '+ w2utils.lang('Type') +':' + ' '+ item.type +''+ '
    '+ w2utils.lang('Modified') +':'+ w2utils.date(item.modified) +'
    '+ '
    '; $('#w2ui-overlay').remove(); $(target).w2overlay(preview); } // event after obj.trigger($.extend(edata, { phase: 'after' })); } }) .on('mouseover', function (event) { var target = (event.target.tagName.toUpperCase() == 'LI' ? event.target : $(event.target).parents('LI')); if ($(target).hasClass('nomouse')) return; if ($(target).data('mouse') == 'out') { var item = selected[$(event.target).attr('index')]; // trigger event var edata = obj.trigger({ phase: 'before', type: 'mouseOver', target: obj.el, originalEvent: event.originalEvent, item: item }); if (edata.isCancelled === true) return; // event after obj.trigger($.extend(edata, { phase: 'after' })); } $(target).data('mouse', 'over'); }) .on('mouseout', function (event) { var target = (event.target.tagName.toUpperCase() == 'LI' ? event.target : $(event.target).parents('LI')); if ($(target).hasClass('nomouse')) return; $(target).data('mouse', 'leaving'); setTimeout(function () { if ($(target).data('mouse') == 'leaving') { $(target).data('mouse', 'out'); var item = selected[$(event.target).attr('index')]; // trigger event var edata = obj.trigger({ phase: 'before', type: 'mouseOut', target: obj.el, originalEvent: event.originalEvent, item: item }); if (edata.isCancelled === true) return; // event after obj.trigger($.extend(edata, { phase: 'after' })); } }, 0); }); // adjust height $(this.el).height('auto'); var cntHeight = $(div).find('> div.w2ui-multi-items').height() + w2utils.getSize(div, '+height') * 2; if (cntHeight < 26) cntHeight = 26; if (cntHeight > options.maxHeight) cntHeight = options.maxHeight; if (div.length > 0) div[0].scrollTop = 1000; var inpHeight = w2utils.getSize($(this.el), 'height') - 2; if (inpHeight > cntHeight) cntHeight = inpHeight; $(div).css({ 'height': cntHeight + 'px', overflow: (cntHeight == options.maxHeight ? 'auto' : 'hidden') }); if (cntHeight < options.maxHeight) $(div).prop('scrollTop', 0); $(this.el).css({ 'height' : (cntHeight + 2) + 'px' }); // update size if (obj.type == 'enum') { var tmp = obj.helpers.multi.find('input'); tmp.width(((tmp.val().length + 2) * 8) + 'px'); } } return (new Date()).getTime() - time; }, reset: function () { var type = this.type; this.clear(); this.type = type; this.init(); }, // resizing width of list, enum, file controls resize: function () { var obj = this; var new_width = $(obj.el).width(); var new_height = $(obj.el).height(); if (obj.tmp.current_width == new_width && new_height > 0) return; var focus = this.helpers.focus; var multi = this.helpers.multi; var suffix = this.helpers.suffix; var prefix = this.helpers.prefix; // resize helpers if (focus) { focus.width($(obj.el).width()); } if (multi) { var width = (w2utils.getSize(obj.el, 'width') - parseInt($(obj.el).css('margin-left'), 10) - parseInt($(obj.el).css('margin-right'), 10)); $(multi).width(width); } if (suffix) { obj.options.suffix = '
    '; obj.addSuffix(); } if (prefix) { obj.addPrefix(); } // remember width obj.tmp.current_width = new_width; }, clean: function (val) { //issue #499 if(typeof val == 'number'){ return val; } var options = this.options; val = String(val).trim(); // clean if (['int', 'float', 'money', 'currency', 'percent'].indexOf(this.type) != -1) { if (typeof val == 'string') { if (options.autoFormat && ['money', 'currency'].indexOf(this.type) != -1) val = String(val).replace(options.moneyRE, ''); if (options.autoFormat && this.type == 'percent') val = String(val).replace(options.percentRE, ''); if (options.autoFormat && ['int', 'float'].indexOf(this.type) != -1) val = String(val).replace(options.numberRE, ''); val = val.replace(/\s+/g, '').replace(w2utils.settings.groupSymbol, '').replace(w2utils.settings.decimalSymbol, '.'); } if (parseFloat(val) == val) { if (options.min != null && val < options.min) { val = options.min; $(this.el).val(options.min); } if (options.max != null && val > options.max) { val = options.max; $(this.el).val(options.max); } } if (val !== '' && w2utils.isFloat(val)) val = Number(val); else val = ''; } return val; }, format: function (val) { var options = this.options; // autoformat numbers or money if (options.autoFormat && val !== '') { switch (this.type) { case 'money': case 'currency': val = w2utils.formatNumber(val, options.currencyPrecision, options.groupSymbol); if (val !== '') val = options.currencyPrefix + val + options.currencySuffix; break; case 'percent': val = w2utils.formatNumber(val, options.precision, options.groupSymbol); if (val !== '') val += '%'; break; case 'float': val = w2utils.formatNumber(val, options.precision, options.groupSymbol); break; case 'int': val = w2utils.formatNumber(val, 0, options.groupSymbol); break; } } return val; }, change: function (event) { var obj = this; var options = obj.options; // numeric if (['int', 'float', 'money', 'currency', 'percent'].indexOf(this.type) != -1) { // check max/min var val = $(this.el).val(); var new_val = this.format(this.clean($(this.el).val())); // if was modified if (val !== '' && val != new_val) { $(this.el).val(new_val).change(); // cancel event event.stopPropagation(); event.preventDefault(); return false; } } // color if (this.type == 'color') { var color = '#' + $(this.el).val(); if ($(this.el).val().length != 6 && $(this.el).val().length != 3) color = ''; $(this.el).next().find('div').css('background-color', color); if ($(obj.el).is(':focus')) this.updateOverlay(); } // list, enum if (['list', 'enum', 'file'].indexOf(this.type) != -1) { obj.refresh(); // need time out to show icon indent properly setTimeout(function () { obj.refresh(); }, 5); } // date, time if (['date', 'time', 'datetime'].indexOf(this.type) != -1) { // convert linux timestamps var tmp = parseInt(obj.el.value); if (w2utils.isInt(obj.el.value) && tmp > 3000) { if (this.type == 'time') $(obj.el).val(w2utils.formatTime(new Date(tmp), options.format)).change(); if (this.type == 'date') $(obj.el).val(w2utils.formatDate(new Date(tmp), options.format)).change(); if (this.type == 'datetime') $(obj.el).val(w2utils.formatDateTime(new Date(tmp), options.format)).change(); } } }, click: function (event) { event.stopPropagation(); // lists if (['list', 'combo', 'enum'].indexOf(this.type) != -1) { if (!$(this.el).is(':focus')) this.focus(event); } // other fields with drops if (['date', 'time', 'color', 'datetime'].indexOf(this.type) != -1) { this.updateOverlay(); } }, focus: function (event) { var obj = this; var options = this.options; // color, date, time if (['color', 'date', 'time', 'datetime'].indexOf(obj.type) !== -1) { if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay')[0].hide(); setTimeout(function () { obj.updateOverlay(); }, 150); } // menu if (['list', 'combo', 'enum'].indexOf(obj.type) != -1) { if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay')[0].hide(); obj.resize(); setTimeout(function () { if (obj.type == 'list' && $(obj.el).is(':focus')) { $(obj.helpers.focus).find('input').focus(); return; } obj.search(); setTimeout(function () { obj.updateOverlay(); }, 1); }, 1); } // file if (obj.type == 'file') { $(obj.helpers.multi).css({ 'outline': 'auto 5px #7DB4F3', 'outline-offset': '-2px' }); } }, blur: function (event) { var obj = this; var options = obj.options; var val = $(obj.el).val().trim(); // hide overlay if (['color', 'date', 'time', 'list', 'combo', 'enum', 'datetime'].indexOf(obj.type) != -1) { if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay')[0].hide(); } if (['int', 'float', 'money', 'currency', 'percent'].indexOf(obj.type) != -1) { if (val !== '' && !obj.checkType(val)) { $(obj.el).val('').change(); if (options.silent === false) { $(obj.el).w2tag('Not a valid number'); setTimeout(function () { $(obj.el).w2tag(''); }, 3000); } } } // date or time if (['date', 'time', 'datetime'].indexOf(obj.type) != -1) { // check if in range if (val !== '' && !obj.inRange(obj.el.value)) { $(obj.el).val('').removeData('selected').change(); if (options.silent === false) { $(obj.el).w2tag('Not in range'); setTimeout(function () { $(obj.el).w2tag(''); }, 3000); } } else { if (obj.type == 'date' && val !== '' && !w2utils.isDate(obj.el.value, options.format)) { $(obj.el).val('').removeData('selected').change(); if (options.silent === false) { $(obj.el).w2tag('Not a valid date'); setTimeout(function () { $(obj.el).w2tag(''); }, 3000); } } else if (obj.type == 'time' && val !== '' && !w2utils.isTime(obj.el.value)) { $(obj.el).val('').removeData('selected').change(); if (options.silent === false) { $(obj.el).w2tag('Not a valid time'); setTimeout(function () { $(obj.el).w2tag(''); }, 3000); } } else if (obj.type == 'datetime' && val !== '' && !w2utils.isDateTime(obj.el.value, options.format)) { $(obj.el).val('').removeData('selected').change(); if (options.silent === false) { $(obj.el).w2tag('Not a valid date'); setTimeout(function () { $(obj.el).w2tag(''); }, 3000); } } } } // clear search input if (obj.type == 'enum') { $(obj.helpers.multi).find('input').val('').width(20); } // file if (obj.type == 'file') { $(obj.helpers.multi).css({ 'outline': 'none' }); } }, keyPress: function (event) { var obj = this; var options = obj.options; // ignore wrong pressed key if (['int', 'float', 'money', 'currency', 'percent', 'hex', 'bin', 'color', 'alphanumeric'].indexOf(obj.type) != -1) { // keyCode & charCode differ in FireFox if (event.metaKey || event.ctrlKey || event.altKey || (event.charCode != event.keyCode && event.keyCode > 0)) return; var ch = String.fromCharCode(event.charCode); if (!obj.checkType(ch, true) && event.keyCode != 13) { event.preventDefault(); if (event.stopPropagation) event.stopPropagation(); else event.cancelBubble = true; return false; } } // update date popup if (['date', 'time', 'datetime'].indexOf(obj.type) != -1) { if (event.keyCode !== 9) setTimeout(function () { obj.updateOverlay(); }, 1); } }, keyDown: function (event, extra) { var obj = this; var options = obj.options; var key = event.keyCode || (extra && extra.keyCode); // numeric if (['int', 'float', 'money', 'currency', 'percent'].indexOf(obj.type) != -1) { if (!options.keyboard || $(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; var cancel = false; var val = parseFloat($(obj.el).val().replace(options.moneyRE, '')) || 0; var inc = options.step; if (event.ctrlKey || event.metaKey) inc = 10; switch (key) { case 38: // up if (event.shiftKey) break; // no action if shift key is pressed $(obj.el).val((val + inc <= options.max || options.max == null ? Number((val + inc).toFixed(12)) : options.max)).change(); cancel = true; break; case 40: // down if (event.shiftKey) break; // no action if shift key is pressed $(obj.el).val((val - inc >= options.min || options.min == null ? Number((val - inc).toFixed(12)) : options.min)).change(); cancel = true; break; } if (cancel) { event.preventDefault(); setTimeout(function () { // set cursor to the end obj.el.setSelectionRange(obj.el.value.length, obj.el.value.length); }, 0); } } // date if (obj.type == 'date') { if (!options.keyboard || $(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; var cancel = false; var daymil = 24*60*60*1000; var inc = 1; if (event.ctrlKey || event.metaKey) inc = 10; var dt = w2utils.isDate($(obj.el).val(), options.format, true); if (!dt) { dt = new Date(); daymil = 0; } switch (key) { case 38: // up if (event.shiftKey) break; // no action if shift key is pressed var newDT = w2utils.formatDate(dt.getTime() + daymil, options.format); if (inc == 10) newDT = w2utils.formatDate(new Date(dt.getFullYear(), dt.getMonth()+1, dt.getDate()), options.format); $(obj.el).val(newDT).change(); cancel = true; break; case 40: // down if (event.shiftKey) break; // no action if shift key is pressed var newDT = w2utils.formatDate(dt.getTime() - daymil, options.format); if (inc == 10) newDT = w2utils.formatDate(new Date(dt.getFullYear(), dt.getMonth()-1, dt.getDate()), options.format); $(obj.el).val(newDT).change(); cancel = true; break; } if (cancel) { event.preventDefault(); setTimeout(function () { // set cursor to the end obj.el.setSelectionRange(obj.el.value.length, obj.el.value.length); obj.updateOverlay(); }, 0); } } // time if (obj.type == 'time') { if (!options.keyboard || $(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; var cancel = false; var inc = (event.ctrlKey || event.metaKey ? 60 : 1); var val = $(obj.el).val(); var time = obj.toMin(val) || obj.toMin((new Date()).getHours() + ':' + ((new Date()).getMinutes() - 1)); switch (key) { case 38: // up if (event.shiftKey) break; // no action if shift key is pressed time += inc; cancel = true; break; case 40: // down if (event.shiftKey) break; // no action if shift key is pressed time -= inc; cancel = true; break; } if (cancel) { $(obj.el).val(obj.fromMin(time)).change(); event.preventDefault(); setTimeout(function () { // set cursor to the end obj.el.setSelectionRange(obj.el.value.length, obj.el.value.length); }, 0); } } // datetime if (obj.type == 'datetime') { if (!options.keyboard || $(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; var cancel = false; var daymil = 24*60*60*1000; var inc = 1; if (event.ctrlKey || event.metaKey) inc = 10; var str = $(obj.el).val(); var dt = w2utils.isDateTime(str, this.options.format, true); if (!dt) { dt = new Date(); daymil = 0; } switch (key) { case 38: // up if (event.shiftKey) break; // no action if shift key is pressed var newDT = w2utils.formatDateTime(dt.getTime() + daymil, options.format); if (inc == 10) newDT = w2utils.formatDateTime(new Date(dt.getFullYear(), dt.getMonth()+1, dt.getDate()), options.format); $(obj.el).val(newDT).change(); cancel = true; break; case 40: // down if (event.shiftKey) break; // no action if shift key is pressed var newDT = w2utils.formatDateTime(dt.getTime() - daymil, options.format); if (inc == 10) newDT = w2utils.formatDateTime(new Date(dt.getFullYear(), dt.getMonth()-1, dt.getDate()), options.format); $(obj.el).val(newDT).change(); cancel = true; break; } if (cancel) { event.preventDefault(); setTimeout(function () { // set cursor to the end obj.el.setSelectionRange(obj.el.value.length, obj.el.value.length); obj.updateOverlay(); }, 0); } } // color if (obj.type == 'color') { if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; // paste if (event.keyCode == 86 && (event.ctrlKey || event.metaKey)) { $(obj.el).prop('maxlength', 7); setTimeout(function () { var val = $(obj).val(); if (val.substr(0, 1) == '#') val = val.substr(1); if (!w2utils.isHex(val)) val = ''; $(obj).val(val).prop('maxlength', 6).change(); }, 20); } if ((event.ctrlKey || event.metaKey) && !event.shiftKey) { var dir = null; var newColor = null; switch (key) { case 38: // up dir = 'up'; break; case 40: // down dir = 'down'; break; case 39: // right dir = 'right'; break; case 37: // left dir = 'left'; break; } if (obj.el.nav && dir != null) { newColor = obj.el.nav(dir); $(obj.el).val(newColor).change(); event.preventDefault(); } } } // list/select/combo if (['list', 'combo', 'enum'].indexOf(obj.type) != -1) { if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; var selected = $(obj.el).data('selected'); var focus = $(obj.el); var indexOnly = false; if (['list', 'enum'].indexOf(obj.type) != -1) { if (obj.type == 'list') { focus = $(obj.helpers.focus).find('input'); } if (obj.type == 'enum') { focus = $(obj.helpers.multi).find('input'); } // not arrows - refresh if ([37, 38, 39, 40].indexOf(key) == -1) { setTimeout(function () { obj.refresh(); }, 1); } // paste if (event.keyCode == 86 && (event.ctrlKey || event.metaKey)) { setTimeout(function () { obj.refresh(); obj.search(); obj.request(); }, 50); } } // apply arrows switch (key) { case 27: // escape if (obj.type == 'list') { if (focus.val() !== '') focus.val(''); event.stopPropagation(); // escape in field should not close popup } break; case 37: // left case 39: // right // indexOnly = true; break; case 13: // enter if ($('#w2ui-overlay').length === 0) break; // no action if overlay not open var item = options.items[options.index]; if (obj.type == 'enum') { if (item != null) { // trigger event var edata = obj.trigger({ phase: 'before', type: 'add', target: obj.el, originalEvent: event.originalEvent, item: item }); if (edata.isCancelled === true) return; item = edata.item; // need to reassign because it could be recreated by user // default behavior if (selected.length >= options.max && options.max > 0) selected.pop(); delete item.hidden; delete obj.tmp.force_open; selected.push(item); $(obj.el).change(); focus.val('').width(20); obj.refresh(); // event after obj.trigger($.extend(edata, { phase: 'after' })); } else { // trigger event item = { id: focus.val(), text: focus.val() }; var edata = obj.trigger({ phase: 'before', type: 'new', target: obj.el, originalEvent: event.originalEvent, item: item }); if (edata.isCancelled === true) return; item = edata.item; // need to reassign because it could be recreated by user // default behavior if (typeof obj.onNew == 'function') { if (selected.length >= options.max && options.max > 0) selected.pop(); delete obj.tmp.force_open; selected.push(item); $(obj.el).change(); focus.val('').width(20); obj.refresh(); } // event after obj.trigger($.extend(edata, { phase: 'after' })); } } else { if (item) $(obj.el).data('selected', item).val(item.text).change(); if ($(obj.el).val() === '' && $(obj.el).data('selected')) $(obj.el).removeData('selected').val('').change(); if (obj.type == 'list') { focus.val(''); obj.refresh(); } // hide overlay obj.tmp.force_hide = true; } break; case 8: // backspace case 46: // delete if (obj.type == 'enum' && key == 8) { if (focus.val() === '' && selected.length > 0) { var item = selected[selected.length - 1]; // trigger event var edata = obj.trigger({ phase: 'before', type: 'remove', target: obj.el, originalEvent: event.originalEvent, item: item }); if (edata.isCancelled === true) return; // default behavior selected.pop(); $(obj.el).trigger('change'); obj.refresh(); // event after obj.trigger($.extend(edata, { phase: 'after' })); } } if (obj.type == 'list' && focus.val() === '') { $(obj.el).data('selected', {}).change(); obj.refresh(); } break; case 38: // up options.index = w2utils.isInt(options.index) ? parseInt(options.index) : 0; options.index--; while (options.index > 0 && options.items[options.index].hidden) options.index--; if (options.index === 0 && options.items[options.index].hidden) { while (options.items[options.index] && options.items[options.index].hidden) options.index++; } indexOnly = true; break; case 40: // down options.index = w2utils.isInt(options.index) ? parseInt(options.index) : -1; options.index++; while (options.index < options.items.length-1 && options.items[options.index].hidden) options.index++; if (options.index == options.items.length-1 && options.items[options.index].hidden) { while (options.items[options.index] && options.items[options.index].hidden) options.index--; } // show overlay if not shown if (focus.val() === '' && $('#w2ui-overlay').length === 0) { obj.tmp.force_open = true; } else { indexOnly = true; } break; } if (indexOnly) { if (options.index < 0) options.index = 0; if (options.index >= options.items.length) options.index = options.items.length -1; obj.updateOverlay(indexOnly); // cancel event event.preventDefault(); setTimeout(function () { // set cursor to the end if (obj.type == 'enum') { var tmp = focus.get(0); tmp.setSelectionRange(tmp.value.length, tmp.value.length); } else if (obj.type == 'list') { var tmp = focus.get(0); tmp.setSelectionRange(tmp.value.length, tmp.value.length); } else { obj.el.setSelectionRange(obj.el.value.length, obj.el.value.length); } }, 0); return; } // expand input if (obj.type == 'enum') { focus.width(((focus.val().length + 2) * 8) + 'px'); } } }, keyUp: function (event) { var obj = this; if (this.type == 'color') { if (event.keyCode == 86 && (event.ctrlKey || event.metaKey)) { $(this).prop('maxlength', 6); } } if (['list', 'combo', 'enum'].indexOf(this.type) != -1) { if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; // need to be here for ipad compa if ([16, 17, 18, 20, 37, 39, 91].indexOf(event.keyCode) == -1) { // no refreah on crtl, shift, left/right arrows, etc var input = $(this.helpers.focus).find('input'); if (input.length === 0) input = $(this.el); // for combo list // trigger event var edata = this.trigger({ phase: 'before', type: 'search', originalEvent: event, target: input, search: input.val() }); if (edata.isCancelled === true) return; // regular if (!this.tmp.force_hide) this.request(); if (input.val().length == 1) this.refresh(); if ($('#w2ui-overlay').length === 0 || [38, 40].indexOf(event.keyCode) == -1) { // no search on arrows this.search(); } // event after this.trigger($.extend(edata, { phase: 'after' })); } } }, clearCache: function () { var options = this.options; options.items = []; this.tmp.xhr_loading = false; this.tmp.xhr_search = ''; this.tmp.xhr_total = -1; }, request: function (interval) { var obj = this; var options = this.options; var search = $(obj.el).val() || ''; // if no url - do nothing if (!options.url) return; // -- if (obj.type == 'enum') { var tmp = $(obj.helpers.multi).find('input'); if (tmp.length === 0) search = ''; else search = tmp.val(); } if (obj.type == 'list') { var tmp = $(obj.helpers.focus).find('input'); if (tmp.length === 0) search = ''; else search = tmp.val(); } if (options.minLength !== 0 && search.length < options.minLength) { options.items = []; // need to empty the list this.updateOverlay(); return; } if (interval == null) interval = options.interval; if (obj.tmp.xhr_search == null) obj.tmp.xhr_search = ''; if (obj.tmp.xhr_total == null) obj.tmp.xhr_total = -1; // check if need to search if (options.url && $(obj.el).prop('readonly') !== true && $(obj.el).prop('disabled') !== true && ( (options.items.length === 0 && obj.tmp.xhr_total !== 0) || (obj.tmp.xhr_total == options.cacheMax && search.length > obj.tmp.xhr_search.length) || (search.length >= obj.tmp.xhr_search.length && search.substr(0, obj.tmp.xhr_search.length) != obj.tmp.xhr_search) || (search.length < obj.tmp.xhr_search.length) )) { // empty list if (obj.tmp.xhr) obj.tmp.xhr.abort(); obj.tmp.xhr_loading = true; obj.search(); // timeout clearTimeout(obj.tmp.timeout); obj.tmp.timeout = setTimeout(function () { // trigger event var url = options.url; var postData = { search : search, max : options.cacheMax }; $.extend(postData, options.postData); var edata = obj.trigger({ phase: 'before', type: 'request', search: search, target: obj.el, url: url, postData: postData }); if (edata.isCancelled === true) return; url = edata.url; postData = edata.postData; var ajaxOptions = { type : 'GET', url : url, data : postData, dataType : 'JSON' // expected from server }; if (options.method) ajaxOptions.type = options.method; if (w2utils.settings.dataType == 'JSON') { ajaxOptions.type = 'POST'; ajaxOptions.data = JSON.stringify(ajaxOptions.data); ajaxOptions.contentType = 'application/json'; } if (w2utils.settings.dataType == 'HTTPJSON') { ajaxOptions.data = { request: JSON.stringify(ajaxOptions.data) }; } if (options.method != null) ajaxOptions.type = options.method; obj.tmp.xhr = $.ajax(ajaxOptions) .done(function (data, status, xhr) { // trigger event var edata2 = obj.trigger({ phase: 'before', type: 'load', target: obj.el, search: postData.search, data: data, xhr: xhr }); if (edata2.isCancelled === true) return; // default behavior data = edata2.data; if (typeof data == 'string') data = JSON.parse(data); if (data.records == null && data.items != null) { // needed for backward compatibility data.records = data.items; delete data.items; } if (data.status != 'success' || !Array.isArray(data.records)) { console.log('ERROR: server did not return proper structure. It should return', { status: 'success', records: [{ id: 1, text: 'item' }] }); return; } // remove all extra items if more then needed for cache if (data.records.length > options.cacheMax) data.records.splice(options.cacheMax, 100000); // map id and text if (options.recId == null && options.recid != null) options.recId = options.recid; // since lower-case recid is used in grid if (options.recId || options.recText) { data.records.forEach(function (item) { if (typeof options.recId == 'string') item.id = item[options.recId]; if (typeof options.recId == 'function') item.id = options.recId(item); if (typeof options.recText == 'string') item.text = item[options.recText]; if (typeof options.recText == 'function') item.text = options.recText(item); }); } // remember stats obj.tmp.xhr_loading = false; obj.tmp.xhr_search = search; obj.tmp.xhr_total = data.records.length; options.items = obj.normMenu(data.records); if (search === '' && data.records.length === 0) obj.tmp.emptySet = true; else obj.tmp.emptySet = false; obj.search(); // event after obj.trigger($.extend(edata2, { phase: 'after' })); }) .fail(function (xhr, status, error) { // trigger event var errorObj = { status: status, error: error, rawResponseText: xhr.responseText }; var edata2 = obj.trigger({ phase: 'before', type: 'error', target: obj.el, search: search, error: errorObj, xhr: xhr }); if (edata2.isCancelled === true) return; // default behavior if (status != 'abort') { var data; try { data = $.parseJSON(xhr.responseText); } catch (e) {} console.log('ERROR: Server communication failed.', '\n EXPECTED:', { status: 'success', records: [{ id: 1, text: 'item' }] }, '\n OR:', { status: 'error', message: 'error message' }, '\n RECEIVED:', typeof data == 'object' ? data : xhr.responseText); } // reset stats obj.clearCache(); obj.search(); // event after obj.trigger($.extend(edata2, { phase: 'after' })); }); // event after obj.trigger($.extend(edata, { phase: 'after' })); }, interval); } }, search: function () { var obj = this; var options = this.options; var search = $(obj.el).val(); var target = obj.el; var ids = []; var selected = $(obj.el).data('selected'); if (obj.type == 'enum') { target = $(obj.helpers.multi).find('input'); search = target.val(); for (var s in selected) { if (selected[s]) ids.push(selected[s].id); } } else if (obj.type == 'list') { target = $(obj.helpers.focus).find('input'); search = target.val(); for (var s in selected) { if (selected[s]) ids.push(selected[s].id); } } if (obj.tmp.xhr_loading !== true) { var shown = 0; for (var i = 0; i < options.items.length; i++) { var item = options.items[i]; if (options.compare != null) { if (typeof options.compare == 'function') { item.hidden = (options.compare.call(this, item, search) === false ? true : false); } } else { var prefix = ''; var suffix = ''; if (['is', 'begins'].indexOf(options.match) != -1) prefix = '^'; if (['is', 'ends'].indexOf(options.match) != -1) suffix = '$'; try { var re = new RegExp(prefix + search + suffix, 'i'); if (re.test(item.text) || item.text == '...') item.hidden = false; else item.hidden = true; } catch (e) {} } if (options.filter === false) item.hidden = false; // do not show selected items if (obj.type == 'enum' && $.inArray(item.id, ids) != -1) item.hidden = true; if (item.hidden !== true) { shown++; delete item.hidden; } } // preselect first item options.index = -1; while (options.items[options.index] && options.items[options.index].hidden) options.index++; if (shown <= 0) options.index = -1; options.spinner = false; obj.updateOverlay(); setTimeout(function () { var html = $('#w2ui-overlay').html() || ''; if (options.markSearch && html.indexOf('$.fn.w2menuHandler') != -1) { // do not highlight when no items $('#w2ui-overlay').w2marker(search); } }, 1); } else { options.items.splice(0, options.cacheMax); options.spinner = true; obj.updateOverlay(); } }, updateOverlay: function (indexOnly) { var obj = this; var options = this.options; // color if (this.type == 'color') { if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; $(this.el).w2color({ color: $(this.el).val(), transparent: options.transparent }, function (color) { if (color == null) return; $(obj.el).val(color).change(); }); } // date if (this.type == 'date') { if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; if ($('#w2ui-overlay').length === 0) { $(obj.el).w2overlay('
    ', { css: { "background-color": "#f5f5f5" } }); } var month, year; var dt = w2utils.isDate($(obj.el).val(), obj.options.format, true); if (dt) { month = dt.getMonth() + 1; year = dt.getFullYear(); } (function refreshCalendar(month, year) { $('#w2ui-overlay > div > div').html(obj.getMonthHTML(month, year, $(obj.el).val())); $('#w2ui-overlay .w2ui-calendar-title') .on('mousedown', function () { if ($(this).next().hasClass('w2ui-calendar-jump')) { $(this).next().remove(); } else { var selYear, selMonth; $(this).after('
    '); $(this).next().hide().html(obj.getYearHTML()).fadeIn(200); setTimeout(function () { $('#w2ui-overlay .w2ui-calendar-jump') .find('.w2ui-jump-month, .w2ui-jump-year') .on('click', function () { if ($(this).hasClass('w2ui-jump-month')) { $(this).parent().find('.w2ui-jump-month').removeClass('selected'); $(this).addClass('selected'); selMonth = $(this).attr('name'); } if ($(this).hasClass('w2ui-jump-year')) { $(this).parent().find('.w2ui-jump-year').removeClass('selected'); $(this).addClass('selected'); selYear = $(this).attr('name'); } if (selYear != null && selMonth != null) { $('#w2ui-overlay .w2ui-calendar-jump').fadeOut(100); setTimeout(function () { refreshCalendar(parseInt(selMonth)+1, selYear); }, 100); } }); $('#w2ui-overlay .w2ui-calendar-jump >:last-child').prop('scrollTop', 2000); }, 1); } }); $('#w2ui-overlay .w2ui-date') .on('mousedown', function () { var day = $(this).attr('date'); $(obj.el).val(day).change(); $(this).css({ 'background-color': '#B6D5FB', 'border-color': '#aaa' }); }) .on('mouseup', function () { setTimeout(function () { if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay').removeData('keepOpen')[0].hide(); }, 10); }); $('#w2ui-overlay .previous').on('mousedown', function () { var tmp = obj.options.current.split('/'); tmp[0] = parseInt(tmp[0]) - 1; refreshCalendar(tmp[0], tmp[1]); }); $('#w2ui-overlay .next').on('mousedown', function () { var tmp = obj.options.current.split('/'); tmp[0] = parseInt(tmp[0]) + 1; refreshCalendar(tmp[0], tmp[1]); }); }) (month, year); } // time if (this.type == 'time') { if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; if ($('#w2ui-overlay').length === 0) { $(obj.el).w2overlay('
    ', { css: { "background-color": "#fff" } }); } var h24 = (this.options.format == 'h24'); $('#w2ui-overlay > div').html(obj.getHourHTML()); $('#w2ui-overlay .w2ui-time') .on('mousedown', function (event) { $(this).css({ 'background-color': '#B6D5FB', 'border-color': '#aaa' }); var hour = $(this).attr('hour'); $(obj.el).val((hour > 12 && !h24 ? hour - 12 : hour) + ':00' + (!h24 ? (hour < 12 ? ' am' : ' pm') : '')).change(); }); if (this.options.noMinutes == null || this.options.noMinutes === false) { $('#w2ui-overlay .w2ui-time') .on('mouseup', function () { var hour = $(this).attr('hour'); if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay')[0].hide(); $(obj.el).w2overlay('
    ', { css: { "background-color": "#fff" } }); $('#w2ui-overlay > div').html(obj.getMinHTML(hour)); $('#w2ui-overlay .w2ui-time') .on('mousedown', function () { $(this).css({ 'background-color': '#B6D5FB', 'border-color': '#aaa' }); var min = $(this).attr('min'); $(obj.el).val((hour > 12 && !h24 ? hour - 12 : hour) + ':' + (min < 10 ? 0 : '') + min + (!h24 ? (hour < 12 ? ' am' : ' pm') : '')).change(); }) .on('mouseup', function () { setTimeout(function () { if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay').removeData('keepOpen')[0].hide(); }, 10); }); }); } else { $('#w2ui-overlay .w2ui-time') .on('mouseup', function () { setTimeout(function () { if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay').removeData('keepOpen')[0].hide(); }, 10); }); } } // datetime if (this.type == 'datetime') { if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; // hide overlay if we are in the time selection if ($("#w2ui-overlay .w2ui-time").length > 0) $('#w2ui-overlay')[0].hide(); if ($('#w2ui-overlay').length === 0) { $(obj.el).w2overlay('
    ', { css: { "background-color": "#f5f5f5" } }); } var month, year; var dt = w2utils.isDateTime($(obj.el).val(), obj.options.format, true); if (dt) { month = dt.getMonth() + 1; year = dt.getFullYear(); } var selDate = null; (function refreshCalendar(month, year) { $('#w2ui-overlay > div > div').html( obj.getMonthHTML(month, year, $(obj.el).val()) + (options.btn_now ? '
    '+ w2utils.lang('Current Date & Time') + '
    ' : '') ); $('#w2ui-overlay .w2ui-calendar-title') .on('mousedown', function () { if ($(this).next().hasClass('w2ui-calendar-jump')) { $(this).next().remove(); } else { var selYear, selMonth; $(this).after('
    '); $(this).next().hide().html(obj.getYearHTML()).fadeIn(200); setTimeout(function () { $('#w2ui-overlay .w2ui-calendar-jump') .find('.w2ui-jump-month, .w2ui-jump-year') .on('click', function () { if ($(this).hasClass('w2ui-jump-month')) { $(this).parent().find('.w2ui-jump-month').removeClass('selected'); $(this).addClass('selected'); selMonth = $(this).attr('name'); } if ($(this).hasClass('w2ui-jump-year')) { $(this).parent().find('.w2ui-jump-year').removeClass('selected'); $(this).addClass('selected'); selYear = $(this).attr('name'); } if (selYear != null && selMonth != null) { $('#w2ui-overlay .w2ui-calendar-jump').fadeOut(100); setTimeout(function () { refreshCalendar(parseInt(selMonth)+1, selYear); }, 100); } }); $('#w2ui-overlay .w2ui-calendar-jump >:last-child').prop('scrollTop', 2000); }, 1); } }); $('#w2ui-overlay .w2ui-date') .on('mousedown', function () { var day = $(this).attr('date'); $(obj.el).val(day).change(); $(this).css({ 'background-color': '#B6D5FB', 'border-color': '#aaa' }); selDate = new Date($(this).attr('data-date')); }) .on('mouseup', function () { // continue with time picker var selHour, selMin; if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay')[0].hide(); $(obj.el).w2overlay('
    ', { css: { "background-color": "#fff" } }); $('#w2ui-overlay > div').html(obj.getHourHTML()); $('#w2ui-overlay .w2ui-time') .on('mousedown', function (event) { $(this).css({ 'background-color': '#B6D5FB', 'border-color': '#aaa' }); selHour = $(this).attr('hour'); selDate.setHours(selHour); var txt = w2utils.formatDateTime(selDate, obj.options.format); $(obj.el).val(txt).change(); //$(obj.el).val((hour > 12 && !h24 ? hour - 12 : hour) + ':00' + (!h24 ? (hour < 12 ? ' am' : ' pm') : '')).change(); }); if (obj.options.noMinutes == null || obj.options.noMinutes === false) { $('#w2ui-overlay .w2ui-time') .on('mouseup', function () { var hour = $(this).attr('hour'); if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay')[0].hide(); $(obj.el).w2overlay('
    ', { css: { "background-color": "#fff" } }); $('#w2ui-overlay > div').html(obj.getMinHTML(hour)); $('#w2ui-overlay .w2ui-time') .on('mousedown', function () { $(this).css({ 'background-color': '#B6D5FB', 'border-color': '#aaa' }); selMin = $(this).attr('min'); selDate.setHours(selHour, selMin); var txt = w2utils.formatDateTime(selDate, obj.options.format); $(obj.el).val(txt).change(); //$(obj.el).val((hour > 12 && !h24 ? hour - 12 : hour) + ':' + (min < 10 ? 0 : '') + min + (!h24 ? (hour < 12 ? ' am' : ' pm') : '')).change(); }) .on('mouseup', function () { setTimeout(function () { if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay').removeData('keepOpen')[0].hide(); }, 10); }); }); } else { $('#w2ui-overlay .w2ui-time') .on('mouseup', function () { setTimeout(function () { if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay').removeData('keepOpen')[0].hide(); }, 10); }); } }); $('#w2ui-overlay .previous').on('mousedown', function () { var tmp = obj.options.current.split('/'); tmp[0] = parseInt(tmp[0]) - 1; refreshCalendar(tmp[0], tmp[1]); }); $('#w2ui-overlay .next').on('mousedown', function () { var tmp = obj.options.current.split('/'); tmp[0] = parseInt(tmp[0]) + 1; refreshCalendar(tmp[0], tmp[1]); }); // "now" button $('#w2ui-overlay .now') .on('mousedown', function () { // this currently ignores blocked days or start / end dates! var tmp = w2utils.formatDateTime(new Date(), obj.options.format); $(obj.el).val(tmp).change(); return false; }) .on('mouseup', function () { setTimeout(function () { if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay').removeData('keepOpen')[0].hide(); }, 10); }); }) (month, year); } // list if (['list', 'combo', 'enum'].indexOf(this.type) != -1) { var el = this.el; var input = this.el; if (this.type == 'enum') { el = $(this.helpers.multi); input = $(el).find('input'); } if (this.type == 'list') { var sel = $(input).data('selected'); if ($.isPlainObject(sel) && !$.isEmptyObject(sel) && options.index == -1) { options.items.forEach(function (item, ind) { if (item.id == sel.id) { options.index = ind; } }); } input = $(this.helpers.focus).find('input'); } if ($(input).is(':focus')) { if (options.openOnFocus === false && $(input).val() === '' && obj.tmp.force_open !== true) { $().w2overlay(); return; } if (obj.tmp.force_hide) { $().w2overlay(); setTimeout(function () { delete obj.tmp.force_hide; }, 1); return; } if ($(input).val() !== '') delete obj.tmp.force_open; var msgNoItems = w2utils.lang('No matches'); if (options.url != null && $(input).val().length < options.minLength && obj.tmp.emptySet !== true) msgNoItems = options.minLength + ' ' + w2utils.lang('letters or more...'); if (options.url != null && $(input).val() === '' && obj.tmp.emptySet !== true) msgNoItems = w2utils.lang('Type to search...'); if (options.url == null && options.items.length === 0) msgNoItems = w2utils.lang('Empty list'); if (options.msgNoItems != null) msgNoItems = options.msgNoItems; if (msgNoItems == 'function') msgNoItems = msgNoItems(options); $(el).w2menu((!indexOnly ? 'refresh' : 'refresh-index'), $.extend(true, {}, options, { search : false, render : options.renderDrop, maxHeight : options.maxDropHeight, maxWidth : options.maxDropWidth, msgNoItems : msgNoItems, // selected with mouse onSelect: function (event) { if (obj.type == 'enum') { var selected = $(obj.el).data('selected'); if (event.item) { // trigger event var edata = obj.trigger({ phase: 'before', type: 'add', target: obj.el, originalEvent: event.originalEvent, item: event.item }); if (edata.isCancelled === true) return; // default behavior if (selected.length >= options.max && options.max > 0) selected.pop(); delete event.item.hidden; selected.push(event.item); $(obj.el).data('selected', selected).change(); $(obj.helpers.multi).find('input').val('').width(20); obj.refresh(); if ($("#w2ui-overlay").length > 0) $('#w2ui-overlay')[0].hide(); // event after obj.trigger($.extend(edata, { phase: 'after' })); } } else { $(obj.el).data('selected', event.item).val(event.item.text).change(); if (obj.helpers.focus) obj.helpers.focus.find('input').val(''); } } })); } } }, inRange: function (str, onlyDate) { var inRange = false; if (this.type == 'date') { var dt = w2utils.isDate(str, this.options.format, true); if (dt) { // enable range if (this.options.start || this.options.end) { var st = (typeof this.options.start == 'string' ? this.options.start : $(this.options.start).val()); var en = (typeof this.options.end == 'string' ? this.options.end : $(this.options.end).val()); var start = w2utils.isDate(st, this.options.format, true); var end = w2utils.isDate(en, this.options.format, true); var current = new Date(dt); if (!start) start = current; if (!end) end = current; if (current >= start && current <= end) inRange = true; } else { inRange = true; } // block predefined dates if (this.options.blocked && $.inArray(str, this.options.blocked) != -1) inRange = false; /* clockWeekDay - type: array or integers. every element - number of week day. number of weekday (1 - monday, 2 - tuesday, 3 - wensday, 4 - thursday, 5 - friday, 6 - saturday, 0 - sunday) for block in calendar (for example, block all sundays so user can't choose sunday in calendar) */ if (this.options.blockWeekDays != null && this.options.blockWeekDays != undefined && this.options.blockWeekDays.length != undefined){ var l = this.options.blockWeekDays.length; for (var i=0; i= tm1 && tm <= tm2) inRange = true; } else { inRange = true; } } else if (this.type == 'datetime') { var dt = w2utils.isDateTime(str, this.options.format, true); if (dt) { // enable range if (this.options.start || this.options.end) { var start, end; if (typeof this.options.start == 'object' && this.options.start instanceof Date) { start = this.options.start; } else { var st = (typeof this.options.start == 'string' ? this.options.start : $(this.options.start).val()); if (st.trim() !== '') { start = w2utils.isDateTime(st, this.options.format, true); } else { start = ''; } } if (typeof this.options.end == 'object' && this.options.end instanceof Date) { end = this.options.end; } else { var en = (typeof this.options.end == 'string' ? this.options.end : $(this.options.end).val()); if (en.trim() !== '') { end = w2utils.isDateTime(en, this.options.format, true); } else { end = ''; } } var current = dt; // new Date(dt); if (!start) start = current; if (!end) end = current; if (onlyDate && start instanceof Date) { start.setHours(0); start.setMinutes(0); start.setSeconds(0); } if (current >= start && current <= end) inRange = true; } else { inRange = true; } // block predefined dates if (inRange && this.options.blocked) { for (var i=0; i'+ obj.options.prefix + '' ); helper = $(obj.el).prev(); helper .css({ 'color' : $(obj.el).css('color'), 'font-family' : $(obj.el).css('font-family'), 'font-size' : $(obj.el).css('font-size'), 'padding-top' : $(obj.el).css('padding-top'), 'padding-bottom' : $(obj.el).css('padding-bottom'), 'padding-left' : $(obj.el).css('padding-left'), 'padding-right' : 0, 'margin-top' : (parseInt($(obj.el).css('margin-top'), 10) + 2) + 'px', 'margin-bottom' : (parseInt($(obj.el).css('margin-bottom'), 10) + 1) + 'px', 'margin-left' : $(obj.el).css('margin-left'), 'margin-right' : 0 }) .on('click', function (event) { if (obj.options.icon && typeof obj.onIconClick == 'function') { // event before var edata = obj.trigger({ phase: 'before', type: 'iconClick', target: obj.el, el: $(this).find('span.w2ui-icon')[0] }); if (edata.isCancelled === true) return; // intentionally empty // event after obj.trigger($.extend(edata, { phase: 'after' })); } else { if (obj.type == 'list') { $(obj.helpers.focus).find('input').focus(); } else { $(obj.el).focus(); } } }); $(obj.el).css('padding-left', (helper.width() + parseInt($(obj.el).css('padding-left'), 10)) + 'px'); // remember helper obj.helpers.prefix = helper; } }, 1); }, addSuffix: function () { var obj = this; var helper, pr; setTimeout(function () { if (obj.type === 'clear') return; var tmp = $(obj.el).data('tmp') || {}; if (tmp['old-padding-right']) $(obj.el).css('padding-right', tmp['old-padding-right']); tmp['old-padding-right'] = $(obj.el).css('padding-right'); $(obj.el).data('tmp', tmp); pr = parseInt($(obj.el).css('padding-right'), 10); if (obj.options.arrows) { // remove if already displayed if (obj.helpers.arrows) $(obj.helpers.arrows).remove(); // add fresh $(obj.el).after( '
     '+ '
    '+ '
    '+ '
    '+ '
    '+ '
    '+ '
    '+ '
    '); helper = $(obj.el).next(); helper.css({ 'color' : $(obj.el).css('color'), 'font-family' : $(obj.el).css('font-family'), 'font-size' : $(obj.el).css('font-size'), 'height' : ($(obj.el).height() + parseInt($(obj.el).css('padding-top'), 10) + parseInt($(obj.el).css('padding-bottom'), 10) ) + 'px', 'padding' : 0, 'margin-top' : (parseInt($(obj.el).css('margin-top'), 10) + 1) + 'px', 'margin-bottom' : 0, 'border-left' : '1px solid silver' }) .css('margin-left', '-'+ (helper.width() + parseInt($(obj.el).css('margin-right'), 10) + 12) + 'px') .on('mousedown', function (event) { var body = $('body'); body.on('mouseup', tmp); body.data('_field_update_timer', setTimeout(update, 700)); update(false); // timer function function tmp() { clearTimeout(body.data('_field_update_timer')); body.off('mouseup', tmp); } // update function function update(notimer) { $(obj.el).focus(); obj.keyDown($.Event("keydown"), { keyCode : ($(event.target).attr('type') == 'up' ? 38 : 40) }); if (notimer !== false) $('body').data('_field_update_timer', setTimeout(update, 60)); } }); pr += helper.width() + 12; $(obj.el).css('padding-right', pr + 'px'); // remember helper obj.helpers.arrows = helper; } if (obj.options.suffix !== '') { // remove if already displayed if (obj.helpers.suffix) $(obj.helpers.suffix).remove(); // add fresh $(obj.el).after( '
    '+ obj.options.suffix + '
    '); helper = $(obj.el).next(); helper .css({ 'color' : $(obj.el).css('color'), 'font-family' : $(obj.el).css('font-family'), 'font-size' : $(obj.el).css('font-size'), 'padding-top' : $(obj.el).css('padding-top'), 'padding-bottom' : $(obj.el).css('padding-bottom'), 'padding-left' : '3px', 'padding-right' : $(obj.el).css('padding-right'), 'margin-top' : (parseInt($(obj.el).css('margin-top'), 10) + 2) + 'px', 'margin-bottom' : (parseInt($(obj.el).css('margin-bottom'), 10) + 1) + 'px' }) .on('click', function (event) { if (obj.type == 'list') { $(obj.helpers.focus).find('input').focus(); } else { $(obj.el).focus(); } }); helper.css('margin-left', '-'+ (w2utils.getSize(helper, 'width') + parseInt($(obj.el).css('margin-right'), 10) + 2) + 'px'); pr += helper.width() + 3; $(obj.el).css('padding-right', pr + 'px'); // remember helper obj.helpers.suffix = helper; } }, 1); }, addFocus: function () { var obj = this; var options = this.options; var width = 0; // 11 - show search icon, 0 do not show var pholder; // clean up & init $(obj.helpers.focus).remove(); // remember original tabindex var tabIndex = $(obj.el).attr('tabIndex'); if (tabIndex && tabIndex != -1) obj.el._tabIndex = tabIndex; if (obj.el._tabIndex) tabIndex = obj.el._tabIndex; if (tabIndex == null) tabIndex = -1; // build helper var html = '
    '+ ' '+ ' '+ '
    '; $(obj.el).attr('tabindex', -1).before(html); var helper = $(obj.el).prev(); obj.helpers.focus = helper; helper.css({ width : $(obj.el).width(), "margin-top" : $(obj.el).css('margin-top'), "margin-left" : (parseInt($(obj.el).css('margin-left')) + parseInt($(obj.el).css('padding-left'))) + 'px', "margin-bottom" : $(obj.el).css('margin-bottom'), "margin-right" : $(obj.el).css('margin-right') }) .find('input') .css({ cursor : 'default', width : '100%', outline : 'none', opacity : 1, margin : 0, border : '1px solid transparent', padding : $(obj.el).css('padding-top'), "padding-left" : 0, "margin-left" : (width > 0 ? width + 6 : 0), "background-color" : 'transparent' }); // INPUT events helper.find('input') .on('click', function (event) { if ($('#w2ui-overlay').length === 0) obj.focus(event); event.stopPropagation(); }) .on('focus', function (event) { pholder = $(obj.el).attr('placeholder'); $(obj.el).css({ 'outline': 'auto 5px #7DB4F3', 'outline-offset': '-2px' }); $(this).val(''); $(obj.el).triggerHandler('focus'); if (event.stopPropagation) event.stopPropagation(); else event.cancelBubble = true; }) .on('blur', function (event) { $(obj.el).css('outline', 'none'); $(this).val(''); obj.refresh(); $(obj.el).triggerHandler('blur'); if (event.stopPropagation) event.stopPropagation(); else event.cancelBubble = true; if (pholder != null) $(obj.el).attr('placeholder', pholder); }) .on('keydown', function (event) { var el = this; obj.keyDown(event); setTimeout(function () { if (el.value === '') $(obj.el).attr('placeholder', pholder); else $(obj.el).attr('placeholder', ''); }, 10); }) .on('keyup', function (event) { obj.keyUp(event); }) .on('keypress', function (event) { obj.keyPress(event); }); // MAIN div helper.on('click', function (event) { $(this).find('input').focus(); }); obj.refresh(); }, addMulti: function () { var obj = this; var options = this.options; // clean up & init $(obj.helpers.multi).remove(); // build helper var html = ''; var margin = 'margin-top : 0px; ' + 'margin-bottom : 0px; ' + 'margin-left : ' + $(obj.el).css('margin-left') + '; ' + 'margin-right : ' + $(obj.el).css('margin-right') + '; '+ 'width : ' + (w2utils.getSize(obj.el, 'width') - parseInt($(obj.el).css('margin-left'), 10) - parseInt($(obj.el).css('margin-right'), 10)) + 'px;'; if (obj.type == 'enum') { // remember original tabindex var tabIndex = $(obj.el).attr('tabIndex'); if (tabIndex && tabIndex != -1) obj.el._tabIndex = tabIndex; if (obj.el._tabIndex) tabIndex = obj.el._tabIndex; if (tabIndex == null) tabIndex = -1; html = '
    '+ '
    '+ '
      '+ '
    • '+ ' '+ '
    • '+ '
    '+ '
    '+ '
    '; } if (obj.type == 'file') { html = '
    '+ '
    '+ ' '+ '
    '+ '
    '+ '
    '+ '
    '+ '
    '; } // old bg and border var tmp = $(obj.el).data('tmp') || {}; tmp['old-background-color'] = $(obj.el).css('background-color'); tmp['old-border-color'] = $(obj.el).css('border-color'); $(obj.el).data('tmp', tmp); $(obj.el) .before(html) .css({ 'background-color' : 'transparent', 'border-color' : 'transparent' }); var div = $(obj.el).prev(); obj.helpers.multi = div; if (obj.type == 'enum') { $(obj.el).attr('tabindex', -1); // INPUT events div.find('input') .on('click', function (event) { if ($('#w2ui-overlay').length === 0) obj.focus(event); $(obj.el).triggerHandler('click'); }) .on('focus', function (event) { $(div).css({ 'outline': 'auto 5px #7DB4F3', 'outline-offset': '-2px' }); $(obj.el).triggerHandler('focus'); if (event.stopPropagation) event.stopPropagation(); else event.cancelBubble = true; }) .on('blur', function (event) { $(div).css('outline', 'none'); $(obj.el).triggerHandler('blur'); if (event.stopPropagation) event.stopPropagation(); else event.cancelBubble = true; }) .on('keyup', function (event) { obj.keyUp(event); }) .on('keydown', function (event) { obj.keyDown(event); }) .on('keypress', function (event) { obj.keyPress(event); }); // MAIN div div.on('click', function (event) { $(this).find('input').focus(); }); } if (obj.type == 'file') { $(obj.el).css('outline', 'none'); div.on('click', function (event) { $(obj.el).focus(); if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; obj.blur(event); obj.resize(); setTimeout(function () { div.find('input').click(); }, 10); // needed this when clicked on items div }) .on('dragenter', function (event) { if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; $(div).addClass('w2ui-file-dragover'); }) .on('dragleave', function (event) { if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; var tmp = $(event.target).parents('.w2ui-field-helper'); if (tmp.length === 0) $(div).removeClass('w2ui-file-dragover'); }) .on('drop', function (event) { if ($(obj.el).prop('readonly') || $(obj.el).prop('disabled')) return; $(div).removeClass('w2ui-file-dragover'); var files = event.originalEvent.dataTransfer.files; for (var i = 0, l = files.length; i < l; i++) obj.addFile.call(obj, files[i]); // cancel to stop browser behaviour event.preventDefault(); event.stopPropagation(); }) .on('dragover', function (event) { // cancel to stop browser behaviour event.preventDefault(); event.stopPropagation(); }); div.find('input') .on('click', function (event) { event.stopPropagation(); }) .on('change', function () { if (typeof this.files !== "undefined") { for (var i = 0, l = this.files.length; i < l; i++) { obj.addFile.call(obj, this.files[i]); } } }); } obj.refresh(); }, addFile: function (file) { var obj = this; var options = this.options; var selected = $(obj.el).data('selected'); var newItem = { name : file.name, type : file.type, modified : file.lastModifiedDate, size : file.size, content : null, file : file }; var size = 0; var cnt = 0; var err; if (selected) { for (var s = 0; s < selected.length; s++) { // check for dups if (selected[s].name == file.name && selected[s].size == file.size) return; size += selected[s].size; cnt++; } } // trigger event var edata = obj.trigger({ phase: 'before', type: 'add', target: obj.el, file: newItem, total: cnt, totalSize: size }); if (edata.isCancelled === true) return; // check params if (options.maxFileSize !== 0 && newItem.size > options.maxFileSize) { err = 'Maximum file size is '+ w2utils.formatSize(options.maxFileSize); if (options.silent === false) $(obj.el).w2tag(err); console.log('ERROR: '+ err); return; } if (options.maxSize !== 0 && size + newItem.size > options.maxSize) { err = 'Maximum total size is '+ w2utils.formatSize(options.maxSize); if (options.silent === false) $(obj.el).w2tag(err); console.log('ERROR: '+ err); return; } if (options.max !== 0 && cnt >= options.max) { err = 'Maximum number of files is '+ options.max; if (options.silent === false) $(obj.el).w2tag(err); console.log('ERROR: '+ err); return; } selected.push(newItem); // read file as base64 if (typeof FileReader !== "undefined" && options.readContent === true) { var reader = new FileReader(); // need a closure reader.onload = (function () { return function (event) { var fl = event.target.result; var ind = fl.indexOf(','); newItem.content = fl.substr(ind+1); obj.refresh(); $(obj.el).trigger('change'); // event after obj.trigger($.extend(edata, { phase: 'after' })); }; })(); reader.readAsDataURL(file); } else { obj.refresh(); $(obj.el).trigger('change'); } }, normMenu: function (menu) { if ($.isArray(menu)) { for (var m = 0; m < menu.length; m++) { if (typeof menu[m] == 'string') { menu[m] = { id: menu[m], text: menu[m] }; } else { if (menu[m].text != null && menu[m].id == null) menu[m].id = menu[m].text; if (menu[m].text == null && menu[m].id != null) menu[m].text = menu[m].id; if (menu[m].caption != null) menu[m].text = menu[m].caption; } } return menu; } else if (typeof menu == 'function') { return this.normMenu(menu()); } else if (typeof menu == 'object') { var tmp = []; for (var m in menu) tmp.push({ id: m, text: menu[m] }); return tmp; } }, getMonthHTML: function (month, year, selected) { var td = new Date(); var months = w2utils.settings.fullmonths; var daysCount = ['31', '28', '31', '30', '31', '30', '31', '31', '30', '31', '30', '31']; var today = td.getFullYear() + '/' + (Number(td.getMonth()) + 1) + '/' + td.getDate(); var days = w2utils.settings.fulldays.slice(); // creates copy of the array var sdays = w2utils.settings.shortdays.slice(); // creates copy of the array if (w2utils.settings.weekStarts != 'M') { days.unshift(days.pop()); sdays.unshift(sdays.pop()); } var options = this.options; if (options == null) options = {}; // normalize date year = w2utils.isInt(year) ? parseInt(year) : td.getFullYear(); month = w2utils.isInt(month) ? parseInt(month) : td.getMonth() + 1; if (month > 12) { month -= 12; year++; } if (month < 1 || month === 0) { month += 12; year--; } if (year/4 == Math.floor(year/4)) { daysCount[1] = '29'; } else { daysCount[1] = '28'; } options.current = month + '/' + year; // start with the required date td = new Date(year, month-1, 1); var weekDay = td.getDay(); var dayTitle = ''; for (var i = 0; i < sdays.length; i++) dayTitle += '' + sdays[i] + ''; var html = '
    '+ ' '+ ' '+ months[month-1] +', '+ year + '
    '+ ''+ ' ' + dayTitle + ''+ ' '; var day = 1; if (w2utils.settings.weekStarts != 'M') weekDay++; if(this.type === 'datetime') { var dt_sel = w2utils.isDateTime(selected, options.format, true); selected = w2utils.formatDate(dt_sel, w2utils.settings.dateFormat); } for (var ci = 1; ci < 43; ci++) { if (weekDay === 0 && ci == 1) { for (var ti = 0; ti < 6; ti++) html += ''; ci += 6; } else { if (ci < weekDay || day > daysCount[month-1]) { html += ''; if ((ci) % 7 === 0) html += ''; continue; } } var dt = year + '/' + month + '/' + day; var DT = new Date(dt); var className = ''; if (DT.getDay() === 6) className = ' w2ui-saturday'; if (DT.getDay() === 0) className = ' w2ui-sunday'; if (dt == today) className += ' w2ui-today'; var dspDay = day; var col = ''; var bgcol = ''; var tmp_dt, tmp_dt_fmt; if(this.type === 'datetime') { // var fm = options.format.split('|')[0].trim(); // tmp_dt = w2utils.formatDate(dt, fm); tmp_dt = w2utils.formatDateTime(dt, options.format); tmp_dt_fmt = w2utils.formatDate(dt, w2utils.settings.dateFormat); } else { tmp_dt = w2utils.formatDate(dt, options.format); tmp_dt_fmt = tmp_dt; } if (options.colored && options.colored[tmp_dt_fmt] !== undefined) { // if there is predefined colors for dates var tmp = options.colored[tmp_dt_fmt].split(':'); bgcol = 'background-color: ' + tmp[0] + ';'; col = 'color: ' + tmp[1] + ';'; } html += ''; if (ci % 7 === 0 || (weekDay === 0 && ci == 1)) html += ''; day++; } html += '
      
    '+ dspDay + '
    '; return html; }, getYearHTML: function () { var months = w2utils.settings.shortmonths; var start_year = w2utils.settings.dateStartYear; var end_year = w2utils.settings.dateEndYear; var mhtml = ''; var yhtml = ''; for (var m = 0; m < months.length; m++) { mhtml += '
    '+ months[m] + '
    '; } for (var y = start_year; y <= end_year; y++) { yhtml += '
    '+ y + '
    '; } return '
    '+ mhtml +'
    '+ yhtml +'
    '; }, getHourHTML: function () { var tmp = []; var options = this.options; if (options == null) options = { format: w2utils.settings.timeFormat }; var h24 = (options.format.indexOf('h24') > -1); for (var a = 0; a < 24; a++) { var time = (a >= 12 && !h24 ? a - 12 : a) + ':00' + (!h24 ? (a < 12 ? ' am' : ' pm') : ''); if (a == 12 && !h24) time = '12:00 pm'; if (!tmp[Math.floor(a/8)]) tmp[Math.floor(a/8)] = ''; var tm1 = this.fromMin(this.toMin(time)); var tm2 = this.fromMin(this.toMin(time) + 59); if (this.type === 'datetime') { var dt = w2utils.isDateTime(this.el.value, options.format, true); var fm = options.format.split('|')[0].trim(); tm1 = w2utils.formatDate(dt, fm) + ' ' + tm1; tm2 = w2utils.formatDate(dt, fm) + ' ' + tm2; } tmp[Math.floor(a/8)] += '
    '+ time +'
    '; } var html = '
    '+ '
    '+ w2utils.lang('Select Hour') +'
    '+ '
    '+ ' ' + ' ' + ' ' + '
    '+ tmp[0] +''+ tmp[1] +''+ tmp[2] +'
    '+ '
    '; return html; }, getMinHTML: function (hour) { if (hour == null) hour = 0; var options = this.options; if (options == null) options = { format: w2utils.settings.timeFormat }; var h24 = (options.format.indexOf('h24') > -1); var tmp = []; for (var a = 0; a < 60; a += 5) { var time = (hour > 12 && !h24 ? hour - 12 : hour) + ':' + (a < 10 ? 0 : '') + a + ' ' + (!h24 ? (hour < 12 ? 'am' : 'pm') : ''); var tm = time; var ind = a < 20 ? 0 : (a < 40 ? 1 : 2); if (!tmp[ind]) tmp[ind] = ''; if (this.type === 'datetime') { var dt = w2utils.isDateTime(this.el.value, options.format, true); var fm = options.format.split('|')[0].trim(); tm = w2utils.formatDate(dt, fm) + ' ' + tm; } tmp[ind] += '
    '+ time +'
    '; } var html = '
    '+ '
    '+ w2utils.lang('Select Minute') +'
    '+ '
    '+ ' ' + ' ' + ' ' + '
    '+ tmp[0] +''+ tmp[1] +''+ tmp[2] +'
    '+ '
    '; return html; }, toMin: function (str) { if (typeof str != 'string') return null; var tmp = str.split(':'); if (tmp.length === 2) { tmp[0] = parseInt(tmp[0]); tmp[1] = parseInt(tmp[1]); if (str.indexOf('pm') != -1 && tmp[0] != 12) tmp[0] += 12; } else { return null; } return tmp[0] * 60 + tmp[1]; }, fromMin: function (time) { var ret = ''; if (time >= 24 * 60) time = time % (24 * 60); if (time < 0) time = 24 * 60 + time; var hour = Math.floor(time/60); var min = ((time % 60) < 10 ? '0' : '') + (time % 60); var options = this.options; if (options == null) options = { format: w2utils.settings.timeFormat }; if (options.format.indexOf('h24') != -1) { ret = hour + ':' + min; } else { ret = (hour <= 12 ? hour : hour - 12) + ':' + min + ' ' + (hour >= 12 ? 'pm' : 'am'); } return ret; } }; $.extend(w2field.prototype, w2utils.event); w2obj.field = w2field; }) (jQuery); /************************************************************************ * Library: Web 2.0 UI for jQuery (using prototypical inheritance) * - Following objects defined * - w2toolbar - toolbar widget * - $().w2toolbar - jQuery wrapper * - Dependencies: jQuery, w2utils, w2field * * == NICE TO HAVE == * - vertical toolbar * ************************************************************************/ (function ($) { var w2toolbar = function (options) { this.box = null; // DOM Element that holds the element this.name = null; // unique name for w2ui this.routeData = {}; // data for dynamic routes this.items = []; this.right = ''; // HTML text on the right of toolbar this.tooltip = 'top|left';// can be top, bottom, left, right $.extend(true, this, w2obj.toolbar, options); }; // ==================================================== // -- Registers as a jQuery plugin $.fn.w2toolbar = function(method) { if ($.isPlainObject(method)) { // check name parameter if (!w2utils.checkName(method, 'w2toolbar')) return; // extend items var items = method.items || []; var object = new w2toolbar(method); $.extend(object, { items: [], handlers: [] }); for (var i = 0; i < items.length; i++) { object.items[i] = $.extend({}, w2toolbar.prototype.item, items[i]); // menus if (object.items[i].type == 'menu-check') { var item = object.items[i]; if (!Array.isArray(item.selected)) item.selected = []; if (Array.isArray(item.items)) { for (var j = 0; j < item.items.length; j++) { var it = item.items[j]; if (it.checked && item.selected.indexOf(it.id) == -1) item.selected.push(it.id); if (!it.checked && item.selected.indexOf(it.id) != -1) it.checked = true; if (it.checked == null) it.checked = false; } } } else if (object.items[i].type == 'menu-radio') { var item = object.items[i]; if (Array.isArray(item.items)) { for (var j = 0; j < item.items.length; j++) { var it = item.items[j]; if (it.checked && item.selected == null) item.selected = it.id; else it.checked = false; if (!it.checked && item.selected == it.id) it.checked = true; if (it.checked == null) it.checked = false; } } } } if ($(this).length !== 0) { object.render($(this)[0]); } // register new object w2ui[object.name] = object; return object; } else { var obj = w2ui[$(this).attr('name')]; if (!obj) return null; if (arguments.length > 0) { if (obj[method]) obj[method].apply(obj, Array.prototype.slice.call(arguments, 1)); return this; } else { return obj; } } }; // ==================================================== // -- Implementation of core functionality w2toolbar.prototype = { onClick : null, onRender : null, onRefresh : null, onResize : null, onDestroy : null, item: { id : null, // command to be sent to all event handlers type : 'button', // button, check, radio, drop, menu, menu-radio, menu-check, break, html, spacer text : null, html : '', tooltip : null, // w2toolbar.tooltip should be count : null, hidden : false, disabled : false, checked : false, // used for radio buttons img : null, icon : null, route : null, // if not null, it is route to go arrow : true, // arrow down for drop/menu types style : null, // extre css style for caption color : null, // color value - used in color pickers transparent : null, // transparent t/f - used in color pickers group : null, // used for radio buttons items : null, // for type menu* it is an array of items in the menu selected : null, // used for menu-check, menu-radio overlay : {}, onClick : null, onRefresh : null }, add: function (items) { this.insert(null, items); }, insert: function (id, items) { if (!$.isArray(items)) items = [items]; for (var o = 0; o < items.length; o++) { // checks if (items[o].type == null) { console.log('ERROR: The parameter "type" is required but not supplied in w2toolbar.add() method.'); return; } if ($.inArray(String(items[o].type), ['button', 'check', 'radio', 'drop', 'menu', 'menu-radio', 'menu-check', 'color', 'text-color', 'break', 'html', 'spacer']) == -1) { console.log('ERROR: The parameter "type" should be one of the following [button, check, radio, drop, menu, break, html, spacer] '+ 'in w2toolbar.add() method.'); return; } if (items[o].id == null && items[o].type != 'break' && items[o].type != 'spacer') { console.log('ERROR: The parameter "id" is required but not supplied in w2toolbar.add() method.'); return; } if (!w2utils.checkUniqueId(items[o].id, this.items, 'toolbar items', this.name)) return; // add item var it = $.extend({}, w2toolbar.prototype.item, items[o]); if (id == null) { this.items.push(it); } else { var middle = this.get(id, true); this.items = this.items.slice(0, middle).concat([it], this.items.slice(middle)); } this.refresh(it.id); this.resize(); } }, remove: function () { var removed = 0; for (var a = 0; a < arguments.length; a++) { var it = this.get(arguments[a]); if (!it || String(arguments[a]).indexOf(':') != -1) continue; removed++; // remove from screen $(this.box).find('#tb_'+ this.name +'_item_'+ w2utils.escapeId(it.id)).remove(); // remove from array var ind = this.get(it.id, true); if (ind != null) this.items.splice(ind, 1); } this.resize(); return removed; }, set: function (id, newOptions) { var item = this.get(id); if (item == null) return false; $.extend(item, newOptions); this.refresh(String(id).split(':')[0]); return true; }, get: function (id, returnIndex) { if (arguments.length === 0) { var all = []; for (var i1 = 0; i1 < this.items.length; i1++) if (this.items[i1].id != null) all.push(this.items[i1].id); return all; } var tmp = String(id).split(':'); for (var i2 = 0; i2 < this.items.length; i2++) { var it = this.items[i2]; // find a menu item if (['menu', 'menu-radio', 'menu-check'].indexOf(it.type) != -1 && tmp.length == 2 && it.id == tmp[0]) { for (var i = 0; i < it.items.length; i++) { var item = it.items[i]; if (item.id == tmp[1] || (item.id == null && item.text == tmp[1])) { if (returnIndex == true) return i; else return item; } } } else if (it.id == tmp[0]) { if (returnIndex == true) return i2; else return it; } } return null; }, show: function () { var obj = this; var items = 0; var tmp = []; for (var a = 0; a < arguments.length; a++) { var it = this.get(arguments[a]); if (!it) continue; items++; it.hidden = false; tmp.push(String(arguments[a]).split(':')[0]); } setTimeout(function () { for (var t=0; t 1) { var subItem = this.get(id); if (subItem && !subItem.disabled) { obj.menuClick({ name: obj.name, item: it, subItem: subItem, originalEvent: event }); } return; } if (it && !it.disabled) { // event before var edata = this.trigger({ phase: 'before', type: 'click', target: (id != null ? id : this.name), item: it, object: it, originalEvent: event }); if (tmp[0] === 'zoomin' || tmp[0] === 'zoomout') { return; } if (edata.isCancelled === true) return; var btn = '#tb_'+ this.name +'_item_'+ w2utils.escapeId(it.id) +' table.w2ui-button'; $(btn).removeClass('down'); // need to requery at the moment -- as well as elsewhere in this function if (it.type == 'radio') { for (var i = 0; i < this.items.length; i++) { var itt = this.items[i]; if (itt == null || itt.id == it.id || itt.type !== 'radio') continue; if (itt.group == it.group && itt.checked) { itt.checked = false; this.refresh(itt.id); } } it.checked = true; $(btn).addClass('checked'); } if (['menu', 'menu-radio', 'menu-check', 'drop', 'color', 'text-color'].indexOf(it.type) != -1) { obj.tooltipHide(id); if (it.checked) { // if it was already checked, second click will hide it setTimeout(function () { // hide overlay var el = $('#tb_'+ obj.name +'_item_'+ w2utils.escapeId(it.id)); el.w2overlay({ name: obj.name }); // uncheck it.checked = false; obj.refresh(it.id); }, 1); } else { // show overlay setTimeout(function () { var el = $('#tb_'+ obj.name +'_item_'+ w2utils.escapeId(it.id)); if (!$.isPlainObject(it.overlay)) it.overlay = {}; var left = (el.width() - 50) / 2; if (left > 19) left = 19; if (it.type == 'drop') { el.w2overlay(it.html, $.extend({ name: obj.name, left: left, top: 3 }, it.overlay, { onHide: function (event) { hideDrop(); } })); } if (['menu', 'menu-radio', 'menu-check'].indexOf(it.type) != -1) { var menuType = 'normal'; if (it.type == 'menu-radio') { menuType = 'radio'; it.items.forEach(function (item) { if (it.selected == item.id) item.checked = true; else item.checked = false; }); } if (it.type == 'menu-check') { menuType = 'check'; it.items.forEach(function (item) { if ($.isArray(it.selected) && it.selected.indexOf(item.id) != -1) item.checked = true; else item.checked = false; }); } el.w2menu($.extend({ name: obj.name, items: it.items, left: left, top: 3 }, it.overlay, { type: menuType, select: function (event) { obj.menuClick({ name: obj.name, item: it, subItem: event.item, originalEvent: event.originalEvent, keepOpen: event.keepOpen }); }, onHide: function (event) { hideDrop(); } })); } if (['color', 'text-color'].indexOf(it.type) != -1) { if (it.transparent == null) it.transparent = true; $(el).w2color({ color: it.color, transparent: it.transparent }, function (color, themeData) { if (color != null) { obj.colorClick({ name: obj.name, item: it, color: color, themeData: themeData, originalEvent: event.originalEvent }); } hideDrop(); }); } function hideDrop(event) { it.checked = false; $(btn).removeClass('checked'); } }, 1); } } if (['check', 'menu', 'menu-radio', 'menu-check', 'drop', 'color', 'text-color'].indexOf(it.type) != -1) { it.checked = !it.checked; if (it.checked) { $(btn).addClass('checked'); } else { $(btn).removeClass('checked'); } } // route processing if (it.route) { var route = String('/'+ it.route).replace(/\/{2,}/g, '/'); var info = w2utils.parseRoute(route); if (info.keys.length > 0) { for (var k = 0; k < info.keys.length; k++) { route = route.replace((new RegExp(':'+ info.keys[k].name, 'g')), this.routeData[info.keys[k].name]); } } setTimeout(function () { window.location.hash = route; }, 1); } if (event && ['button', 'check', 'radio'].indexOf(it.type) != -1) { // need to refresh toolbar as it might be dynamic this.tooltipShow(id, event, true); } // event after this.trigger($.extend(edata, { phase: 'after' })); } }, scroll: function (direction) { var box = $(this.box); var obj = this; var scrollBox = box.find('.w2ui-scroll-wrapper'); var scrollLeft = scrollBox.scrollLeft(); var width1, width2, scroll; switch (direction) { case 'left': width1 = scrollBox.outerWidth(); width2 = scrollBox.find(':first').outerWidth(); scroll = scrollLeft - width1 + 50; // 35 is width of both button if (scroll <= 0) scroll = 0; scrollBox.animate({ scrollLeft: scroll }, 300); break; case 'right': width1 = scrollBox.outerWidth(); width2 = scrollBox.find(':first').outerWidth(); scroll = scrollLeft + width1 - 50; // 35 is width of both button if (scroll >= width2 - width1) scroll = width2 - width1; scrollBox.animate({ scrollLeft: scroll }, 300); break; } setTimeout(function () { obj.resize(); }, 350); }, render: function (box) { var time = (new Date()).getTime(); // event before var edata = this.trigger({ phase: 'before', type: 'render', target: this.name, box: box }); if (edata.isCancelled === true) return; if (box != null) { if ($(this.box).find('> table #tb_'+ this.name + '_right').length > 0) { $(this.box) .removeAttr('name') .removeClass('w2ui-reset w2ui-toolbar') .html(''); } this.box = box; } if (!this.box) return; // render all buttons var html = '
    '+ ''+ ''; for (var i = 0; i < this.items.length; i++) { var it = this.items[i]; if (it == null) continue; if (it.id == null) it.id = "item_" + i; if (it.type == 'spacer') { html += ''; } else { html += ''; } } html += ''; html += ''+ '
    ' ''+ this.right +'
    '+ '
    '+ '
    '; $(this.box) .attr('name', this.name) .addClass('w2ui-reset w2ui-toolbar') .html(html); if ($(this.box).length > 0) $(this.box)[0].style.cssText += this.style; // refresh all this.refresh(); this.resize(); // event after this.trigger($.extend(edata, { phase: 'after' })); return (new Date()).getTime() - time; }, refresh: function (id) { var time = (new Date()).getTime(); // event before var edata = this.trigger({ phase: 'before', type: 'refresh', target: (id != null ? id : this.name), item: this.get(id) }); if (edata.isCancelled === true) return; // refresh all if (id == null) { for (var i = 0; i < this.items.length; i++) { var it1 = this.items[i]; if (it1.id == null) it1.id = "item_" + i; this.refresh(it1.id); } return; } // create or refresh only one item var it = this.get(id); if (it == null) return false; if (typeof it.onRefresh == 'function') { var edata2 = this.trigger({ phase: 'before', type: 'refresh', target: id, item: it, object: it }); if (edata2.isCancelled === true) return; } var el = $(this.box).find('#tb_'+ this.name +'_item_'+ w2utils.escapeId(it.id)); var html = this.getItemHTML(it); if (el.length === 0) { // does not exist - create it if (it.type == 'spacer') { html = ''; } else { html = '' + html + ''; } if (this.get(id, true) == this.items.length-1) { $(this.box).find('#tb_'+ this.name +'_right').before(html); } else { $(this.box).find('#tb_'+ this.name +'_item_'+ w2utils.escapeId(this.items[parseInt(this.get(id, true))+1].id)).before(html); } } else { if (['menu', 'menu-radio', 'menu-check', 'drop', 'color', 'text-color'].indexOf(it.type) != -1 && it.checked == false) { if ($('#w2ui-overlay-'+ this.name).length > 0) $('#w2ui-overlay-'+ this.name)[0].hide(); } // refresh el.html(html); if (it.hidden) { el.css('display', 'none'); } else { el.css('display', ''); } if (it.disabled) { el.addClass('disabled'); } else { el.removeClass('disabled'); } } // event after if (typeof it.onRefresh == 'function') { this.trigger($.extend(edata2, { phase: 'after' })); } this.trigger($.extend(edata, { phase: 'after' })); return (new Date()).getTime() - time; }, resize: function () { var time = (new Date()).getTime(); // event before var edata = this.trigger({ phase: 'before', type: 'resize', target: this.name }); if (edata.isCancelled === true) return; // show hide overflow buttons var box = $(this.box); box.find('.w2ui-scroll-left, .w2ui-scroll-right').hide(); var scrollBox = box.find('.w2ui-scroll-wrapper'); if (scrollBox.find(':first').outerWidth() > scrollBox.outerWidth()) { // we have overflowed content if (scrollBox.scrollLeft() > 0) { box.find('.w2ui-scroll-left').show(); } // Allow for rounding errors (on mobile, the max scrollLeft we get is 0.5 less than the real max). if (scrollBox.scrollLeft() < scrollBox.find(':first').outerWidth() - scrollBox.outerWidth() - 1) { box.find('.w2ui-scroll-right').show(); } } if (window.mode.isMobile()) { $('#toolbar-wrapper.mobile .w2ui-scroll-right, #toolbar-wrapper.mobile .w2ui-scroll-left').hide(); } // event after this.trigger($.extend(edata, { phase: 'after' })); return (new Date()).getTime() - time; }, destroy: function () { // event before var edata = this.trigger({ phase: 'before', type: 'destroy', target: this.name }); if (edata.isCancelled === true) return; // clean up if ($(this.box).find('> table #tb_'+ this.name + '_right').length > 0) { $(this.box) .removeAttr('name') .removeClass('w2ui-reset w2ui-toolbar') .html(''); } $(this.box).html(''); delete w2ui[this.name]; // event after this.trigger($.extend(edata, { phase: 'after' })); }, // ======================================== // --- Internal Functions getItemHTML: function (item) { var html = ''; if (item.caption != null && item.text == null) item.text = item.caption; // for backward compatibility if (item.text == null) item.text = ''; if (item.tooltip == null) item.tooltip = ''; var img = ' '; var text = item.text; if (typeof text == 'function') text = text.call(this, item); if (item.img) { // color indicator container for classic mode var colorContainer = '
    '; /** * @css class="textcolor" used in: * - Writer, Calc, Impress, Draw * - as "Font Color" * * @css class="backcolor" used in: * - Writer, Impress, Draw * - as "Character Highlighting Color" * * @css class="backgroundcolor" used in: * - Calc * - as "Background Color" * - (on mobile Calc uses "backcolor") * * It would be appropriate to place color indicator to below * of those classes' container. * * We have to filter where to add the color indicator, * otherwise it will be added to below of each toolbar * elements. */ img = (item.img == 'textcolor' || item.img == 'backcolor' || item.img == 'backgroundcolor') ? '
    ' + colorContainer + '' : '
    '; } if (item.icon) img = '
    '; if (html === '') switch (item.type) { case 'color': case 'text-color': if (typeof item.color == 'string' && item.color.substr(0,1) == '#') item.color = item.color.substr(1); /* if (item.type == 'color') { text = '
    '+ (item.text ? '
    ' + w2utils.lang(item.text) + '
    ' : ''); } */ /*if (item.type == 'text-color') { text = '
    '+ (item.text ? w2utils.lang(item.text) : 'Aa') + '
    '; }*/ case 'menu': case 'menu-check': case 'menu-radio': case 'button': case 'check': case 'radio': case 'drop': html += ''+ '
    '+ ' '+ ' ' + img + (text !== '' ? '' : '' ) + (item.count != null ? '' : '' ) + (((['menu', 'menu-radio', 'menu-check', 'drop'].indexOf(item.type) != -1) && item.arrow !== false) ? '' : '') + '
    '+ w2utils.lang(text) +''+ item.count +'
    '+ '
    '; break; case 'break': html += ''+ ' '+ '
     
    '; break; case 'html': html += ''+ ' '+ '
    ' + (typeof item.html == 'function' ? item.html.call(this, item) : item.html) + '
    '; break; } return '
    ' + html + '
    '; }, tooltipShow: function (id, event, forceRefresh) { if (window.mode.isMobile() || window.mode.isTablet()) { return; } if (window.ThisIsTheiOSApp) return; if (this.tooltip == null) return; var $el = $(this.box).find('#tb_'+ this.name + '_item_'+ w2utils.escapeId(id)); var item = this.get(id); var pos = this.tooltip; var txt = item.tooltip; if (typeof txt == 'function') txt = txt.call(this, item); $el.prop('_mouse_over', true); setTimeout(function () { if ($el.prop('_mouse_over') === true && $el.prop('_mouse_tooltip') !== true) { $el.prop('_mouse_tooltip', true); // show tooltip if (['menu', 'menu-radio', 'menu-check', 'drop', 'color', 'text-color'].indexOf(item.type) != -1 && item.checked == true) return; // not for opened drop downs $el.w2tag(w2utils.lang(txt), { position: pos }); } if (forceRefresh == true) { $el.w2tag(w2utils.lang(txt), { position: pos }); } }, 1); }, tooltipHide: function (id, event) { if (window.ThisIsTheiOSApp) return; if (this.tooltip == null) return; var $el = $(this.box).find('#tb_'+ this.name + '_item_'+ w2utils.escapeId(id)); $el.removeProp('_mouse_over'); setTimeout(function () { if ($el.prop('_mouse_over') !== true && $el.prop('_mouse_tooltip') === true) { $el.removeProp('_mouse_tooltip'); // hide tooltip $el.w2tag(); } }, 1); }, menuClick: function (event) { var obj = this; if (event.item && !event.item.disabled) { // event before var edata = this.trigger({ phase: 'before', type: 'click', target: event.item.id + ':' + event.subItem.id, item: event.item, subItem: event.subItem, originalEvent: event.originalEvent }); if (edata.isCancelled === true) return; // route processing var it = event.subItem; var item = this.get(event.item.id); if (item.type == 'menu-radio') { item.selected = it.id; event.item.items.forEach(function (item) { item.checked = false; }); it.checked = true; } if (item.type == 'menu-check') { if (!$.isArray(item.selected)) item.selected = []; var ind = item.selected.indexOf(it.id); if (ind == -1) { item.selected.push(it.id); it.checked = true; } else { item.selected.splice(ind, 1); it.checked = false; } } if (typeof it.route == 'string') { var route = it.route !== '' ? String('/'+ it.route).replace(/\/{2,}/g, '/') : ''; var info = w2utils.parseRoute(route); if (info.keys.length > 0) { for (var k = 0; k < info.keys.length; k++) { if (obj.routeData[info.keys[k].name] == null) continue; route = route.replace((new RegExp(':'+ info.keys[k].name, 'g')), this.routeData[info.keys[k].name]); } } setTimeout(function () { window.location.hash = route; }, 1); } this.refresh(event.item.id); // event after this.trigger($.extend(edata, { phase: 'after' })); } }, colorClick: function (event) { var obj = this; if (event.item && !event.item.disabled) { // event before var edata = this.trigger({ phase: 'before', type: 'click', target: event.item.id, item: event.item, color: event.color, themeData: event.themeData, originalEvent: event.originalEvent }); if (edata.isCancelled === true) return; // default behavior event.item.color = event.color; obj.refresh(event.item.id); // event after this.trigger($.extend(edata, { phase: 'after' })); } }, }; $.extend(w2toolbar.prototype, w2utils.event); w2obj.toolbar = w2toolbar; })(jQuery);