PageRenderTime 54ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/files/w2ui/1.3.2/w2ui.js

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