jquery.yiigridview.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /**
  2. * jQuery Yii GridView plugin file.
  3. *
  4. * @author Qiang Xue <qiang.xue@gmail.com>
  5. * @link http://www.yiiframework.com/
  6. * @copyright 2008-2010 Yii Software LLC
  7. * @license http://www.yiiframework.com/license/
  8. */
  9. (function ($) {
  10. var selectCheckedRows, methods,
  11. yiiXHR={},
  12. gridSettings = [];
  13. /**
  14. * 1. Selects rows that have checkbox checked (only checkbox that is connected with selecting a row)
  15. * 2. Check if "check all" need to be checked/unchecked
  16. * @return object the jQuery object
  17. */
  18. selectCheckedRows = function (gridId) {
  19. var settings = gridSettings[gridId],
  20. table = $('#' + gridId).find('.' + settings.tableClass);
  21. table.children('tbody').find('input.select-on-check').filter(':checked').each(function () {
  22. $(this).closest('tr').addClass('selected');
  23. });
  24. table.children('thead').find('th input').filter('[type="checkbox"]').each(function () {
  25. var name = this.name.substring(0, this.name.length - 4) + '[]', //.. remove '_all' and add '[]''
  26. $checks = $("input[name='" + name + "']", table);
  27. this.checked = $checks.length > 0 && $checks.length === $checks.filter(':checked').length;
  28. });
  29. return this;
  30. };
  31. methods = {
  32. /**
  33. * yiiGridView set function.
  34. * @param options map settings for the grid view. Available options are as follows:
  35. * - ajaxUpdate: array, IDs of the containers whose content may be updated by ajax response
  36. * - ajaxVar: string, the name of the request variable indicating the ID of the element triggering the AJAX request
  37. * - ajaxType: string, the type (GET or POST) of the AJAX request
  38. * - pagerClass: string, the CSS class for the pager container
  39. * - tableClass: string, the CSS class for the table
  40. * - selectableRows: integer, the number of rows that can be selected
  41. * - updateSelector: string, the selector for choosing which elements can trigger ajax requests
  42. * - beforeAjaxUpdate: function, the function to be called before ajax request is sent
  43. * - afterAjaxUpdate: function, the function to be called after ajax response is received
  44. * - ajaxUpdateError: function, the function to be called if an ajax error occurs
  45. * - selectionChanged: function, the function to be called after the row selection is changed
  46. * @return object the jQuery object
  47. */
  48. init: function (options) {
  49. var settings = $.extend({
  50. ajaxUpdate: [],
  51. ajaxVar: 'ajax',
  52. ajaxType: 'GET',
  53. pagerClass: 'pager',
  54. loadingClass: 'loading',
  55. filterClass: 'filters',
  56. tableClass: 'items',
  57. selectableRows: 1
  58. // updateSelector: '#id .pager a, '#id .grid thead th a',
  59. // beforeAjaxUpdate: function (id) {},
  60. // afterAjaxUpdate: function (id, data) {},
  61. // selectionChanged: function (id) {},
  62. // url: 'ajax request URL'
  63. }, options || {});
  64. settings.tableClass = settings.tableClass.replace(/\s+/g, '.');
  65. return this.each(function () {
  66. var eventType,
  67. $grid = $(this),
  68. id = $grid.attr('id'),
  69. pagerSelector = '#' + id + ' .' + settings.pagerClass.replace(/\s+/g, '.') + ' a',
  70. sortSelector = '#' + id + ' .' + settings.tableClass + ' thead th a.sort-link',
  71. inputSelector = '#' + id + ' .' + settings.filterClass + ' input, ' + '#' + id + ' .' + settings.filterClass + ' select';
  72. settings.updateSelector = settings.updateSelector
  73. .replace('{page}', pagerSelector)
  74. .replace('{sort}', sortSelector);
  75. settings.filterSelector = settings.filterSelector
  76. .replace('{filter}', inputSelector);
  77. gridSettings[id] = settings;
  78. if (settings.ajaxUpdate.length > 0) {
  79. $(document).on('click.yiiGridView', settings.updateSelector, function () {
  80. // Check to see if History.js is enabled for our Browser
  81. if (settings.enableHistory && window.History.enabled) {
  82. // Ajaxify this link
  83. var url = $(this).attr('href').split('?'),
  84. params = $.deparam.querystring('?'+ (url[1] || ''));
  85. delete params[settings.ajaxVar];
  86. window.History.pushState(null, document.title, decodeURIComponent($.param.querystring(url[0], params)));
  87. } else {
  88. $('#' + id).yiiGridView('update', {url: $(this).attr('href')});
  89. }
  90. return false;
  91. });
  92. }
  93. $(document).on('change.yiiGridView keydown.yiiGridView', settings.filterSelector, function (event) {
  94. if (event.type === 'keydown') {
  95. if (event.keyCode !== 13) {
  96. return; // only react to enter key
  97. } else {
  98. eventType = 'keydown';
  99. }
  100. } else {
  101. // prevent processing for both keydown and change events
  102. if (eventType === 'keydown') {
  103. eventType = '';
  104. return;
  105. }
  106. }
  107. var data = $(settings.filterSelector).serialize();
  108. if (settings.pageVar !== undefined) {
  109. data += '&' + settings.pageVar + '=1';
  110. }
  111. if (settings.enableHistory && settings.ajaxUpdate !== false && window.History.enabled) {
  112. // Ajaxify this link
  113. var url = $('#' + id).yiiGridView('getUrl'),
  114. params = $.deparam.querystring($.param.querystring(url, data));
  115. delete params[settings.ajaxVar];
  116. window.History.pushState(null, document.title, decodeURIComponent($.param.querystring(url.substr(0, url.indexOf('?')), params)));
  117. } else {
  118. $('#' + id).yiiGridView('update', {data: data});
  119. }
  120. return false;
  121. });
  122. if (settings.enableHistory && settings.ajaxUpdate !== false && window.History.enabled) {
  123. $(window).bind('statechange', function() { // Note: We are using statechange instead of popstate
  124. var State = window.History.getState(); // Note: We are using History.getState() instead of event.state
  125. $('#' + id).yiiGridView('update', {url: State.url});
  126. });
  127. }
  128. if (settings.selectableRows > 0) {
  129. selectCheckedRows(this.id);
  130. $(document).on('click.yiiGridView', '#' + id + ' .' + settings.tableClass + ' > tbody > tr', function (e) {
  131. var $currentGrid, $row, isRowSelected, $checks,
  132. $target = $(e.target);
  133. if ($target.closest('td').is('.empty,.button-column') || (e.target.type === 'checkbox' && !$target.hasClass('select-on-check'))) {
  134. return;
  135. }
  136. $row = $(this);
  137. $currentGrid = $('#' + id);
  138. $checks = $('input.select-on-check', $currentGrid);
  139. isRowSelected = $row.toggleClass('selected').hasClass('selected');
  140. if (settings.selectableRows === 1) {
  141. $row.siblings().removeClass('selected');
  142. $checks.prop('checked', false);
  143. }
  144. $('input.select-on-check', $row).prop('checked', isRowSelected);
  145. $("input.select-on-check-all", $currentGrid).prop('checked', $checks.length === $checks.filter(':checked').length);
  146. if (settings.selectionChanged !== undefined) {
  147. settings.selectionChanged(id);
  148. }
  149. });
  150. if (settings.selectableRows > 1) {
  151. $(document).on('click.yiiGridView', '#' + id + ' .select-on-check-all', function () {
  152. var $currentGrid = $('#' + id),
  153. $checks = $('input.select-on-check', $currentGrid),
  154. $checksAll = $('input.select-on-check-all', $currentGrid),
  155. $rows = $currentGrid.find('.' + settings.tableClass).children('tbody').children();
  156. if (this.checked) {
  157. $rows.addClass('selected');
  158. $checks.prop('checked', true);
  159. $checksAll.prop('checked', true);
  160. } else {
  161. $rows.removeClass('selected');
  162. $checks.prop('checked', false);
  163. $checksAll.prop('checked', false);
  164. }
  165. if (settings.selectionChanged !== undefined) {
  166. settings.selectionChanged(id);
  167. }
  168. });
  169. }
  170. } else {
  171. $(document).on('click.yiiGridView', '#' + id + ' .select-on-check', false);
  172. }
  173. });
  174. },
  175. /**
  176. * Returns the key value for the specified row
  177. * @param row integer the row number (zero-based index)
  178. * @return string the key value
  179. */
  180. getKey: function (row) {
  181. return this.children('.keys').children('span').eq(row).text();
  182. },
  183. /**
  184. * Returns the URL that generates the grid view content.
  185. * @return string the URL that generates the grid view content.
  186. */
  187. getUrl: function () {
  188. var sUrl = gridSettings[this.attr('id')].url;
  189. return sUrl || this.children('.keys').attr('title');
  190. },
  191. /**
  192. * Returns the jQuery collection of the cells in the specified row.
  193. * @param row integer the row number (zero-based index)
  194. * @return jQuery the jQuery collection of the cells in the specified row.
  195. */
  196. getRow: function (row) {
  197. var sClass = gridSettings[this.attr('id')].tableClass;
  198. return this.find('.' + sClass).children('tbody').children('tr').eq(row).children();
  199. },
  200. /**
  201. * Returns the jQuery collection of the cells in the specified column.
  202. * @param column integer the column number (zero-based index)
  203. * @return jQuery the jQuery collection of the cells in the specified column.
  204. */
  205. getColumn: function (column) {
  206. var sClass = gridSettings[this.attr('id')].tableClass;
  207. return this.find('.' + sClass).children('tbody').children('tr').children('td:nth-child(' + (column + 1) + ')');
  208. },
  209. /**
  210. * Performs an AJAX-based update of the grid view contents.
  211. * @param options map the AJAX request options (see jQuery.ajax API manual). By default,
  212. * the URL to be requested is the one that generates the current content of the grid view.
  213. * @return object the jQuery object
  214. */
  215. update: function (options) {
  216. var customError;
  217. if (options && options.error !== undefined) {
  218. customError = options.error;
  219. delete options.error;
  220. }
  221. return this.each(function () {
  222. var $form,
  223. $grid = $(this),
  224. id = $grid.attr('id'),
  225. settings = gridSettings[id];
  226. options = $.extend({
  227. type: settings.ajaxType,
  228. url: $grid.yiiGridView('getUrl'),
  229. success: function (data) {
  230. var $data = $('<div>' + data + '</div>');
  231. $.each(settings.ajaxUpdate, function (i, el) {
  232. var updateId = '#' + el;
  233. $(updateId).replaceWith($(updateId, $data));
  234. });
  235. if (settings.afterAjaxUpdate !== undefined) {
  236. settings.afterAjaxUpdate(id, data);
  237. }
  238. if (settings.selectableRows > 0) {
  239. selectCheckedRows(id);
  240. }
  241. },
  242. complete: function () {
  243. yiiXHR[id] = null;
  244. $grid.removeClass(settings.loadingClass);
  245. },
  246. error: function (XHR, textStatus, errorThrown) {
  247. var ret, err;
  248. if (XHR.readyState === 0 || XHR.status === 0) {
  249. return;
  250. }
  251. if (customError !== undefined) {
  252. ret = customError(XHR);
  253. if (ret !== undefined && !ret) {
  254. return;
  255. }
  256. }
  257. switch (textStatus) {
  258. case 'timeout':
  259. err = 'The request timed out!';
  260. break;
  261. case 'parsererror':
  262. err = 'Parser error!';
  263. break;
  264. case 'error':
  265. if (XHR.status && !/^\s*$/.test(XHR.status)) {
  266. err = 'Error ' + XHR.status;
  267. } else {
  268. err = 'Error';
  269. }
  270. if (XHR.responseText && !/^\s*$/.test(XHR.responseText)) {
  271. err = err + ': ' + XHR.responseText;
  272. }
  273. break;
  274. }
  275. if (settings.ajaxUpdateError !== undefined) {
  276. settings.ajaxUpdateError(XHR, textStatus, errorThrown, err);
  277. } else if (err) {
  278. alert(err);
  279. }
  280. }
  281. }, options || {});
  282. if (options.type === 'GET') {
  283. if (options.data !== undefined) {
  284. options.url = $.param.querystring(options.url, options.data);
  285. options.data = {};
  286. }
  287. } else {
  288. if (options.data === undefined) {
  289. options.data = $(settings.filterSelector).serialize();
  290. }
  291. }
  292. if(yiiXHR[id] != null){
  293. yiiXHR[id].abort();
  294. }
  295. //class must be added after yiiXHR.abort otherwise ajax.error will remove it
  296. $grid.addClass(settings.loadingClass);
  297. if (settings.ajaxUpdate !== false) {
  298. if(settings.ajaxVar) {
  299. options.url = $.param.querystring(options.url, settings.ajaxVar + '=' + id);
  300. }
  301. if (settings.beforeAjaxUpdate !== undefined) {
  302. settings.beforeAjaxUpdate(id, options);
  303. }
  304. yiiXHR[id] = $.ajax(options);
  305. } else { // non-ajax mode
  306. if (options.type === 'GET') {
  307. window.location.href = options.url;
  308. } else { // POST mode
  309. $form = $('<form action="' + options.url + '" method="post"></form>').appendTo('body');
  310. if (options.data === undefined) {
  311. options.data = {};
  312. }
  313. if (options.data.returnUrl === undefined) {
  314. options.data.returnUrl = window.location.href;
  315. }
  316. $.each(options.data, function (name, value) {
  317. $form.append($('<input type="hidden" name="t" value="" />').attr('name', name).val(value));
  318. });
  319. $form.submit();
  320. }
  321. }
  322. });
  323. },
  324. /**
  325. * Returns the key values of the currently selected rows.
  326. * @return array the key values of the currently selected rows.
  327. */
  328. getSelection: function () {
  329. var settings = gridSettings[this.attr('id')],
  330. keys = this.find('.keys span'),
  331. selection = [];
  332. this.find('.' + settings.tableClass).children('tbody').children().each(function (i) {
  333. if ($(this).hasClass('selected')) {
  334. selection.push(keys.eq(i).text());
  335. }
  336. });
  337. return selection;
  338. },
  339. /**
  340. * Returns the key values of the currently checked rows.
  341. * @param column_id string the ID of the column
  342. * @return array the key values of the currently checked rows.
  343. */
  344. getChecked: function (column_id) {
  345. var settings = gridSettings[this.attr('id')],
  346. keys = this.find('.keys span'),
  347. checked = [];
  348. if (column_id.substring(column_id.length - 2) !== '[]') {
  349. column_id = column_id + '[]';
  350. }
  351. this.find('.' + settings.tableClass).children('tbody').children('tr').children('td').children('input[name="' + column_id + '"]').each(function (i) {
  352. if (this.checked) {
  353. checked.push(keys.eq(i).text());
  354. }
  355. });
  356. return checked;
  357. }
  358. };
  359. $.fn.yiiGridView = function (method) {
  360. if (methods[method]) {
  361. return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
  362. } else if (typeof method === 'object' || !method) {
  363. return methods.init.apply(this, arguments);
  364. } else {
  365. $.error('Method ' + method + ' does not exist on jQuery.yiiGridView');
  366. return false;
  367. }
  368. };
  369. /******************************************************************************
  370. *** DEPRECATED METHODS
  371. *** used before Yii 1.1.9
  372. ******************************************************************************/
  373. $.fn.yiiGridView.settings = gridSettings;
  374. /**
  375. * Returns the key value for the specified row
  376. * @param id string the ID of the grid view container
  377. * @param row integer the row number (zero-based index)
  378. * @return string the key value
  379. */
  380. $.fn.yiiGridView.getKey = function (id, row) {
  381. return $('#' + id).yiiGridView('getKey', row);
  382. };
  383. /**
  384. * Returns the URL that generates the grid view content.
  385. * @param id string the ID of the grid view container
  386. * @return string the URL that generates the grid view content.
  387. */
  388. $.fn.yiiGridView.getUrl = function (id) {
  389. return $('#' + id).yiiGridView('getUrl');
  390. };
  391. /**
  392. * Returns the jQuery collection of the cells in the specified row.
  393. * @param id string the ID of the grid view container
  394. * @param row integer the row number (zero-based index)
  395. * @return jQuery the jQuery collection of the cells in the specified row.
  396. */
  397. $.fn.yiiGridView.getRow = function (id, row) {
  398. return $('#' + id).yiiGridView('getRow', row);
  399. };
  400. /**
  401. * Returns the jQuery collection of the cells in the specified column.
  402. * @param id string the ID of the grid view container
  403. * @param column integer the column number (zero-based index)
  404. * @return jQuery the jQuery collection of the cells in the specified column.
  405. */
  406. $.fn.yiiGridView.getColumn = function (id, column) {
  407. return $('#' + id).yiiGridView('getColumn', column);
  408. };
  409. /**
  410. * Performs an AJAX-based update of the grid view contents.
  411. * @param id string the ID of the grid view container
  412. * @param options map the AJAX request options (see jQuery.ajax API manual). By default,
  413. * the URL to be requested is the one that generates the current content of the grid view.
  414. */
  415. $.fn.yiiGridView.update = function (id, options) {
  416. $('#' + id).yiiGridView('update', options);
  417. };
  418. /**
  419. * Returns the key values of the currently selected rows.
  420. * @param id string the ID of the grid view container
  421. * @return array the key values of the currently selected rows.
  422. */
  423. $.fn.yiiGridView.getSelection = function (id) {
  424. return $('#' + id).yiiGridView('getSelection');
  425. };
  426. /**
  427. * Returns the key values of the currently checked rows.
  428. * @param id string the ID of the grid view container
  429. * @param column_id string the ID of the column
  430. * @return array the key values of the currently checked rows.
  431. */
  432. $.fn.yiiGridView.getChecked = function (id, column_id) {
  433. return $('#' + id).yiiGridView('getChecked', column_id);
  434. };
  435. })(jQuery);