PageRenderTime 32ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/files/w2ui/1.3.0/w2ui.js

https://gitlab.com/Mirros/jsdelivr
JavaScript | 1330 lines | 1080 code | 114 blank | 136 comment | 420 complexity | 870d05bc0657ff55df2ec8a0619ff07b MD5 | raw file
  1. /* w2ui 1.3 (c) http://w2ui.com, vitmalina@gmail.com */
  2. var w2ui = w2ui || {};
  3. var w2obj = w2obj || {}; // expose object to be able to overwrite default functions
  4. /************************************************
  5. * Library: Web 2.0 UI for jQuery
  6. * - Following objects are defines
  7. * - w2ui - object that will contain all widgets
  8. * - w2obj - object with widget prototypes
  9. * - w2utils - basic utilities
  10. * - $().w2render - common render
  11. * - $().w2destroy - common destroy
  12. * - $().w2marker - marker plugin
  13. * - $().w2tag - tag plugin
  14. * - $().w2overlay - overlay plugin
  15. * - $().w2menu - menu plugin
  16. * - w2utils.event - generic event object
  17. * - w2utils.keyboard - object for keyboard navigation
  18. * - Dependencies: jQuery
  19. *
  20. * == NICE TO HAVE ==
  21. * - date has problems in FF new Date('yyyy-mm-dd') breaks
  22. * - bug: w2utils.formatDate('2011-31-01', 'yyyy-dd-mm'); - wrong foratter
  23. * - overlay should be displayed where more space (on top or on bottom)
  24. * - write and article how to replace certain framework functions
  25. * - format date and time is buggy
  26. * - onComplete should pass widget as context (this)
  27. *
  28. ************************************************/
  29. var w2utils = (function () {
  30. var tmp = {}; // for some temp variables
  31. var obj = {
  32. settings : {
  33. "locale" : "en-us",
  34. "date_format" : "m/d/yyyy",
  35. "date_display" : "Mon d, yyyy",
  36. "time_format" : "hh:mi pm",
  37. "currency" : "^[\$\€\£\¥]?[-]?[0-9]*[\.]?[0-9]+$",
  38. "currencySymbol": "$",
  39. "float" : "^[-]?[0-9]*[\.]?[0-9]+$",
  40. "shortmonths" : ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
  41. "fullmonths" : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
  42. "shortdays" : ["M", "T", "W", "T", "F", "S", "S"],
  43. "fulldays" : ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
  44. "RESTfull" : false,
  45. "phrases" : {} // empty object for english phrases
  46. },
  47. isInt : isInt,
  48. isFloat : isFloat,
  49. isMoney : isMoney,
  50. isHex : isHex,
  51. isAlphaNumeric : isAlphaNumeric,
  52. isEmail : isEmail,
  53. isDate : isDate,
  54. isTime : isTime,
  55. age : age,
  56. date : date,
  57. size : size,
  58. formatNumber : formatNumber,
  59. formatDate : formatDate,
  60. formatTime : formatTime,
  61. formatDateTime : formatDateTime,
  62. stripTags : stripTags,
  63. encodeTags : encodeTags,
  64. escapeId : escapeId,
  65. base64encode : base64encode,
  66. base64decode : base64decode,
  67. transition : transition,
  68. lock : lock,
  69. unlock : unlock,
  70. lang : lang,
  71. locale : locale,
  72. getSize : getSize,
  73. scrollBarSize : scrollBarSize
  74. }
  75. return obj;
  76. function isInt (val) {
  77. var re = /^[-]?[0-9]+$/;
  78. return re.test(val);
  79. }
  80. function isFloat (val) {
  81. var re = new RegExp(w2utils.settings["float"]);
  82. return re.test(val);
  83. }
  84. function isMoney (val) {
  85. var re = new RegExp(w2utils.settings.currency);
  86. return re.test(val);
  87. }
  88. function isHex (val) {
  89. var re = /^[a-fA-F0-9]+$/;
  90. return re.test(val);
  91. }
  92. function isAlphaNumeric (val) {
  93. var re = /^[a-zA-Z0-9_-]+$/;
  94. return re.test(val);
  95. }
  96. function isEmail (val) {
  97. var email = /^[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
  98. return email.test(val);
  99. }
  100. function isDate (val, format, retDate) {
  101. if (!val) return false;
  102. if (!format) format = w2utils.settings.date_format;
  103. // format date
  104. var tmp = val.replace(/-/g, '/').replace(/\./g, '/').toLowerCase().split('/');
  105. var tmp2 = format.replace(/-/g, '/').replace(/\./g, '/').toLowerCase();
  106. var dt = 'Invalid Date';
  107. var month, day, year;
  108. if (tmp2 == 'mm/dd/yyyy') { month = tmp[0]; day = tmp[1]; year = tmp[2]; }
  109. if (tmp2 == 'm/d/yyyy') { month = tmp[0]; day = tmp[1]; year = tmp[2]; }
  110. if (tmp2 == 'dd/mm/yyyy') { month = tmp[1]; day = tmp[0]; year = tmp[2]; }
  111. if (tmp2 == 'd/m/yyyy') { month = tmp[1]; day = tmp[0]; year = tmp[2]; }
  112. if (tmp2 == 'yyyy/dd/mm') { month = tmp[2]; day = tmp[1]; year = tmp[0]; }
  113. if (tmp2 == 'yyyy/d/m') { month = tmp[2]; day = tmp[1]; year = tmp[0]; }
  114. if (tmp2 == 'yyyy/mm/dd') { month = tmp[1]; day = tmp[2]; year = tmp[0]; }
  115. if (tmp2 == 'yyyy/m/d') { month = tmp[1]; day = tmp[2]; year = tmp[0]; }
  116. dt = new Date(month + '/' + day + '/' + year);
  117. // do checks
  118. if (typeof month == 'undefined') return false;
  119. if (dt == 'Invalid Date') return false;
  120. if ((dt.getMonth()+1 != month) || (dt.getDate() != day) || (dt.getFullYear() != year)) return false;
  121. if (retDate === true) return dt; else return true;
  122. }
  123. function isTime (val) {
  124. // Both formats 10:20pm and 22:20
  125. if (String(val) == 'undefined') return false;
  126. var max;
  127. // -- process american foramt
  128. val = val.toUpperCase();
  129. if (val.indexOf('PM') >= 0 || val.indexOf('AM') >= 0) max = 12; else max = 23;
  130. val = $.trim(val.replace('AM', ''));
  131. val = $.trim(val.replace('PM', ''));
  132. // ---
  133. var tmp = val.split(':');
  134. if (tmp.length != 2) { return false; }
  135. if (tmp[0] == '' || parseInt(tmp[0]) < 0 || parseInt(tmp[0]) > max || !this.isInt(tmp[0])) { return false; }
  136. if (tmp[1] == '' || parseInt(tmp[1]) < 0 || parseInt(tmp[1]) > 59 || !this.isInt(tmp[1])) { return false; }
  137. return true;
  138. }
  139. function age (timeStr) {
  140. if (timeStr == '' || typeof timeStr == 'undefined' || timeStr == null) return '';
  141. if (w2utils.isInt(timeStr)) timeStr = Number(timeStr); // for unix timestamps
  142. var d1 = new Date(timeStr);
  143. if (w2utils.isInt(timeStr)) d1 = new Date(Number(timeStr)); // for unix timestamps
  144. var tmp = String(timeStr).split('-');
  145. if (tmp.length == 3) d1 = new Date(tmp[0], Number(tmp[1])-1, tmp[2]); // yyyy-mm-dd
  146. var tmp = String(timeStr).split('/');
  147. if (tmp.length == 3) d1 = new Date(tmp[2], Number(tmp[0])-1, tmp[1]); // mm/dd/yyyy
  148. if (d1 == 'Invalid Time') return '';
  149. var d2 = new Date();
  150. var sec = (d2.getTime() - d1.getTime()) / 1000;
  151. var amount = '';
  152. var type = '';
  153. if (sec < 60) {
  154. amount = Math.floor(sec);
  155. type = 'sec';
  156. if (sec < 0) { amount = 0; type = 'sec' }
  157. } else if (sec < 60*60) {
  158. amount = Math.floor(sec/60);
  159. type = 'min';
  160. } else if (sec < 24*60*60) {
  161. amount = Math.floor(sec/60/60);
  162. type = 'hour';
  163. } else if (sec < 30*24*60*60) {
  164. amount = Math.floor(sec/24/60/60);
  165. type = 'day';
  166. } else if (sec < 12*30*24*60*60) {
  167. amount = Math.floor(sec/30/24/60/60*10)/10;
  168. type = 'month';
  169. } else if (sec >= 12*30*24*60*60) {
  170. amount = Math.floor(sec/12/30/24/60/60*10)/10;
  171. type = 'year';
  172. }
  173. return amount + ' ' + type + (amount > 1 ? 's' : '');
  174. }
  175. function date (dateStr) {
  176. var months = w2utils.settings.shortmonths;
  177. if (dateStr == '' || typeof dateStr == 'undefined' || dateStr == null) return '';
  178. if (w2utils.isInt(dateStr)) dateStr = Number(dateStr); // for unix timestamps
  179. var d1 = new Date(dateStr);
  180. if (w2utils.isInt(dateStr)) d1 = new Date(Number(dateStr)); // for unix timestamps
  181. var tmp = String(dateStr).split('-');
  182. if (tmp.length == 3) d1 = new Date(tmp[0], Number(tmp[1])-1, tmp[2]); // yyyy-mm-dd
  183. var tmp = String(dateStr).split('/');
  184. if (tmp.length == 3) d1 = new Date(tmp[2], Number(tmp[0])-1, tmp[1]); // mm/dd/yyyy
  185. if (d1 == 'Invalid Date') return '';
  186. var d2 = new Date(); // today
  187. var d3 = new Date();
  188. d3.setTime(d3.getTime() - 86400000); // yesterday
  189. var dd1 = months[d1.getMonth()] + ' ' + d1.getDate() + ', ' + d1.getFullYear();
  190. var dd2 = months[d2.getMonth()] + ' ' + d2.getDate() + ', ' + d2.getFullYear();
  191. var dd3 = months[d3.getMonth()] + ' ' + d3.getDate() + ', ' + d3.getFullYear();
  192. var time = (d1.getHours() - (d1.getHours() > 12 ? 12 :0)) + ':' + (d1.getMinutes() < 10 ? '0' : '') + d1.getMinutes() + ' ' + (d1.getHours() >= 12 ? 'pm' : 'am');
  193. 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');
  194. var dsp = dd1;
  195. if (dd1 == dd2) dsp = time;
  196. if (dd1 == dd3) dsp = w2utils.lang('Yesterday');
  197. return '<span title="'+ dd1 +' ' + time2 +'">'+ dsp +'</span>';
  198. }
  199. function size (sizeStr) {
  200. if (!w2utils.isFloat(sizeStr) || sizeStr == '') return '';
  201. sizeStr = parseFloat(sizeStr);
  202. if (sizeStr == 0) return 0;
  203. var sizes = ['Bt', 'KB', 'MB', 'GB', 'TB'];
  204. var i = parseInt( Math.floor( Math.log(sizeStr) / Math.log(1024) ) );
  205. return (Math.floor(sizeStr / Math.pow(1024, i) * 10) / 10).toFixed(i == 0 ? 0 : 1) + ' ' + sizes[i];
  206. }
  207. function formatNumber (val) {
  208. var ret = '';
  209. // check if this is a number
  210. if (w2utils.isFloat(val) || w2utils.isInt(val) || w2utils.isMoney(val)) {
  211. ret = String(val).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
  212. }
  213. return ret;
  214. }
  215. function formatDate (dateStr, format) { // IMPORTANT dateStr HAS TO BE valid JavaScript Date String
  216. var months = w2utils.settings.shortmonths;
  217. var fullMonths = w2utils.settings.fullmonths;
  218. if (typeof format == 'undefined') format = this.settings.date_format;
  219. if (typeof dateStr == 'undefined' || dateStr == '' || dateStr == null) return '';
  220. var dt = new Date(dateStr);
  221. if (w2utils.isInt(dateStr)) dt = new Date(Number(dateStr)); // for unix timestamps
  222. var tmp = String(dateStr).split('-');
  223. if (tmp.length == 3) dt = new Date(tmp[0], Number(tmp[1])-1, tmp[2]); // yyyy-mm-dd
  224. var tmp = String(dateStr).split('/');
  225. if (tmp.length == 3) dt = new Date(tmp[2], Number(tmp[0])-1, tmp[1]); // mm/dd/yyyy
  226. if (dt == 'Invalid Date') return '';
  227. var year = dt.getFullYear();
  228. var month = dt.getMonth();
  229. var date = dt.getDate();
  230. return format.toLowerCase()
  231. .replace('month', w2utils.settings.fullmonths[month])
  232. .replace('mon', w2utils.settings.shortmonths[month])
  233. .replace(/yyyy/g, year)
  234. .replace(/yyy/g, year)
  235. .replace(/yy/g, String(year).substr(2))
  236. .replace(/(^|[^a-z$])y/g, '$1'+year) // only y's that are not preceeded by a letter
  237. .replace(/mm/g, (month + 1 < 10 ? '0' : '') + (month + 1))
  238. .replace(/dd/g, (date < 10 ? '0' : '') + date)
  239. .replace(/(^|[^a-z$])m/g, '$1'+ (month + 1)) // only y's that are not preceeded by a letter
  240. .replace(/(^|[^a-z$])d/g, '$1' + date); // only y's that are not preceeded by a letter
  241. }
  242. function formatTime (dateStr, format) { // IMPORTANT dateStr HAS TO BE valid JavaScript Date String
  243. var months = w2utils.settings.shortmonths;
  244. var fullMonths = w2utils.settings.fullmonths;
  245. if (typeof format == 'undefined') format = this.settings.time_format;
  246. if (typeof dateStr == 'undefined' || dateStr == '' || dateStr == null) return '';
  247. var dt = new Date(dateStr);
  248. if (w2utils.isInt(dateStr)) dt = new Date(Number(dateStr)); // for unix timestamps
  249. if (dt == 'Invalid Date') return '';
  250. var type = 'am';
  251. var hour = dt.getHours();
  252. var h24 = dt.getHours();
  253. var min = dt.getMinutes();
  254. var sec = dt.getSeconds();
  255. if (min < 10) min = '0' + min;
  256. if (sec < 10) sec = '0' + sec;
  257. if (format.indexOf('am') != -1 || format.indexOf('pm') != -1) {
  258. if (hour >= 12) type = 'pm';
  259. if (hour > 12) hour = hour - 12;
  260. }
  261. return format.toLowerCase()
  262. .replace('am', type)
  263. .replace('pm', type)
  264. .replace('hh', hour)
  265. .replace('h24', h24)
  266. .replace('mm', min)
  267. .replace('mi', min)
  268. .replace('ss', sec)
  269. .replace(/(^|[^a-z$])h/g, '$1' + hour) // only y's that are not preceeded by a letter
  270. .replace(/(^|[^a-z$])m/g, '$1' + min) // only y's that are not preceeded by a letter
  271. .replace(/(^|[^a-z$])s/g, '$1' + sec); // only y's that are not preceeded by a letter
  272. }
  273. function formatDateTime(dateStr, format) {
  274. var fmt;
  275. if (typeof format != 'string') {
  276. var fmt = [this.settings.date_format, this.settings.time_format];
  277. } else {
  278. var fmt = format.split('|');
  279. }
  280. return this.formatDate(dateStr, fmt[0]) + ' ' + this.formatTime(dateStr, fmt[1]);
  281. }
  282. function stripTags (html) {
  283. if (html == null) return html;
  284. switch (typeof html) {
  285. case 'number':
  286. break;
  287. case 'string':
  288. html = $.trim(String(html).replace(/(<([^>]+)>)/ig, ""));
  289. break;
  290. case 'object':
  291. for (var a in html) html[a] = this.stripTags(html[a]);
  292. break;
  293. }
  294. return html;
  295. }
  296. function encodeTags (html) {
  297. if (html == null) return html;
  298. switch (typeof html) {
  299. case 'number':
  300. break;
  301. case 'string':
  302. html = String(html).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
  303. break;
  304. case 'object':
  305. for (var a in html) html[a] = this.encodeTags(html[a]);
  306. break;
  307. }
  308. return html;
  309. }
  310. function escapeId (id) {
  311. if (typeof id == 'undefined' || id == '' || id == null) return '';
  312. return String(id).replace(/([;&,\.\+\*\~'`:"\!\^#$%@\[\]\(\)=<>\|\/? {}\\])/g, '\\$1');
  313. }
  314. function base64encode (input) {
  315. var output = "";
  316. var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
  317. var i = 0;
  318. var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  319. input = utf8_encode(input);
  320. while (i < input.length) {
  321. chr1 = input.charCodeAt(i++);
  322. chr2 = input.charCodeAt(i++);
  323. chr3 = input.charCodeAt(i++);
  324. enc1 = chr1 >> 2;
  325. enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
  326. enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
  327. enc4 = chr3 & 63;
  328. if (isNaN(chr2)) {
  329. enc3 = enc4 = 64;
  330. } else if (isNaN(chr3)) {
  331. enc4 = 64;
  332. }
  333. output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
  334. }
  335. function utf8_encode (string) {
  336. var string = String(string).replace(/\r\n/g,"\n");
  337. var utftext = "";
  338. for (var n = 0; n < string.length; n++) {
  339. var c = string.charCodeAt(n);
  340. if (c < 128) {
  341. utftext += String.fromCharCode(c);
  342. }
  343. else if((c > 127) && (c < 2048)) {
  344. utftext += String.fromCharCode((c >> 6) | 192);
  345. utftext += String.fromCharCode((c & 63) | 128);
  346. }
  347. else {
  348. utftext += String.fromCharCode((c >> 12) | 224);
  349. utftext += String.fromCharCode(((c >> 6) & 63) | 128);
  350. utftext += String.fromCharCode((c & 63) | 128);
  351. }
  352. }
  353. return utftext;
  354. }
  355. return output;
  356. }
  357. function base64decode (input) {
  358. var output = "";
  359. var chr1, chr2, chr3;
  360. var enc1, enc2, enc3, enc4;
  361. var i = 0;
  362. var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  363. input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
  364. while (i < input.length) {
  365. enc1 = keyStr.indexOf(input.charAt(i++));
  366. enc2 = keyStr.indexOf(input.charAt(i++));
  367. enc3 = keyStr.indexOf(input.charAt(i++));
  368. enc4 = keyStr.indexOf(input.charAt(i++));
  369. chr1 = (enc1 << 2) | (enc2 >> 4);
  370. chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
  371. chr3 = ((enc3 & 3) << 6) | enc4;
  372. output = output + String.fromCharCode(chr1);
  373. if (enc3 != 64) {
  374. output = output + String.fromCharCode(chr2);
  375. }
  376. if (enc4 != 64) {
  377. output = output + String.fromCharCode(chr3);
  378. }
  379. }
  380. output = utf8_decode(output);
  381. function utf8_decode (utftext) {
  382. var string = "";
  383. var i = 0;
  384. var c = 0, c1 = 0, c2 = 0;
  385. while ( i < utftext.length ) {
  386. c = utftext.charCodeAt(i);
  387. if (c < 128) {
  388. string += String.fromCharCode(c);
  389. i++;
  390. }
  391. else if((c > 191) && (c < 224)) {
  392. c2 = utftext.charCodeAt(i+1);
  393. string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
  394. i += 2;
  395. }
  396. else {
  397. c2 = utftext.charCodeAt(i+1);
  398. c3 = utftext.charCodeAt(i+2);
  399. string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
  400. i += 3;
  401. }
  402. }
  403. return string;
  404. }
  405. return output;
  406. }
  407. function transition (div_old, div_new, type, callBack) {
  408. var width = $(div_old).width();
  409. var height = $(div_old).height();
  410. var time = 0.5;
  411. if (!div_old || !div_new) {
  412. console.log('ERROR: Cannot do transition when one of the divs is null');
  413. return;
  414. }
  415. div_old.parentNode.style.cssText += cross('perspective', '700px') +'; overflow: hidden;';
  416. div_old.style.cssText += '; position: absolute; z-index: 1019; '+ cross('backface-visibility', 'hidden');
  417. div_new.style.cssText += '; position: absolute; z-index: 1020; '+ cross('backface-visibility', 'hidden');
  418. switch (type) {
  419. case 'slide-left':
  420. // init divs
  421. div_old.style.cssText += 'overflow: hidden; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)');
  422. div_new.style.cssText += 'overflow: hidden; '+ cross('transform', 'translate3d('+ width + 'px, 0, 0)', 'translate('+ width +'px, 0)');
  423. $(div_new).show();
  424. // -- need a timing function because otherwise not working
  425. window.setTimeout(function() {
  426. div_new.style.cssText += cross('transition', time+'s') +';'+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)');
  427. div_old.style.cssText += cross('transition', time+'s') +';'+ cross('transform', 'translate3d(-'+ width +'px, 0, 0)', 'translate(-'+ width +'px, 0)');
  428. }, 1);
  429. break;
  430. case 'slide-right':
  431. // init divs
  432. div_old.style.cssText += 'overflow: hidden; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)');
  433. div_new.style.cssText += 'overflow: hidden; '+ cross('transform', 'translate3d(-'+ width +'px, 0, 0)', 'translate(-'+ width +'px, 0)');
  434. $(div_new).show();
  435. // -- need a timing function because otherwise not working
  436. window.setTimeout(function() {
  437. div_new.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'translate3d(0px, 0, 0)', 'translate(0px, 0)');
  438. div_old.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'translate3d('+ width +'px, 0, 0)', 'translate('+ width +'px, 0)');
  439. }, 1);
  440. break;
  441. case 'slide-down':
  442. // init divs
  443. div_old.style.cssText += 'overflow: hidden; z-index: 1; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)');
  444. div_new.style.cssText += 'overflow: hidden; z-index: 0; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)');
  445. $(div_new).show();
  446. // -- need a timing function because otherwise not working
  447. window.setTimeout(function() {
  448. div_new.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)');
  449. div_old.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'translate3d(0, '+ height +'px, 0)', 'translate(0, '+ height +'px)');
  450. }, 1);
  451. break;
  452. case 'slide-up':
  453. // init divs
  454. div_old.style.cssText += 'overflow: hidden; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)');
  455. div_new.style.cssText += 'overflow: hidden; '+ cross('transform', 'translate3d(0, '+ height +'px, 0)', 'translate(0, '+ height +'px)');
  456. $(div_new).show();
  457. // -- need a timing function because otherwise not working
  458. window.setTimeout(function() {
  459. div_new.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)');
  460. div_old.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)');
  461. }, 1);
  462. break;
  463. case 'flip-left':
  464. // init divs
  465. div_old.style.cssText += 'overflow: hidden; '+ cross('-transform', 'rotateY(0deg)');
  466. div_new.style.cssText += 'overflow: hidden; '+ cross('transform', 'rotateY(-180deg)');
  467. $(div_new).show();
  468. // -- need a timing function because otherwise not working
  469. window.setTimeout(function() {
  470. div_new.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'rotateY(0deg)');
  471. div_old.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'rotateY(180deg)');
  472. }, 1);
  473. break;
  474. case 'flip-right':
  475. // init divs
  476. div_old.style.cssText += 'overflow: hidden; '+ cross('transform', 'rotateY(0deg)');
  477. div_new.style.cssText += 'overflow: hidden; '+ cross('transform', 'rotateY(180deg)');
  478. $(div_new).show();
  479. // -- need a timing function because otherwise not working
  480. window.setTimeout(function() {
  481. div_new.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'rotateY(0deg)');
  482. div_old.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'rotateY(-180deg)');
  483. }, 1);
  484. break;
  485. case 'flip-down':
  486. // init divs
  487. div_old.style.cssText += 'overflow: hidden; '+ cross('transform', 'rotateX(0deg)');
  488. div_new.style.cssText += 'overflow: hidden; '+ cross('transform', 'rotateX(180deg)');
  489. $(div_new).show();
  490. // -- need a timing function because otherwise not working
  491. window.setTimeout(function() {
  492. div_new.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'rotateX(0deg)');
  493. div_old.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'rotateX(-180deg)');
  494. }, 1);
  495. break;
  496. case 'flip-up':
  497. // init divs
  498. div_old.style.cssText += 'overflow: hidden; '+ cross('transform', 'rotateX(0deg)');
  499. div_new.style.cssText += 'overflow: hidden; '+ cross('transform', 'rotateX(-180deg)');
  500. $(div_new).show();
  501. // -- need a timing function because otherwise not working
  502. window.setTimeout(function() {
  503. div_new.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'rotateX(0deg)');
  504. div_old.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'rotateX(180deg)');
  505. }, 1);
  506. break;
  507. case 'pop-in':
  508. // init divs
  509. div_old.style.cssText += 'overflow: hidden; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)');
  510. div_new.style.cssText += 'overflow: hidden; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)') + '; '+ cross('transform', 'scale(.8)') + '; opacity: 0;';
  511. $(div_new).show();
  512. // -- need a timing function because otherwise not working
  513. window.setTimeout(function() {
  514. div_new.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'scale(1)') +'; opacity: 1;';
  515. div_old.style.cssText += cross('transition', time+'s') +';';
  516. }, 1);
  517. break;
  518. case 'pop-out':
  519. // init divs
  520. div_old.style.cssText += 'overflow: hidden; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)') +'; '+ cross('transform', 'scale(1)') +'; opacity: 1;';
  521. div_new.style.cssText += 'overflow: hidden; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)') +'; opacity: 0;';
  522. $(div_new).show();
  523. // -- need a timing function because otherwise not working
  524. window.setTimeout(function() {
  525. div_new.style.cssText += cross('transition', time+'s') +'; opacity: 1;';
  526. div_old.style.cssText += cross('transition', time+'s') +'; '+ cross('transform', 'scale(1.7)') +'; opacity: 0;';
  527. }, 1);
  528. break;
  529. default:
  530. // init divs
  531. div_old.style.cssText += 'overflow: hidden; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)');
  532. div_new.style.cssText += 'overflow: hidden; '+ cross('transform', 'translate3d(0, 0, 0)', 'translate(0, 0)') +'; opacity: 0;';
  533. $(div_new).show();
  534. // -- need a timing function because otherwise not working
  535. window.setTimeout(function() {
  536. div_new.style.cssText += cross('transition', time +'s') +'; opacity: 1;';
  537. div_old.style.cssText += cross('transition', time +'s');
  538. }, 1);
  539. break;
  540. }
  541. setTimeout(function () {
  542. if (type == 'slide-down') {
  543. $(div_old).css('z-index', '1019');
  544. $(div_new).css('z-index', '1020');
  545. }
  546. if (div_new) {
  547. $(div_new).css({
  548. 'opacity': '1',
  549. '-webkit-transition': '',
  550. '-moz-transition': '',
  551. '-ms-transition': '',
  552. '-o-transition': '',
  553. '-webkit-transform': '',
  554. '-moz-transform': '',
  555. '-ms-transform': '',
  556. '-o-transform': '',
  557. '-webkit-backface-visibility': '',
  558. '-moz-backface-visibility': '',
  559. '-ms-backface-visibility': '',
  560. '-o-backface-visibility': ''
  561. });
  562. }
  563. if (div_old) {
  564. $(div_old).css({
  565. 'opacity': '1',
  566. '-webkit-transition': '',
  567. '-moz-transition': '',
  568. '-ms-transition': '',
  569. '-o-transition': '',
  570. '-webkit-transform': '',
  571. '-moz-transform': '',
  572. '-ms-transform': '',
  573. '-o-transform': '',
  574. '-webkit-backface-visibility': '',
  575. '-moz-backface-visibility': '',
  576. '-ms-backface-visibility': '',
  577. '-o-backface-visibility': ''
  578. });
  579. if (div_old.parentNode) $(div_old.parentNode).css({
  580. '-webkit-perspective': '',
  581. '-moz-perspective': '',
  582. '-ms-perspective': '',
  583. '-o-perspective': ''
  584. });
  585. }
  586. if (typeof callBack == 'function') callBack();
  587. }, time * 1000);
  588. function cross(property, value, none_webkit_value) {
  589. var isWebkit=!!window.webkitURL; // jQuery no longer supports $.browser - RR
  590. if (!isWebkit && typeof none_webkit_value != 'undefined') value = none_webkit_value;
  591. return ';'+ property +': '+ value +'; -webkit-'+ property +': '+ value +'; -moz-'+ property +': '+ value +'; '+
  592. '-ms-'+ property +': '+ value +'; -o-'+ property +': '+ value +';';
  593. }
  594. }
  595. function lock (box, msg, showSpinner) {
  596. if (!msg && msg != 0) msg = '';
  597. w2utils.unlock(box);
  598. $(box).find('>:first-child').before(
  599. '<div class="w2ui-lock"></div>'+
  600. '<div class="w2ui-lock-msg"></div>'
  601. );
  602. setTimeout(function () {
  603. var lock = $(box).find('.w2ui-lock');
  604. var mess = $(box).find('.w2ui-lock-msg');
  605. lock.data('old_opacity', lock.css('opacity')).css('opacity', '0').show();
  606. mess.data('old_opacity', mess.css('opacity')).css('opacity', '0').show();
  607. setTimeout(function () {
  608. var lock = $(box).find('.w2ui-lock');
  609. var mess = $(box).find('.w2ui-lock-msg');
  610. var left = ($(box).width() - w2utils.getSize(mess, 'width')) / 2;
  611. var top = ($(box).height() * 0.9 - w2utils.getSize(mess, 'height')) / 2;
  612. lock.css({
  613. opacity : lock.data('old_opacity'),
  614. left : '0px',
  615. top : '0px',
  616. width : '100%',
  617. height : '100%'
  618. });
  619. if (!msg) mess.css({ 'background-color': 'transparent', 'border': '0px' });
  620. if (showSpinner === true) msg = '<div class="w2ui-spinner" '+ (!msg ? 'style="width: 30px; height: 30px"' : '') +'></div>' + msg;
  621. mess.html(msg).css({
  622. opacity : mess.data('old_opacity'),
  623. left : left + 'px',
  624. top : top + 'px'
  625. });
  626. }, 10);
  627. }, 10);
  628. // hide all tags (do not hide overlays as the form can be in overlay)
  629. $().w2tag();
  630. }
  631. function unlock (box) {
  632. $(box).find('.w2ui-lock').remove();
  633. $(box).find('.w2ui-lock-msg').remove();
  634. }
  635. function getSize (el, type) {
  636. var bwidth = {
  637. left: parseInt($(el).css('border-left-width')) || 0,
  638. right: parseInt($(el).css('border-right-width')) || 0,
  639. top: parseInt($(el).css('border-top-width')) || 0,
  640. bottom: parseInt($(el).css('border-bottom-width')) || 0
  641. }
  642. var mwidth = {
  643. left: parseInt($(el).css('margin-left')) || 0,
  644. right: parseInt($(el).css('margin-right')) || 0,
  645. top: parseInt($(el).css('margin-top')) || 0,
  646. bottom: parseInt($(el).css('margin-bottom')) || 0
  647. }
  648. var pwidth = {
  649. left: parseInt($(el).css('padding-left')) || 0,
  650. right: parseInt($(el).css('padding-right')) || 0,
  651. top: parseInt($(el).css('padding-top')) || 0,
  652. bottom: parseInt($(el).css('padding-bottom')) || 0
  653. }
  654. switch (type) {
  655. case 'top': return bwidth.top + mwidth.top + pwidth.top;
  656. case 'bottom': return bwidth.bottom + mwidth.bottom + pwidth.bottom;
  657. case 'left': return bwidth.left + mwidth.left + pwidth.left;
  658. case 'right': return bwidth.right + mwidth.right + pwidth.right;
  659. case 'width': return bwidth.left + bwidth.right + mwidth.left + mwidth.right + pwidth.left + pwidth.right + parseInt($(el).width());
  660. case 'height': return bwidth.top + bwidth.bottom + mwidth.top + mwidth.bottom + pwidth.top + pwidth.bottom + parseInt($(el).height());
  661. case '+width': return bwidth.left + bwidth.right + mwidth.left + mwidth.right + pwidth.left + pwidth.right;
  662. case '+height': return bwidth.top + bwidth.bottom + mwidth.top + mwidth.bottom + pwidth.top + pwidth.bottom;
  663. }
  664. return 0;
  665. }
  666. function lang (phrase) {
  667. var translation = this.settings.phrases[phrase];
  668. if (typeof translation == 'undefined') return phrase; else return translation;
  669. }
  670. function locale (locale) {
  671. if (!locale) locale = 'en-us';
  672. if (locale.length == 5) locale = 'locale/'+ locale +'.json';
  673. // load from the file
  674. $.ajax({
  675. url : locale,
  676. type : "GET",
  677. dataType: "JSON",
  678. async : false,
  679. cache : false,
  680. success : function (data, status, xhr) {
  681. w2utils.settings = $.extend(true, w2utils.settings, data);
  682. },
  683. error : function (xhr, status, msg) {
  684. console.log('ERROR: Cannot load locale '+ locale);
  685. }
  686. });
  687. }
  688. function scrollBarSize () {
  689. if (tmp.scrollBarSize) return tmp.scrollBarSize;
  690. var html = '<div id="_scrollbar_width" style="position: absolute; top: -300px; width: 100px; height: 100px; overflow-y: scroll;">'+
  691. ' <div style="height: 120px">1</div>'+
  692. '</div>';
  693. $('body').append(html);
  694. tmp.scrollBarSize = 100 - $('#_scrollbar_width > div').width();
  695. $('#_scrollbar_width').remove();
  696. if (String(navigator.userAgent).indexOf('MSIE') >= 0) tmp.scrollBarSize = tmp.scrollBarSize / 2; // need this for IE9+
  697. return tmp.scrollBarSize;
  698. }
  699. })();
  700. /***********************************************************
  701. * Generic Event Object
  702. * --- This object is reused across all other
  703. * --- widgets in w2ui.
  704. *
  705. *********************************************************/
  706. w2utils.event = {
  707. on: function (eventData, handler) {
  708. if (!$.isPlainObject(eventData)) eventData = { type: eventData };
  709. eventData = $.extend({ type: null, execute: 'before', target: null, onComplete: null }, eventData);
  710. if (typeof eventData.type == 'undefined') { console.log('ERROR: You must specify event type when calling .on() method of '+ this.name); return; }
  711. if (typeof handler == 'undefined') { console.log('ERROR: You must specify event handler function when calling .on() method of '+ this.name); return; }
  712. this.handlers.push({ event: eventData, handler: handler });
  713. },
  714. off: function (eventData, handler) {
  715. if (!$.isPlainObject(eventData)) eventData = { type: eventData };
  716. eventData = $.extend({}, { type: null, execute: 'before', target: null, onComplete: null }, eventData);
  717. if (typeof eventData.type == 'undefined') { console.log('ERROR: You must specify event type when calling .off() method of '+ this.name); return; }
  718. if (typeof handler == 'undefined') { handler = null; }
  719. // remove handlers
  720. var newHandlers = [];
  721. for (var h in this.handlers) {
  722. var t = this.handlers[h];
  723. if ( (t.event.type == eventData.type || eventData.type == '*')
  724. && (t.event.target == eventData.target || eventData.target == null)
  725. && (t.handler == handler || handler == null)) {
  726. // match
  727. } else {
  728. newHandlers.push(t);
  729. }
  730. }
  731. this.handlers = newHandlers;
  732. },
  733. trigger: function (eventData) {
  734. var eventData = $.extend({ type: null, phase: 'before', target: null, isStopped: false, isCancelled: false }, eventData, {
  735. preventDefault : function () { this.isCancelled = true; },
  736. stopPropagation : function () { this.isStopped = true; },
  737. });
  738. if (typeof eventData.target == 'undefined') eventData.target = null;
  739. // process events in REVERSE order
  740. for (var h = this.handlers.length-1; h >= 0; h--) {
  741. var item = this.handlers[h];
  742. if ( (item.event.type == eventData.type || item.event.type == '*')
  743. && (item.event.target == eventData.target || item.event.target == null)
  744. && (item.event.execute == eventData.phase || item.event.execute == '*' || item.event.phase == '*') ) {
  745. eventData = $.extend({}, item.event, eventData);
  746. // check handler arguments
  747. var args = [];
  748. var tmp = RegExp(/\((.*?)\)/).exec(item.handler);
  749. if (tmp) args = tmp[1].split(/\s*,\s*/);
  750. if (args.length == 2) {
  751. item.handler.call(this, eventData.target, eventData); // old way for back compatibility
  752. } else {
  753. item.handler.call(this, eventData); // new way
  754. }
  755. if (eventData.isStopped === true || eventData.stop === true) return eventData; // back compatibility eventData.stop === true
  756. }
  757. }
  758. // main object events
  759. var funName = 'on' + eventData.type.substr(0,1).toUpperCase() + eventData.type.substr(1);
  760. if (eventData.phase == 'before' && typeof this[funName] == 'function') {
  761. var fun = this[funName];
  762. // check handler arguments
  763. var args = [];
  764. var tmp = RegExp(/\((.*?)\)/).exec(fun);
  765. if (tmp) args = tmp[1].split(/\s*,\s*/);
  766. if (args.length == 2) {
  767. fun.call(this, eventData.target, eventData); // old way for back compatibility
  768. } else {
  769. fun.call(this, eventData); // new way
  770. }
  771. if (eventData.isStopped === true || eventData.stop === true) return eventData; // back compatibility eventData.stop === true
  772. }
  773. // item object events
  774. if (typeof eventData.object != 'undefined' && eventData.object != null && eventData.phase == 'before'
  775. && typeof eventData.object[funName] == 'function') {
  776. var fun = eventData.object[funName];
  777. // check handler arguments
  778. var args = [];
  779. var tmp = RegExp(/\((.*?)\)/).exec(fun);
  780. if (tmp) args = tmp[1].split(/\s*,\s*/);
  781. if (args.length == 2) {
  782. fun.call(this, eventData.target, eventData); // old way for back compatibility
  783. } else {
  784. fun.call(this, eventData); // new way
  785. }
  786. if (eventData.isStopped === true || eventData.stop === true) return eventData;
  787. }
  788. // execute onComplete
  789. if (eventData.phase == 'after' && eventData.onComplete != null) eventData.onComplete.call(this, eventData);
  790. return eventData;
  791. }
  792. };
  793. /***********************************************************
  794. * Common Keyboard Handler. Supported in
  795. * - grid
  796. * - sidebar
  797. * - popup
  798. *
  799. *********************************************************/
  800. w2utils.keyboard = (function (obj) {
  801. // private scope
  802. var w2ui_name = null;
  803. obj.active = active;
  804. obj.clear = clear;
  805. obj.register = register;
  806. init();
  807. return obj;
  808. function init() {
  809. $(document).on('keydown', keydown);
  810. $(document).on('mousedown', mousedown);
  811. }
  812. function keydown (event) {
  813. var tag = event.target.tagName;
  814. if ($.inArray(tag, ['INPUT', 'SELECT', 'TEXTAREA']) != -1) return;
  815. if ($(event.target).prop('contenteditable') == 'true') return;
  816. if (!w2ui_name) return;
  817. // pass to appropriate widget
  818. if (w2ui[w2ui_name] && typeof w2ui[w2ui_name].keydown == 'function') {
  819. w2ui[w2ui_name].keydown.call(w2ui[w2ui_name], event);
  820. }
  821. }
  822. function mousedown (event) {
  823. var tag = event.target.tagName;
  824. var obj = $(event.target).parents('.w2ui-reset');
  825. if (obj.length > 0) {
  826. w2ui_name = obj.attr('name');
  827. }
  828. }
  829. function active (new_w2ui_name) {
  830. if (typeof new_w2ui_name == 'undefined') return w2ui_name;
  831. w2ui_name = new_w2ui_name;
  832. }
  833. function clear () {
  834. w2ui_name = null;
  835. }
  836. function register () {
  837. }
  838. })({});
  839. /***********************************************************
  840. * Commonly used plugins
  841. * --- used primarily in grid and form
  842. *
  843. *********************************************************/
  844. (function () {
  845. $.fn.w2render = function (name) {
  846. if ($(this).length > 0) {
  847. if (typeof name == 'string' && w2ui[name]) w2ui[name].render($(this)[0]);
  848. if (typeof name == 'object') name.render($(this)[0]);
  849. }
  850. }
  851. $.fn.w2destroy = function (name) {
  852. if (!name && this.length > 0) name = this.attr('name');
  853. if (typeof name == 'string' && w2ui[name]) w2ui[name].destroy();
  854. if (typeof name == 'object') name.destroy();
  855. }
  856. $.fn.w2marker = function (str) {
  857. if (str == '' || typeof str == 'undefined') { // remove marker
  858. return $(this).each(function (index, el) {
  859. el.innerHTML = el.innerHTML.replace(/\<span class=\"w2ui\-marker\"\>(.*)\<\/span\>/ig, '$1'); // unmark
  860. });
  861. } else { // add marker
  862. return $(this).each(function (index, el) {
  863. if (typeof str == 'string') str = [str];
  864. el.innerHTML = el.innerHTML.replace(/\<span class=\"w2ui\-marker\"\>(.*)\<\/span\>/ig, '$1'); // unmark
  865. for (var s in str) {
  866. var tmp = str[s];
  867. if (typeof tmp != 'string') tmp = String(tmp);
  868. // escape regex special chars
  869. tmp = tmp.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&").replace(/&/g, '&amp;').replace(/</g, '&gt;').replace(/>/g, '&lt;');
  870. var regex = new RegExp(tmp + '(?!([^<]+)?>)', "gi"); // only outside tags
  871. el.innerHTML = el.innerHTML.replace(regex, function (matched) { // mark new
  872. return '<span class="w2ui-marker">' + matched + '</span>';
  873. });
  874. }
  875. });
  876. }
  877. }
  878. // -- w2tag - appears on the right side from element, there can be multiple on screen at a time
  879. $.fn.w2tag = function (text, options) {
  880. if (!$.isPlainObject(options)) options = {};
  881. if (!$.isPlainObject(options.css)) options.css = {};
  882. if (typeof options['class'] == 'undefined') options['class'] = '';
  883. // remove all tags
  884. if ($(this).length == 0) {
  885. $('.w2ui-tag').each(function (index, elem) {
  886. var opt = $(elem).data('options');
  887. if (typeof opt == 'undefined') opt = {};
  888. $($(elem).data('taged-el')).removeClass( opt['class'] );
  889. clearInterval($(elem).data('timer'));
  890. $(elem).remove();
  891. });
  892. return;
  893. }
  894. return $(this).each(function (index, el) {
  895. // show or hide tag
  896. var tagOrigID = el.id;
  897. var tagID = w2utils.escapeId(el.id);
  898. if (text == '' || text == null || typeof text == 'undefined') {
  899. $('#w2ui-tag-'+tagID).css('opacity', 0);
  900. setTimeout(function () {
  901. // remmove element
  902. clearInterval($('#w2ui-tag-'+tagID).data('timer'));
  903. $('#w2ui-tag-'+tagID).remove();
  904. }, 300);
  905. } else {
  906. // remove elements
  907. clearInterval($('#w2ui-tag-'+tagID).data('timer'));
  908. $('#w2ui-tag-'+tagID).remove();
  909. // insert
  910. $('body').append('<div id="w2ui-tag-'+ tagOrigID +'" class="w2ui-tag '+ ($(el).parents('.w2ui-popup').length > 0 ? 'w2ui-tag-popup' : '') +'" '+
  911. ' style=""></div>');
  912. var timer = setInterval(function () {
  913. // monitor if destroyed
  914. if ($(el).length == 0 || ($(el).offset().left == 0 && $(el).offset().top == 0)) {
  915. clearInterval($('#w2ui-tag-'+tagID).data('timer'));
  916. tmp_hide();
  917. return;
  918. }
  919. // monitor if moved
  920. if ($('#w2ui-tag-'+tagID).data('position') != ($(el).offset().left + el.offsetWidth) + 'x' + $(el).offset().top) {
  921. $('#w2ui-tag-'+tagID).css({
  922. '-webkit-transition': '.2s',
  923. '-moz-transition': '.2s',
  924. '-ms-transition': '.2s',
  925. '-o-transition': '.2s',
  926. left: ($(el).offset().left + el.offsetWidth) + 'px',
  927. top: $(el).offset().top + 'px'
  928. }).data('position', ($(el).offset().left + el.offsetWidth) + 'x' + $(el).offset().top);
  929. }
  930. }, 100);
  931. setTimeout(function () {
  932. if (!$(el).offset()) return;
  933. $('#w2ui-tag-'+tagID).css({
  934. opacity: '1',
  935. left: ($(el).offset().left + el.offsetWidth) + 'px',
  936. top: $(el).offset().top + 'px'
  937. }).html('<div style="margin-top: -2px 0px 0px -2px; white-space: nowrap;"> <div class="w2ui-tag-body">'+ text +'</div> </div>')
  938. .data('text', text)
  939. .data('taged-el', el)
  940. .data('options', options)
  941. .data('position', ($(el).offset().left + el.offsetWidth) + 'x' + $(el).offset().top)
  942. .data('timer', timer);
  943. $(el).off('keypress', tmp_hide).on('keypress', tmp_hide).off('change', tmp_hide).on('change', tmp_hide)
  944. .css(options.css).addClass(options['class']);
  945. if (typeof options.onShow == 'function') options.onShow();
  946. }, 1);
  947. var originalCSS = '';
  948. if ($(el).length > 0) originalCSS = $(el)[0].style.cssText;
  949. // bind event to hide it
  950. function tmp_hide() {
  951. if ($('#w2ui-tag-'+tagID).length <= 0) return;
  952. clearInterval($('#w2ui-tag-'+tagID).data('timer'));
  953. $('#w2ui-tag-'+tagID).remove();
  954. $(el).off('keypress', tmp_hide).removeClass(options['class']);
  955. if ($(el).length > 0) $(el)[0].style.cssText = originalCSS;
  956. if (typeof options.onHide == 'function') options.onHide();
  957. }
  958. }
  959. });
  960. }
  961. // w2overlay - appears under the element, there can be only one at a time
  962. $.fn.w2overlay = function (html, options) {
  963. if (!$.isPlainObject(options)) options = {};
  964. if (!$.isPlainObject(options.css)) options.css = {};
  965. if (this.length == 0 || html == '' || typeof html == 'undefined') { hide(); return $(this); }
  966. if ($('#w2ui-overlay').length > 0) $(document).click();
  967. $('body').append('<div id="w2ui-overlay" class="w2ui-reset w2ui-overlay '+
  968. ($(this).parents('.w2ui-popup').length > 0 ? 'w2ui-overlay-popup' : '') +'">'+
  969. ' <div></div>'+
  970. '</div>');
  971. // init
  972. var obj = this;
  973. var div = $('#w2ui-overlay div');
  974. div.css(options.css).html(html);
  975. if (typeof options['class'] != 'undefined') div.addClass(options['class']);
  976. if (typeof options.top == 'undefined') options.top = 0;
  977. if (typeof options.left == 'undefined') options.left = 0;
  978. if (typeof options.width == 'undefined') options.width = 100;
  979. if (typeof options.height == 'undefined') options.height = 0;
  980. // pickup bg color of first div
  981. var bc = div.css('background-color');
  982. var div = $('#w2ui-overlay');
  983. if (typeof bc != 'undefined' && bc != 'rgba(0, 0, 0, 0)' && bc != 'transparent') div.css('background-color', bc);
  984. div.css({
  985. display : 'none',
  986. left : ($(obj).offset().left + options.left) + 'px',
  987. top : ($(obj).offset().top + w2utils.getSize($(obj), 'height') + 3 + options.top) + 'px',
  988. 'min-width' : (options.width ? options.width : 'auto'),
  989. 'min-height' : (options.height ? options.height : 'auto')
  990. })
  991. .fadeIn('fast')
  992. .data('position', ($(obj).offset().left) + 'x' + ($(obj).offset().top + obj.offsetHeight))
  993. .on('click', function (event) {
  994. if (event.stopPropagation) event.stopPropagation(); else event.cancelBubble = true;
  995. });
  996. // click anywhere else hides the drop down
  997. function hide () {
  998. var result;
  999. if (typeof options.onHide == 'function') result = options.onHide();
  1000. if (result === false) return;
  1001. $('#w2ui-overlay').remove();
  1002. $(document).off('click', hide);
  1003. }
  1004. // need time to display
  1005. setTimeout(fixSize, 0);
  1006. return $(this);
  1007. function fixSize () {
  1008. $(document).on('click', hide);
  1009. // if goes over the screen, limit height and width
  1010. if ( $('#w2ui-overlay > div').length > 0) {
  1011. var h = $('#w2ui-overlay > div').height();
  1012. var w = $('#w2ui-overlay> div').width();
  1013. // $(window).height() - has a problem in FF20
  1014. var max = window.innerHeight - $('#w2ui-overlay > div').offset().top - 7;
  1015. if (h > max) $('#w2ui-overlay> div').height(max).width(w + w2utils.scrollBarSize()).css({ 'overflow-y': 'auto' });
  1016. // check width
  1017. w = $('#w2ui-overlay> div').width();
  1018. max = window.innerWidth - $('#w2ui-overlay > div').offset().left - 7;
  1019. if (w > max) $('#w2ui-overlay> div').width(max).css({ 'overflow-x': 'auto' });
  1020. // onShow event
  1021. if (typeof options.onShow == 'function') options.onShow();
  1022. }
  1023. }
  1024. }
  1025. $.fn.w2menu = function (menu, options) {
  1026. if (typeof options.select == 'undefined' && typeof options.onSelect == 'function') options.select = options.onSelect;
  1027. if (typeof options.select != 'function') {
  1028. console.log('ERROR: options.select is required to be a function, not '+ typeof options.select + ' in $().w2menu(menu, options)');
  1029. return $(this);
  1030. }
  1031. if (!$.isArray(menu)) {
  1032. console.log('ERROR: first parameter should be an array of objects or strings in $().w2menu(menu, options)');
  1033. return $(this);
  1034. }
  1035. // since only one overlay can exist at a time
  1036. $.fn.w2menuHandler = function (event, index) {
  1037. options.select(menu[index], event, index);
  1038. }
  1039. return $(this).w2overlay(getMenuHTML(), options);
  1040. function getMenuHTML () {
  1041. var menu_html = '<table cellspacing="0" cellpadding="0" class="w2ui-drop-menu">';
  1042. for (var f = 0; f < menu.length; f++) {
  1043. var mitem = menu[f];
  1044. if (typeof mitem == 'string') {
  1045. var tmp = mitem.split('|');
  1046. // 1 - id, 2 - text, 3 - image, 4 - icon
  1047. mitem = { id: tmp[0], text: tmp[0], img: null, icon: null };
  1048. if (tmp[1]) mitem.text = tmp[1];
  1049. if (tmp[2]) mitem.img = tmp[2];
  1050. if (tmp[3]) mitem.icon = tmp[3];
  1051. } else {
  1052. if (typeof mitem.text != 'undefined' && typeof mitem.id == 'undefined') mitem.id = mitem.text;
  1053. if (typeof mitem.text == 'undefined' && typeof mitem.id != 'undefined') mitem.text = mitem.id;
  1054. if (typeof mitem.caption != 'undefined') mitem.text = mitem.caption;
  1055. if (typeof mitem.img == 'undefined') mitem.img = null;
  1056. if (typeof mitem.icon == 'undefined') mitem.icon = null;
  1057. }
  1058. var img = '<td>&nbsp;</td>';
  1059. if (mitem.img) img = '<td><div class="w2ui-tb-image w2ui-icon '+ mitem.img +'"></div></td>';
  1060. if (mitem.icon) img = '<td align="center"><div class="w2ui-tb-image"><span class="'+ mitem.icon +'"></span></div></td>';
  1061. menu_html +=
  1062. '<tr onmouseover="$(this).addClass(\'w2ui-selected\');" onmouseout="$(this).removeClass(\'w2ui-selected\');" '+
  1063. ' onclick="$(document).click(); $.fn.w2menuHandler(event, \''+ f +'\');">'+
  1064. img +
  1065. ' <td>'+ mitem.text +'</td>'+
  1066. '</tr>';
  1067. }
  1068. menu_html += "</table>";
  1069. return menu_html;
  1070. }
  1071. }
  1072. })();
  1073. /************************************************************************
  1074. * Library: Web 2.0 UI for jQuery (using prototypical inheritance)
  1075. * - Following objects defined
  1076. * - w2grid - grid widget
  1077. * - $().w2grid - jQuery wrapper
  1078. * - Dependencies: jQuery, w2utils, w2toolbar, w2fields, w2alert, w2confirm
  1079. *
  1080. * == NICE TO HAVE ==
  1081. * - global search apply types and drop downs
  1082. * - editable fields (list) - better inline editing
  1083. * - frozen columns
  1084. * - column autosize based on largest content
  1085. * - save grid state into localStorage and restore
  1086. * - easy bubbles in the grid
  1087. * - possibly add context menu similar to sidebar's
  1088. * - Merged cells
  1089. * - More than 2 layers of header groups
  1090. * - for search fields one should be able to pass w2field options
  1091. * - add enum to advanced search fields
  1092. * - be able to attach events in advanced search dialog
  1093. * - reorder columns/records
  1094. * - hidden searches could not be clearned by the user
  1095. *
  1096. ************************************************************************/
  1097. (function () {
  1098. var w2grid = function(options) {
  1099. // public properties
  1100. this.name = null;
  1101. this.box = null; // HTML element that hold this element
  1102. this.header = '';
  1103. this.url = '';
  1104. this.columns = []; // { field, caption, size, attr, render, hidden, gridMinWidth, [editable: {type, inTag, outTag, style, items}] }
  1105. this.columnGroups = []; // { span: int, caption: 'string', master: true/false }
  1106. this.records = []; // { recid: int(requied), field1: 'value1', ... fieldN: 'valueN', style: 'string', editable: true/false, summary: true/false, changed: true/false, changes: object }
  1107. this.summary = []; // arry of summary records, same structure as records array
  1108. this.searches = []; // { type, caption, field, inTag, outTag, default, items, hidden }
  1109. this.searchData = [];
  1110. this.sortData = [];
  1111. this.postData = {};
  1112. this.toolbar = {}; // if not empty object; then it is toolbar object
  1113. this.show = {
  1114. header : false,
  1115. toolbar : false,
  1116. footer : false,
  1117. columnHeaders : true,
  1118. lineNumbers : false,
  1119. expandColumn : false,
  1120. selectColumn : false,
  1121. emptyRecords : true,
  1122. toolbarReload : true,
  1123. toolbarColumns : true,
  1124. toolbarSearch : true,
  1125. toolbarAdd : false,
  1126. toolbarEdit : false,
  1127. toolbarDelete : false,
  1128. toolbarSave : false,
  1129. selectionBorder : true,
  1130. recordTitles : true
  1131. }
  1132. this.autoLoad = true; // for infinite scroll
  1133. this.fixedBody = true; // if false; then grid grows with data
  1134. this.recordHeight = 24;
  1135. this.keyboard = true;
  1136. this.selectType = 'row'; // can be row|cell
  1137. this.multiSearch = true;
  1138. this.multiSelect = true;
  1139. this.multiSort = true;
  1140. this.markSearchResults = true;
  1141. this.total = 0; // server total
  1142. this.buffered = 0; // number of records in the records array
  1143. this.limit = 100;
  1144. this.offset = 0; // how many records to skip (for infinite scroll) when pulling from server
  1145. this.style = '';
  1146. this.ranges = [];
  1147. // events
  1148. this.onAdd = null;
  1149. this.onEdit = null;
  1150. this.onRequest = null; // called on any server event
  1151. this.onLoad = null;
  1152. this.onDelete = null;
  1153. this.onDeleted = null
  1154. this.onSave = null;
  1155. this.onSaved = null;
  1156. this.onSelect = null;
  1157. this.onUnselect = null;
  1158. this.onClick = null;
  1159. this.onDblClick = null;
  1160. this.onColumnClick = null;
  1161. this.onColumnResize = null;
  1162. this.onSort = null;
  1163. this.onSearch = null;
  1164. this.onChange = null; // called when editable record is changed
  1165. this.onExpand = null;
  1166. this.onCollapse = null;
  1167. this.onError = null;
  1168. this.onKeydown = null;
  1169. this.onToolbar = null; // all events from toolbar
  1170. this.onColumnOnOff = null;
  1171. this.onCopy = null;
  1172. this.onPaste = null;
  1173. this.onSelectionExtend = null;
  1174. this.onEditField = null;
  1175. this.onRender = null;
  1176. this.onRefresh = null;
  1177. this.onReload = null;
  1178. this.onResize = null;
  1179. this.onDestroy = null;
  1180. // internal
  1181. this.last = {
  1182. field : 'all',
  1183. caption : w2utils.lang('All Fields'),
  1184. logic : 'OR',
  1185. search : '',
  1186. searchIds : [],
  1187. multi : false,
  1188. scrollTop : 0,
  1189. scrollLeft : 0,
  1190. selected : [],
  1191. sortData : null,
  1192. sortCount : 0,
  1193. xhr : null,
  1194. range_start : null,
  1195. range_end : null,
  1196. sel_ind : null,
  1197. sel_col : null,
  1198. sel_type : null
  1199. }
  1200. this.isIOS = (navigator.userAgent.toLowerCase().indexOf('iphone') != -1 ||
  1201. navigator.userAgent.toLowerCase().indexOf('ipod') != -1 ||
  1202. navigator.userAgent.toLowerCase().indexOf('ipad') != -1) ? true : false;
  1203. $.extend(true, this, w2obj.grid, options);
  1204. };
  1205. // ====================================================
  1206. // -- Registers as a jQuery plugin
  1207. $.fn.w2grid = function(method) {
  1208. if (typeof method === 'object' || !method ) {
  1209. // check required parameters
  1210. if (!method || typeof method.name == 'undefined') {
  1211. console.log('ERROR: The parameter "name" is required but not supplied in $().w2grid().');
  1212. return;
  1213. }
  1214. if (typeof w2ui[method.name] != 'undefined') {
  1215. console.log