PageRenderTime 33ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/files/w2ui/1.2/w2ui.js

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