jquery.fmatter.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /*
  2. **
  3. * formatter for values but most of the values if for jqGrid
  4. * Some of this was inspired and based on how YUI does the table datagrid but in jQuery fashion
  5. * we are trying to keep it as light as possible
  6. * Joshua Burnett josh@9ci.com
  7. * http://www.greenbill.com
  8. *
  9. * Changes from Tony Tomov tony@trirand.com
  10. * Dual licensed under the MIT and GPL licenses:
  11. * http://www.opensource.org/licenses/mit-license.php
  12. * http://www.gnu.org/licenses/gpl-2.0.html
  13. *
  14. **/
  15. /*jshint eqeqeq:false */
  16. /*global jQuery */
  17. (function($) {
  18. "use strict";
  19. $.fmatter = {};
  20. //opts can be id:row id for the row, rowdata:the data for the row, colmodel:the column model for this column
  21. //example {id:1234,}
  22. $.extend($.fmatter,{
  23. isBoolean : function(o) {
  24. return typeof o === 'boolean';
  25. },
  26. isObject : function(o) {
  27. return (o && (typeof o === 'object' || $.isFunction(o))) || false;
  28. },
  29. isString : function(o) {
  30. return typeof o === 'string';
  31. },
  32. isNumber : function(o) {
  33. return typeof o === 'number' && isFinite(o);
  34. },
  35. isValue : function (o) {
  36. return (this.isObject(o) || this.isString(o) || this.isNumber(o) || this.isBoolean(o));
  37. },
  38. isEmpty : function(o) {
  39. if(!this.isString(o) && this.isValue(o)) {
  40. return false;
  41. }
  42. if (!this.isValue(o)){
  43. return true;
  44. }
  45. o = $.trim(o).replace(/\&nbsp\;/ig,'').replace(/\&#160\;/ig,'');
  46. return o==="";
  47. }
  48. });
  49. $.fn.fmatter = function(formatType, cellval, opts, rwd, act) {
  50. // build main options before element iteration
  51. var v=cellval;
  52. opts = $.extend({}, $.jgrid.formatter, opts);
  53. try {
  54. v = $.fn.fmatter[formatType].call(this, cellval, opts, rwd, act);
  55. } catch(fe){}
  56. return v;
  57. };
  58. $.fmatter.util = {
  59. // Taken from YAHOO utils
  60. NumberFormat : function(nData,opts) {
  61. if(!$.fmatter.isNumber(nData)) {
  62. nData *= 1;
  63. }
  64. if($.fmatter.isNumber(nData)) {
  65. var bNegative = (nData < 0);
  66. var sOutput = String(nData);
  67. var sDecimalSeparator = opts.decimalSeparator || ".";
  68. var nDotIndex;
  69. if($.fmatter.isNumber(opts.decimalPlaces)) {
  70. // Round to the correct decimal place
  71. var nDecimalPlaces = opts.decimalPlaces;
  72. var nDecimal = Math.pow(10, nDecimalPlaces);
  73. sOutput = String(Math.round(nData*nDecimal)/nDecimal);
  74. nDotIndex = sOutput.lastIndexOf(".");
  75. if(nDecimalPlaces > 0) {
  76. // Add the decimal separator
  77. if(nDotIndex < 0) {
  78. sOutput += sDecimalSeparator;
  79. nDotIndex = sOutput.length-1;
  80. }
  81. // Replace the "."
  82. else if(sDecimalSeparator !== "."){
  83. sOutput = sOutput.replace(".",sDecimalSeparator);
  84. }
  85. // Add missing zeros
  86. while((sOutput.length - 1 - nDotIndex) < nDecimalPlaces) {
  87. sOutput += "0";
  88. }
  89. }
  90. }
  91. if(opts.thousandsSeparator) {
  92. var sThousandsSeparator = opts.thousandsSeparator;
  93. nDotIndex = sOutput.lastIndexOf(sDecimalSeparator);
  94. nDotIndex = (nDotIndex > -1) ? nDotIndex : sOutput.length;
  95. var sNewOutput = sOutput.substring(nDotIndex);
  96. var nCount = -1, i;
  97. for (i=nDotIndex; i>0; i--) {
  98. nCount++;
  99. if ((nCount%3 === 0) && (i !== nDotIndex) && (!bNegative || (i > 1))) {
  100. sNewOutput = sThousandsSeparator + sNewOutput;
  101. }
  102. sNewOutput = sOutput.charAt(i-1) + sNewOutput;
  103. }
  104. sOutput = sNewOutput;
  105. }
  106. // Prepend prefix
  107. sOutput = (opts.prefix) ? opts.prefix + sOutput : sOutput;
  108. // Append suffix
  109. sOutput = (opts.suffix) ? sOutput + opts.suffix : sOutput;
  110. return sOutput;
  111. }
  112. return nData;
  113. }
  114. };
  115. $.fn.fmatter.defaultFormat = function(cellval, opts) {
  116. return ($.fmatter.isValue(cellval) && cellval!=="" ) ? cellval : opts.defaultValue || "&#160;";
  117. };
  118. $.fn.fmatter.email = function(cellval, opts) {
  119. if(!$.fmatter.isEmpty(cellval)) {
  120. return "<a href=\"mailto:" + cellval + "\">" + cellval + "</a>";
  121. }
  122. return $.fn.fmatter.defaultFormat(cellval,opts );
  123. };
  124. $.fn.fmatter.checkbox =function(cval, opts) {
  125. var op = $.extend({},opts.checkbox), ds;
  126. if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
  127. op = $.extend({},op,opts.colModel.formatoptions);
  128. }
  129. if(op.disabled===true) {ds = "disabled=\"disabled\"";} else {ds="";}
  130. if($.fmatter.isEmpty(cval) || cval === undefined ) {cval = $.fn.fmatter.defaultFormat(cval,op);}
  131. cval=String(cval);
  132. cval=(cval+"").toLowerCase();
  133. var bchk = cval.search(/(false|f|0|no|n|off|undefined)/i)<0 ? " checked='checked' " : "";
  134. return "<input type=\"checkbox\" " + bchk + " value=\""+ cval+"\" offval=\"no\" "+ds+ "/>";
  135. };
  136. $.fn.fmatter.link = function(cellval, opts) {
  137. var op = {target:opts.target};
  138. var target = "";
  139. if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
  140. op = $.extend({},op,opts.colModel.formatoptions);
  141. }
  142. if(op.target) {target = 'target=' + op.target;}
  143. if(!$.fmatter.isEmpty(cellval)) {
  144. return "<a "+target+" href=\"" + cellval + "\">" + cellval + "</a>";
  145. }
  146. return $.fn.fmatter.defaultFormat(cellval,opts);
  147. };
  148. $.fn.fmatter.showlink = function(cellval, opts) {
  149. var op = {baseLinkUrl: opts.baseLinkUrl,showAction:opts.showAction, addParam: opts.addParam || "", target: opts.target, idName: opts.idName},
  150. target = "", idUrl;
  151. if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
  152. op = $.extend({},op,opts.colModel.formatoptions);
  153. }
  154. if(op.target) {target = 'target=' + op.target;}
  155. idUrl = op.baseLinkUrl+op.showAction + '?'+ op.idName+'='+opts.rowId+op.addParam;
  156. if($.fmatter.isString(cellval) || $.fmatter.isNumber(cellval)) { //add this one even if its blank string
  157. return "<a "+target+" href=\"" + idUrl + "\">" + cellval + "</a>";
  158. }
  159. return $.fn.fmatter.defaultFormat(cellval,opts);
  160. };
  161. $.fn.fmatter.integer = function(cellval, opts) {
  162. var op = $.extend({},opts.integer);
  163. if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
  164. op = $.extend({},op,opts.colModel.formatoptions);
  165. }
  166. if($.fmatter.isEmpty(cellval)) {
  167. return op.defaultValue;
  168. }
  169. return $.fmatter.util.NumberFormat(cellval,op);
  170. };
  171. $.fn.fmatter.number = function (cellval, opts) {
  172. var op = $.extend({},opts.number);
  173. if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
  174. op = $.extend({},op,opts.colModel.formatoptions);
  175. }
  176. if($.fmatter.isEmpty(cellval)) {
  177. return op.defaultValue;
  178. }
  179. return $.fmatter.util.NumberFormat(cellval,op);
  180. };
  181. $.fn.fmatter.currency = function (cellval, opts) {
  182. var op = $.extend({},opts.currency);
  183. if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
  184. op = $.extend({},op,opts.colModel.formatoptions);
  185. }
  186. if($.fmatter.isEmpty(cellval)) {
  187. return op.defaultValue;
  188. }
  189. return $.fmatter.util.NumberFormat(cellval,op);
  190. };
  191. $.fn.fmatter.date = function (cellval, opts, rwd, act) {
  192. var op = $.extend({},opts.date);
  193. if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
  194. op = $.extend({},op,opts.colModel.formatoptions);
  195. }
  196. if(!op.reformatAfterEdit && act === 'edit'){
  197. return $.fn.fmatter.defaultFormat(cellval, opts);
  198. }
  199. if(!$.fmatter.isEmpty(cellval)) {
  200. return $.jgrid.parseDate(op.srcformat,cellval,op.newformat,op);
  201. }
  202. return $.fn.fmatter.defaultFormat(cellval, opts);
  203. };
  204. $.fn.fmatter.select = function (cellval,opts) {
  205. // jqGrid specific
  206. cellval = String(cellval);
  207. var oSelect = false, ret=[], sep, delim;
  208. if(opts.colModel.formatoptions !== undefined){
  209. oSelect= opts.colModel.formatoptions.value;
  210. sep = opts.colModel.formatoptions.separator === undefined ? ":" : opts.colModel.formatoptions.separator;
  211. delim = opts.colModel.formatoptions.delimiter === undefined ? ";" : opts.colModel.formatoptions.delimiter;
  212. } else if(opts.colModel.editoptions !== undefined){
  213. oSelect= opts.colModel.editoptions.value;
  214. sep = opts.colModel.editoptions.separator === undefined ? ":" : opts.colModel.editoptions.separator;
  215. delim = opts.colModel.editoptions.delimiter === undefined ? ";" : opts.colModel.editoptions.delimiter;
  216. }
  217. if (oSelect) {
  218. var msl = (opts.colModel.editoptions != null && opts.colModel.editoptions.multiple === true) === true ? true : false,
  219. scell = [], sv;
  220. if(msl) {scell = cellval.split(",");scell = $.map(scell,function(n){return $.trim(n);});}
  221. if ($.fmatter.isString(oSelect)) {
  222. // mybe here we can use some caching with care ????
  223. var so = oSelect.split(delim), j=0, i;
  224. for(i=0; i<so.length;i++){
  225. sv = so[i].split(sep);
  226. if(sv.length > 2 ) {
  227. sv[1] = $.map(sv,function(n,i){if(i>0) {return n;}}).join(sep);
  228. }
  229. if(msl) {
  230. if($.inArray(sv[0],scell)>-1) {
  231. ret[j] = sv[1];
  232. j++;
  233. }
  234. } else if($.trim(sv[0]) === $.trim(cellval)) {
  235. ret[0] = sv[1];
  236. break;
  237. }
  238. }
  239. } else if($.fmatter.isObject(oSelect)) {
  240. // this is quicker
  241. if(msl) {
  242. ret = $.map(scell, function(n){
  243. return oSelect[n];
  244. });
  245. } else {
  246. ret[0] = oSelect[cellval] || "";
  247. }
  248. }
  249. }
  250. cellval = ret.join(", ");
  251. return cellval === "" ? $.fn.fmatter.defaultFormat(cellval,opts) : cellval;
  252. };
  253. $.fn.fmatter.rowactions = function(act) {
  254. var $tr = $(this).closest("tr.jqgrow"),
  255. rid = $tr.attr("id"),
  256. $id = $(this).closest("table.ui-jqgrid-btable").attr('id').replace(/_frozen([^_]*)$/,'$1'),
  257. $grid = $("#"+$id),
  258. $t = $grid[0],
  259. p = $t.p,
  260. cm = p.colModel[$.jgrid.getCellIndex(this)],
  261. $actionsDiv = cm.frozen ? $("tr#"+rid+" td:eq("+$.jgrid.getCellIndex(this)+") > div",$grid) :$(this).parent(),
  262. op = {
  263. extraparam: {}
  264. },
  265. saverow = function(rowid, res) {
  266. if($.isFunction(op.afterSave)) { op.afterSave.call($t, rowid, res); }
  267. $actionsDiv.find("div.ui-inline-edit,div.ui-inline-del").show();
  268. $actionsDiv.find("div.ui-inline-save,div.ui-inline-cancel").hide();
  269. },
  270. restorerow = function(rowid) {
  271. if($.isFunction(op.afterRestore)) { op.afterRestore.call($t, rowid); }
  272. $actionsDiv.find("div.ui-inline-edit,div.ui-inline-del").show();
  273. $actionsDiv.find("div.ui-inline-save,div.ui-inline-cancel").hide();
  274. };
  275. if (cm.formatoptions !== undefined) {
  276. op = $.extend(op,cm.formatoptions);
  277. }
  278. if (p.editOptions !== undefined) {
  279. op.editOptions = p.editOptions;
  280. }
  281. if (p.delOptions !== undefined) {
  282. op.delOptions = p.delOptions;
  283. }
  284. if ($tr.hasClass("jqgrid-new-row")){
  285. op.extraparam[p.prmNames.oper] = p.prmNames.addoper;
  286. }
  287. var actop = {
  288. keys: op.keys,
  289. oneditfunc: op.onEdit,
  290. successfunc: op.onSuccess,
  291. url: op.url,
  292. extraparam: op.extraparam,
  293. aftersavefunc: saverow,
  294. errorfunc: op.onError,
  295. afterrestorefunc: restorerow,
  296. restoreAfterError: op.restoreAfterError,
  297. mtype: op.mtype
  298. };
  299. switch(act)
  300. {
  301. case 'edit':
  302. $grid.jqGrid('editRow', rid, actop);
  303. $actionsDiv.find("div.ui-inline-edit,div.ui-inline-del").hide();
  304. $actionsDiv.find("div.ui-inline-save,div.ui-inline-cancel").show();
  305. $grid.triggerHandler("jqGridAfterGridComplete");
  306. break;
  307. case 'save':
  308. if ($grid.jqGrid('saveRow', rid, actop)) {
  309. $actionsDiv.find("div.ui-inline-edit,div.ui-inline-del").show();
  310. $actionsDiv.find("div.ui-inline-save,div.ui-inline-cancel").hide();
  311. $grid.triggerHandler("jqGridAfterGridComplete");
  312. }
  313. break;
  314. case 'cancel' :
  315. $grid.jqGrid('restoreRow', rid, restorerow);
  316. $actionsDiv.find("div.ui-inline-edit,div.ui-inline-del").show();
  317. $actionsDiv.find("div.ui-inline-save,div.ui-inline-cancel").hide();
  318. $grid.triggerHandler("jqGridAfterGridComplete");
  319. break;
  320. case 'del':
  321. $grid.jqGrid('delGridRow', rid, op.delOptions);
  322. break;
  323. case 'formedit':
  324. $grid.jqGrid('setSelection', rid);
  325. $grid.jqGrid('editGridRow', rid, op.editOptions);
  326. break;
  327. }
  328. };
  329. $.fn.fmatter.actions = function(cellval,opts) {
  330. var op={keys:false, editbutton:true, delbutton:true, editformbutton: false},
  331. rowid=opts.rowId, str="",ocl;
  332. if(opts.colModel.formatoptions !== undefined) {
  333. op = $.extend(op,opts.colModel.formatoptions);
  334. }
  335. if(rowid === undefined || $.fmatter.isEmpty(rowid)) {return "";}
  336. if(op.editformbutton){
  337. ocl = "id='jEditButton_"+rowid+"' onclick=jQuery.fn.fmatter.rowactions.call(this,'formedit'); onmouseover=jQuery(this).addClass('ui-state-hover'); onmouseout=jQuery(this).removeClass('ui-state-hover'); ";
  338. str += "<div title='"+$.jgrid.nav.edittitle+"' style='float:left;cursor:pointer;' class='ui-pg-div ui-inline-edit' "+ocl+"><span class='ui-icon ui-icon-pencil'></span></div>";
  339. } else if(op.editbutton){
  340. ocl = "id='jEditButton_"+rowid+"' onclick=jQuery.fn.fmatter.rowactions.call(this,'edit'); onmouseover=jQuery(this).addClass('ui-state-hover'); onmouseout=jQuery(this).removeClass('ui-state-hover') ";
  341. str += "<div title='"+$.jgrid.nav.edittitle+"' style='float:left;cursor:pointer;' class='ui-pg-div ui-inline-edit' "+ocl+"><span class='ui-icon ui-icon-pencil'></span></div>";
  342. }
  343. if(op.delbutton) {
  344. ocl = "id='jDeleteButton_"+rowid+"' onclick=jQuery.fn.fmatter.rowactions.call(this,'del'); onmouseover=jQuery(this).addClass('ui-state-hover'); onmouseout=jQuery(this).removeClass('ui-state-hover'); ";
  345. str += "<div title='"+$.jgrid.nav.deltitle+"' style='float:left;margin-left:5px;' class='ui-pg-div ui-inline-del' "+ocl+"><span class='ui-icon ui-icon-trash'></span></div>";
  346. }
  347. ocl = "id='jSaveButton_"+rowid+"' onclick=jQuery.fn.fmatter.rowactions.call(this,'save'); onmouseover=jQuery(this).addClass('ui-state-hover'); onmouseout=jQuery(this).removeClass('ui-state-hover'); ";
  348. str += "<div title='"+$.jgrid.edit.bSubmit+"' style='float:left;display:none' class='ui-pg-div ui-inline-save' "+ocl+"><span class='ui-icon ui-icon-disk'></span></div>";
  349. ocl = "id='jCancelButton_"+rowid+"' onclick=jQuery.fn.fmatter.rowactions.call(this,'cancel'); onmouseover=jQuery(this).addClass('ui-state-hover'); onmouseout=jQuery(this).removeClass('ui-state-hover'); ";
  350. str += "<div title='"+$.jgrid.edit.bCancel+"' style='float:left;display:none;margin-left:5px;' class='ui-pg-div ui-inline-cancel' "+ocl+"><span class='ui-icon ui-icon-cancel'></span></div>";
  351. return "<div style='margin-left:8px;'>" + str + "</div>";
  352. };
  353. $.unformat = function (cellval,options,pos,cnt) {
  354. // specific for jqGrid only
  355. var ret, formatType = options.colModel.formatter,
  356. op =options.colModel.formatoptions || {}, sep,
  357. re = /([\.\*\_\'\(\)\{\}\+\?\\])/g,
  358. unformatFunc = options.colModel.unformat||($.fn.fmatter[formatType] && $.fn.fmatter[formatType].unformat);
  359. if(unformatFunc !== undefined && $.isFunction(unformatFunc) ) {
  360. ret = unformatFunc.call(this, $(cellval).text(), options, cellval);
  361. } else if(formatType !== undefined && $.fmatter.isString(formatType) ) {
  362. var opts = $.jgrid.formatter || {}, stripTag;
  363. switch(formatType) {
  364. case 'integer' :
  365. op = $.extend({},opts.integer,op);
  366. sep = op.thousandsSeparator.replace(re,"\\$1");
  367. stripTag = new RegExp(sep, "g");
  368. ret = $(cellval).text().replace(stripTag,'');
  369. break;
  370. case 'number' :
  371. op = $.extend({},opts.number,op);
  372. sep = op.thousandsSeparator.replace(re,"\\$1");
  373. stripTag = new RegExp(sep, "g");
  374. ret = $(cellval).text().replace(stripTag,"").replace(op.decimalSeparator,'.');
  375. break;
  376. case 'currency':
  377. op = $.extend({},opts.currency,op);
  378. sep = op.thousandsSeparator.replace(re,"\\$1");
  379. stripTag = new RegExp(sep, "g");
  380. ret = $(cellval).text();
  381. if (op.prefix && op.prefix.length) {
  382. ret = ret.substr(op.prefix.length);
  383. }
  384. if (op.suffix && op.suffix.length) {
  385. ret = ret.substr(0, ret.length - op.suffix.length);
  386. }
  387. ret = ret.replace(stripTag,'').replace(op.decimalSeparator,'.');
  388. break;
  389. case 'checkbox':
  390. var cbv = (options.colModel.editoptions) ? options.colModel.editoptions.value.split(":") : ["Yes","No"];
  391. ret = $('input',cellval).is(":checked") ? cbv[0] : cbv[1];
  392. break;
  393. case 'select' :
  394. ret = $.unformat.select(cellval,options,pos,cnt);
  395. break;
  396. case 'actions':
  397. return "";
  398. default:
  399. ret= $(cellval).text();
  400. }
  401. }
  402. return ret !== undefined ? ret : cnt===true ? $(cellval).text() : $.jgrid.htmlDecode($(cellval).html());
  403. };
  404. $.unformat.select = function (cellval,options,pos,cnt) {
  405. // Spacial case when we have local data and perform a sort
  406. // cnt is set to true only in sortDataArray
  407. var ret = [];
  408. var cell = $(cellval).text();
  409. if(cnt===true) {return cell;}
  410. var op = $.extend({}, options.colModel.formatoptions !== undefined ? options.colModel.formatoptions: options.colModel.editoptions),
  411. sep = op.separator === undefined ? ":" : op.separator,
  412. delim = op.delimiter === undefined ? ";" : op.delimiter;
  413. if(op.value){
  414. var oSelect = op.value,
  415. msl = op.multiple === true ? true : false,
  416. scell = [], sv;
  417. if(msl) {scell = cell.split(",");scell = $.map(scell,function(n){return $.trim(n);});}
  418. if ($.fmatter.isString(oSelect)) {
  419. var so = oSelect.split(delim), j=0, i;
  420. for(i=0; i<so.length;i++){
  421. sv = so[i].split(sep);
  422. if(sv.length > 2 ) {
  423. sv[1] = $.map(sv,function(n,i){if(i>0) {return n;}}).join(sep);
  424. }
  425. if(msl) {
  426. if($.inArray(sv[1],scell)>-1) {
  427. ret[j] = sv[0];
  428. j++;
  429. }
  430. } else if($.trim(sv[1]) === $.trim(cell)) {
  431. ret[0] = sv[0];
  432. break;
  433. }
  434. }
  435. } else if($.fmatter.isObject(oSelect) || $.isArray(oSelect) ){
  436. if(!msl) {scell[0] = cell;}
  437. ret = $.map(scell, function(n){
  438. var rv;
  439. $.each(oSelect, function(i,val){
  440. if (val === n) {
  441. rv = i;
  442. return false;
  443. }
  444. });
  445. if( rv !== undefined ) {return rv;}
  446. });
  447. }
  448. return ret.join(", ");
  449. }
  450. return cell || "";
  451. };
  452. $.unformat.date = function (cellval, opts) {
  453. var op = $.jgrid.formatter.date || {};
  454. if(opts.formatoptions !== undefined) {
  455. op = $.extend({},op,opts.formatoptions);
  456. }
  457. if(!$.fmatter.isEmpty(cellval)) {
  458. return $.jgrid.parseDate(op.newformat,cellval,op.srcformat,op);
  459. }
  460. return $.fn.fmatter.defaultFormat(cellval, opts);
  461. };
  462. })(jQuery);