utils.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. // Some general purpose JS functions for the iTop application
  2. //IE 8 compatibility, copied from: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/IndexOf
  3. if (!Array.prototype.indexOf) {
  4. Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
  5. "use strict";
  6. if (this == null) {
  7. throw new TypeError();
  8. }
  9. var t = Object(this);
  10. var len = t.length >>> 0;
  11. if (len === 0) {
  12. return -1;
  13. }
  14. var n = 0;
  15. if (arguments.length > 1) {
  16. n = Number(arguments[1]);
  17. if (n != n) { // shortcut for verifying if it's NaN
  18. n = 0;
  19. } else if (n != 0 && n != Infinity && n != -Infinity) {
  20. n = (n > 0 || -1) * Math.floor(Math.abs(n));
  21. }
  22. }
  23. if (n >= len) {
  24. return -1;
  25. }
  26. var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
  27. for (; k < len; k++) {
  28. if (k in t && t[k] === searchElement) {
  29. return k;
  30. }
  31. }
  32. return -1;
  33. }
  34. }
  35. /**
  36. * Reload a truncated list
  37. */
  38. aTruncatedLists = {}; // To keep track of the list being loaded, each member is an ajaxRequest object
  39. function ReloadTruncatedList(divId, sSerializedFilter, sExtraParams)
  40. {
  41. $('#'+divId).block();
  42. //$('#'+divId).blockUI();
  43. if (aTruncatedLists[divId] != undefined)
  44. {
  45. try
  46. {
  47. aAjaxRequest = aTruncatedLists[divId];
  48. aAjaxRequest.abort();
  49. }
  50. catch(e)
  51. {
  52. // Do nothing special, just continue
  53. console.log('Uh,uh, exception !');
  54. }
  55. }
  56. aTruncatedLists[divId] = $.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?style=list',
  57. { operation: 'ajax', filter: sSerializedFilter, extra_params: sExtraParams },
  58. function(data)
  59. {
  60. aTruncatedLists[divId] = undefined;
  61. if (data.length > 0)
  62. {
  63. $('#'+divId).html(data);
  64. $('#'+divId+' .listResults').tableHover(); // hover tables
  65. $('#'+divId+' .listResults').each( function()
  66. {
  67. var table = $(this);
  68. var id = $(this).parent();
  69. aTruncatedLists[divId] = undefined;
  70. var checkbox = (table.find('th:first :checkbox').length > 0);
  71. if (checkbox)
  72. {
  73. // There is a checkbox in the first column, don't make it sortable
  74. table.tablesorter( { headers: { 0: {sorter: false}}, widgets: ['myZebra', 'truncatedList']} ).tablesorterPager({container: $("#pager")}); // sortable and zebra tables
  75. }
  76. else
  77. {
  78. // There is NO checkbox in the first column, all columns are considered sortable
  79. table.tablesorter( { widgets: ['myZebra', 'truncatedList']} ).tablesorterPager({container: $("#pager"), totalRows:97, filter: sSerializedFilter, extra_params: sExtraParams }); // sortable and zebra tables
  80. }
  81. });
  82. $('#'+divId).unblock();
  83. }
  84. }
  85. );
  86. }
  87. /**
  88. * Truncate a previously expanded list !
  89. */
  90. function TruncateList(divId, iLimit, sNewLabel, sLinkLabel)
  91. {
  92. $('#'+divId).block();
  93. var iCount = 0;
  94. $('#'+divId+' table.listResults tr:gt('+iLimit+')').each( function(){
  95. $(this).remove();
  96. });
  97. $('#lbl_'+divId).html(sNewLabel);
  98. $('#'+divId+' table.listResults tr:last td').addClass('truncated');
  99. $('#'+divId+' table.listResults').addClass('truncated');
  100. $('#trc_'+divId).html(sLinkLabel);
  101. $('#'+divId+' .listResults').trigger("update"); // Reset the cache
  102. $('#'+divId).unblock();
  103. }
  104. /**
  105. * Reload any block -- used for periodic auto-reload
  106. */
  107. function ReloadBlock(divId, sStyle, sSerializedFilter, sExtraParams)
  108. {
  109. // Check if the user is not editing the list properties right now
  110. var bDialogOpen = false;
  111. var oDataTable = $('#'+divId+' :itop-datatable');
  112. if (oDataTable.length > 0)
  113. {
  114. bDialogOpen = oDataTable.datatable('IsDialogOpen');
  115. }
  116. if (!bDialogOpen)
  117. {
  118. $('#'+divId).block();
  119. $.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?style='+sStyle,
  120. { operation: 'ajax', filter: sSerializedFilter, extra_params: sExtraParams },
  121. function(data){
  122. $('#'+divId).empty();
  123. $('#'+divId).append(data);
  124. $('#'+divId).removeClass('loading');
  125. }
  126. );
  127. }
  128. }
  129. /**
  130. * Update the display and value of a file input widget when the user picks a new file
  131. */
  132. function UpdateFileName(id, sNewFileName)
  133. {
  134. var aPath = sNewFileName.split('\\');
  135. var sNewFileName = aPath[aPath.length-1];
  136. $('#'+id).val(sNewFileName);
  137. $('#'+id).trigger('validate');
  138. $('#name_'+id).text(sNewFileName);
  139. return true;
  140. }
  141. /**
  142. * Reload a search form for the specified class
  143. */
  144. function ReloadSearchForm(divId, sClassName, sBaseClass, sContext)
  145. {
  146. var oDiv = $('#ds_'+divId);
  147. oDiv.block();
  148. // deprecated in jQuery 1.8
  149. //var oFormEvents = $('#ds_'+divId+' form').data('events');
  150. var oForm = $('#ds_'+divId+' form');
  151. var oFormEvents = $._data(oForm[0], "events");
  152. // Save the submit handlers
  153. aSubmit = new Array();
  154. if ( (oFormEvents != null) && (oFormEvents.submit != undefined))
  155. {
  156. for(var index = 0; index < oFormEvents.submit.length; index++)
  157. {
  158. aSubmit [index ] = { data:oFormEvents.submit[index].data, namespace:oFormEvents.submit[index].namespace, handler: oFormEvents.submit[index].handler};
  159. }
  160. }
  161. sAction = $('#ds_'+divId+' form').attr('action');
  162. // Save the current values in the form
  163. var oMap = {};
  164. $('#ds_'+divId+" form :input[name!='']").each(function() {
  165. oMap[this.name] = this.value;
  166. });
  167. oMap.operation = 'search_form';
  168. oMap.className = sClassName;
  169. oMap.baseClass = sBaseClass;
  170. oMap.currentId = divId;
  171. oMap.action = sAction;
  172. $.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?'+sContext, oMap,
  173. function(data) {
  174. oDiv.empty();
  175. oDiv.append(data);
  176. if (aSubmit.length > 0)
  177. {
  178. var oForm = $('#ds_'+divId+' form'); // Form was reloaded, recompute it
  179. for(var index = 0; index < aSubmit.length; index++)
  180. {
  181. // Restore the previously bound submit handlers
  182. if (aSubmit[index].data != undefined)
  183. {
  184. oForm.bind('submit.'+aSubmit[index].namespace, aSubmit[index].data, aSubmit[index].handler)
  185. }
  186. else
  187. {
  188. oForm.bind('submit.'+aSubmit[index].namespace, aSubmit[index].handler)
  189. }
  190. }
  191. }
  192. oDiv.unblock();
  193. oDiv.parent().resize(); // Inform the parent that the form has just been (potentially) resized
  194. }
  195. );
  196. }
  197. /**
  198. * Stores - in a persistent way - user specific preferences
  199. * depends on a global variable oUserPreferences created/filled by the iTopWebPage
  200. * that acts as a local -write through- cache
  201. */
  202. function SetUserPreference(sPreferenceCode, sPrefValue, bPersistent)
  203. {
  204. sPreviousValue = undefined;
  205. try
  206. {
  207. sPreviousValue = oUserPreferences[sPreferenceCode];
  208. }
  209. catch(err)
  210. {
  211. sPreviousValue = undefined;
  212. }
  213. oUserPreferences[sPreferenceCode] = sPrefValue;
  214. if (bPersistent && (sPrefValue != sPreviousValue))
  215. {
  216. ajax_request = $.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
  217. { operation: 'set_pref', code: sPreferenceCode, value: sPrefValue} ); // Make it persistent
  218. }
  219. }
  220. /**
  221. * Get user specific preferences
  222. * depends on a global variable oUserPreferences created/filled by the iTopWebPage
  223. * that acts as a local -write through- cache
  224. */
  225. function GetUserPreference(sPreferenceCode, sDefaultValue)
  226. {
  227. var value = sDefaultValue;
  228. if ( oUserPreferences[sPreferenceCode] != undefined)
  229. {
  230. value = oUserPreferences[sPreferenceCode];
  231. }
  232. return value;
  233. }
  234. /**
  235. * Check/uncheck a whole list of checkboxes
  236. */
  237. function CheckAll(sSelector, bValue)
  238. {
  239. var value = bValue;
  240. $(sSelector).each( function() {
  241. if (this.checked != value)
  242. {
  243. this.checked = value;
  244. $(this).trigger('change');
  245. }
  246. });
  247. }
  248. /**
  249. * Toggle (enabled/disabled) the specified field of a form
  250. */
  251. function ToogleField(value, field_id)
  252. {
  253. if (value)
  254. {
  255. $('#'+field_id).removeAttr('disabled');
  256. }
  257. else
  258. {
  259. $('#'+field_id).attr('disabled', 'disabled');
  260. }
  261. $('#'+field_id).trigger('update');
  262. $('#'+field_id).trigger('validate');
  263. }
  264. /**
  265. * For the fields that cannot be visually disabled, they can be blocked
  266. * @return
  267. */
  268. function BlockField(field_id, bBlocked)
  269. {
  270. if (bBlocked)
  271. {
  272. $('#'+field_id).block({ message: ' ** disabled ** '});
  273. }
  274. else
  275. {
  276. $('#'+field_id).unblock();
  277. }
  278. }
  279. /**
  280. * Updates (enables/disables) a "duration" field
  281. */
  282. function ToggleDurationField(field_id)
  283. {
  284. // Toggle all the subfields that compose the "duration" input
  285. aSubFields = new Array('d', 'h', 'm', 's');
  286. if ($('#'+field_id).attr('disabled'))
  287. {
  288. for(var i=0; i<aSubFields.length; i++)
  289. {
  290. $('#'+field_id+'_'+aSubFields[i]).attr('disabled', 'disabled');
  291. }
  292. }
  293. else
  294. {
  295. for(var i=0; i<aSubFields.length; i++)
  296. {
  297. $('#'+field_id+'_'+aSubFields[i]).removeAttr('disabled');
  298. }
  299. }
  300. }
  301. /**
  302. * PropagateCheckBox
  303. */
  304. function PropagateCheckBox(bCurrValue, aFieldsList, bCheck)
  305. {
  306. if (bCurrValue == bCheck)
  307. {
  308. for(var i=0;i<aFieldsList.length;i++)
  309. {
  310. $('#enable_'+aFieldsList[i]).attr('checked', bCheck);
  311. ToogleField(bCheck, aFieldsList[i]);
  312. }
  313. }
  314. }
  315. function FixTableSorter(table)
  316. {
  317. if ($('th.header', table).length == 0)
  318. {
  319. // Table is not sort-able, let's fix it
  320. var checkbox = (table.find('th:first :checkbox').length > 0);
  321. if (checkbox)
  322. {
  323. // There is a checkbox in the first column, don't make it sort-able
  324. table.tablesorter( { headers: { 0: {sorter: false}}, widgets: ['myZebra', 'truncatedList']} ); // sort-able and zebra tables
  325. }
  326. else
  327. {
  328. // There is NO checkbox in the first column, all columns are considered sort-able
  329. table.tablesorter( { widgets: ['myZebra', 'truncatedList']} ); // sort-able and zebra tables
  330. }
  331. }
  332. }
  333. function DashletCreationDlg(sOQL)
  334. {
  335. $.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'dashlet_creation_dlg', oql: sOQL}, function(data){
  336. $('body').append(data);
  337. });
  338. return false;
  339. }
  340. function ShortcutListDlg(sOQL, sContext)
  341. {
  342. $.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?'+sContext, {operation: 'shortcut_list_dlg', oql: sOQL}, function(data){
  343. $('body').append(data);
  344. });
  345. return false;
  346. }