PageRenderTime 25ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/resources/META-INF/resources/primefaces/picklist/picklist.js

http://primefaces.googlecode.com/
JavaScript | 640 lines | 508 code | 117 blank | 15 comment | 79 complexity | bc5d33208f76b0849f802f9e2c56e9d9 MD5 | raw file
Possible License(s): Apache-2.0
  1. /**
  2. * PrimeFaces PickList Widget
  3. */
  4. PrimeFaces.widget.PickList = PrimeFaces.widget.BaseWidget.extend({
  5. init: function(cfg) {
  6. this._super(cfg);
  7. this.sourceList = this.jq.find('ul.ui-picklist-source');
  8. this.targetList = this.jq.find('ul.ui-picklist-target');
  9. this.sourceInput = $(this.jqId + '_source');
  10. this.targetInput = $(this.jqId + '_target');
  11. this.items = this.jq.find('.ui-picklist-item:not(.ui-state-disabled)');
  12. if(this.cfg.showCheckbox) {
  13. this.checkboxes = this.items.find('div.ui-chkbox > div.ui-chkbox-box');
  14. }
  15. //generate input options
  16. this.generateItems(this.sourceList, this.sourceInput);
  17. this.generateItems(this.targetList, this.targetInput);
  18. if(this.cfg.disabled) {
  19. $(this.jqId + ' li.ui-picklist-item').addClass('ui-state-disabled');
  20. $(this.jqId + ' button').attr('disabled', 'disabled').addClass('ui-state-disabled');
  21. }
  22. else {
  23. var $this = this,
  24. reordered = true;
  25. //Sortable lists
  26. $(this.jqId + ' ul').sortable({
  27. cancel: '.ui-state-disabled,.ui-chkbox-box',
  28. connectWith: this.jqId + ' .ui-picklist-list',
  29. revert: 1,
  30. update: function(event, ui) {
  31. $this.unselectItem(ui.item);
  32. $this.saveState();
  33. if(reordered) {
  34. $this.fireReorderEvent();
  35. reordered = false;
  36. }
  37. },
  38. receive: function(event, ui) {
  39. $this.fireTransferEvent(ui.item, ui.sender, ui.item.parents('ul.ui-picklist-list:first'), 'dragdrop');
  40. },
  41. start: function(event, ui) {
  42. $this.itemListName = $this.getListName(ui.item);
  43. $this.dragging = true;
  44. },
  45. stop: function(event, ui) {
  46. $this.dragging = false;
  47. },
  48. beforeStop:function(event, ui) {
  49. if($this.itemListName !== $this.getListName(ui.item)) {
  50. reordered = false;
  51. }
  52. else {
  53. reordered = true;
  54. }
  55. }
  56. });
  57. this.bindItemEvents();
  58. this.bindButtonEvents();
  59. this.bindFilterEvents();
  60. }
  61. },
  62. bindItemEvents: function() {
  63. var $this = this;
  64. this.items.on('mouseover.pickList', function(e) {
  65. var element = $(this);
  66. if(!element.hasClass('ui-state-highlight')) {
  67. $(this).addClass('ui-state-hover');
  68. }
  69. })
  70. .on('mouseout.pickList', function(e) {
  71. $(this).removeClass('ui-state-hover');
  72. })
  73. .on('click.pickList', function(e) {
  74. //stop propagation
  75. if($this.checkboxClick||$this.dragging) {
  76. $this.checkboxClick = false;
  77. return;
  78. }
  79. var item = $(this),
  80. metaKey = (e.metaKey||e.ctrlKey);
  81. if(!e.shiftKey) {
  82. if(!metaKey) {
  83. $this.unselectAll();
  84. }
  85. if(metaKey && item.hasClass('ui-state-highlight')) {
  86. $this.unselectItem(item, true);
  87. }
  88. else {
  89. $this.selectItem(item, true);
  90. $this.cursorItem = item;
  91. }
  92. }
  93. else {
  94. $this.unselectAll();
  95. if($this.cursorItem && ($this.cursorItem.parent().is(item.parent()))) {
  96. var currentItemIndex = item.index(),
  97. cursorItemIndex = $this.cursorItem.index(),
  98. startIndex = (currentItemIndex > cursorItemIndex) ? cursorItemIndex : currentItemIndex,
  99. endIndex = (currentItemIndex > cursorItemIndex) ? (currentItemIndex + 1) : (cursorItemIndex + 1),
  100. parentList = item.parent();
  101. for(var i = startIndex ; i < endIndex; i++) {
  102. var it = parentList.children('li.ui-picklist-item').eq(i);
  103. if(it.is(':visible')) {
  104. if(i === (endIndex - 1))
  105. $this.selectItem(it, true);
  106. else
  107. $this.selectItem(it);
  108. }
  109. }
  110. }
  111. else {
  112. $this.selectItem(item, true);
  113. $this.cursorItem = item;
  114. }
  115. }
  116. })
  117. .on('dblclick.pickList', function() {
  118. var item = $(this);
  119. if($(this).parent().hasClass('ui-picklist-source'))
  120. $this.transfer(item, $this.sourceList, $this.targetList, 'dblclick');
  121. else
  122. $this.transfer(item, $this.targetList, $this.sourceList, 'dblclick');
  123. PrimeFaces.clearSelection();
  124. });
  125. if(this.cfg.showCheckbox) {
  126. this.checkboxes.on('mouseover.pickList', function(e) {
  127. var chkbox = $(this);
  128. if(!chkbox.hasClass('ui-state-active'))
  129. chkbox.addClass('ui-state-hover');
  130. })
  131. .on('mouseout.pickList', function(e) {
  132. $(this).removeClass('ui-state-hover');
  133. })
  134. .on('click.pickList', function(e) {
  135. $this.checkboxClick = true;
  136. var item = $(this).closest('li.ui-picklist-item');
  137. if(item.hasClass('ui-state-highlight')) {
  138. $this.unselectItem(item, true);
  139. }
  140. else {
  141. $this.selectItem(item, true);
  142. }
  143. });
  144. }
  145. },
  146. selectItem: function(item, silent) {
  147. item.removeClass('ui-state-hover').addClass('ui-state-highlight');
  148. if(this.cfg.showCheckbox) {
  149. this.selectCheckbox(item.find('div.ui-chkbox-box'));
  150. }
  151. if(silent) {
  152. this.fireItemSelectEvent(item);
  153. }
  154. },
  155. unselectItem: function(item, silent) {
  156. item.removeClass('ui-state-hover ui-state-highlight');
  157. if(PrimeFaces.isIE(8)) {
  158. item.css('filter','');
  159. }
  160. if(this.cfg.showCheckbox) {
  161. this.unselectCheckbox(item.find('div.ui-chkbox-box'));
  162. }
  163. if(silent) {
  164. this.fireItemUnselectEvent(item);
  165. }
  166. },
  167. unselectAll: function() {
  168. var selectedItems = this.items.filter('.ui-state-highlight');
  169. for(var i = 0; i < selectedItems.length; i++) {
  170. this.unselectItem(selectedItems.eq(i));
  171. }
  172. },
  173. selectCheckbox: function(chkbox) {
  174. chkbox.removeClass('ui-state-hover').addClass('ui-state-active').children('span.ui-chkbox-icon').removeClass('ui-icon-blank').addClass('ui-icon-check');
  175. },
  176. unselectCheckbox: function(chkbox) {
  177. chkbox.removeClass('ui-state-active').children('span.ui-chkbox-icon').addClass('ui-icon-blank').removeClass('ui-icon-check');
  178. },
  179. generateItems: function(list, input) {
  180. list.children('.ui-picklist-item').each(function() {
  181. var item = $(this),
  182. itemValue = PrimeFaces.escapeHTML(item.attr('data-item-value')),
  183. itemLabel = item.attr('data-item-label'),
  184. escapedItemLabel = (itemLabel) ? PrimeFaces.escapeHTML(itemLabel) : '';
  185. input.append('<option value="' + itemValue + '" selected="selected">' + escapedItemLabel + '</option>');
  186. });
  187. },
  188. bindButtonEvents: function() {
  189. var _self = this;
  190. //visuals
  191. PrimeFaces.skinButton(this.jq.find('.ui-button'));
  192. //events
  193. $(this.jqId + ' .ui-picklist-button-add').click(function() {_self.add();});
  194. $(this.jqId + ' .ui-picklist-button-add-all').click(function() {_self.addAll();});
  195. $(this.jqId + ' .ui-picklist-button-remove').click(function() {_self.remove();});
  196. $(this.jqId + ' .ui-picklist-button-remove-all').click(function() {_self.removeAll();});
  197. if(this.cfg.showSourceControls) {
  198. $(this.jqId + ' .ui-picklist-source-controls .ui-picklist-button-move-up').click(function() {_self.moveUp(_self.sourceList);});
  199. $(this.jqId + ' .ui-picklist-source-controls .ui-picklist-button-move-top').click(function() {_self.moveTop(_self.sourceList);});
  200. $(this.jqId + ' .ui-picklist-source-controls .ui-picklist-button-move-down').click(function() {_self.moveDown(_self.sourceList);});
  201. $(this.jqId + ' .ui-picklist-source-controls .ui-picklist-button-move-bottom').click(function() {_self.moveBottom(_self.sourceList);});
  202. }
  203. if(this.cfg.showTargetControls) {
  204. $(this.jqId + ' .ui-picklist-target-controls .ui-picklist-button-move-up').click(function() {_self.moveUp(_self.targetList);});
  205. $(this.jqId + ' .ui-picklist-target-controls .ui-picklist-button-move-top').click(function() {_self.moveTop(_self.targetList);});
  206. $(this.jqId + ' .ui-picklist-target-controls .ui-picklist-button-move-down').click(function() {_self.moveDown(_self.targetList);});
  207. $(this.jqId + ' .ui-picklist-target-controls .ui-picklist-button-move-bottom').click(function() {_self.moveBottom(_self.targetList);});
  208. }
  209. },
  210. bindFilterEvents: function() {
  211. this.setupFilterMatcher();
  212. this.sourceFilter = $(this.jqId + '_source_filter');
  213. this.targetFilter = $(this.jqId + '_target_filter');
  214. var _self = this;
  215. PrimeFaces.skinInput(this.sourceFilter);
  216. PrimeFaces.skinInput(this.targetFilter);
  217. this.sourceFilter.on('keyup', function(e) {
  218. _self.filter(this.value, _self.sourceList);
  219. });
  220. this.targetFilter.on('keyup', function(e) {
  221. _self.filter(this.value, _self.targetList);
  222. });
  223. },
  224. setupFilterMatcher: function() {
  225. this.cfg.filterMatchMode = this.cfg.filterMatchMode||'startsWith';
  226. this.filterMatchers = {
  227. 'startsWith': this.startsWithFilter
  228. ,'contains': this.containsFilter
  229. ,'endsWith': this.endsWithFilter
  230. ,'custom': this.cfg.filterFunction
  231. };
  232. this.filterMatcher = this.filterMatchers[this.cfg.filterMatchMode];
  233. },
  234. filter: function(value, list) {
  235. var filterValue = $.trim(value).toLowerCase(),
  236. items = list.children('li.ui-picklist-item'),
  237. animated = this.isAnimated();
  238. if(filterValue === '') {
  239. items.filter(':hidden').show();
  240. }
  241. else {
  242. for(var i = 0; i < items.length; i++) {
  243. var item = items.eq(i),
  244. itemLabel = item.attr('data-item-label'),
  245. matches = this.filterMatcher(itemLabel, filterValue);
  246. if(matches) {
  247. if(animated)
  248. item.fadeIn('fast');
  249. else
  250. item.show();
  251. }
  252. else {
  253. if(animated)
  254. item.fadeOut('fast');
  255. else
  256. item.hide();
  257. }
  258. }
  259. }
  260. },
  261. startsWithFilter: function(value, filter) {
  262. return value.toLowerCase().indexOf(filter) === 0;
  263. },
  264. containsFilter: function(value, filter) {
  265. return value.toLowerCase().indexOf(filter) !== -1;
  266. },
  267. endsWithFilter: function(value, filter) {
  268. return value.indexOf(filter, value.length - filter.length) !== -1;
  269. },
  270. add: function() {
  271. var items = this.sourceList.children('li.ui-picklist-item.ui-state-highlight')
  272. this.transfer(items, this.sourceList, this.targetList, 'command');
  273. },
  274. addAll: function() {
  275. var items = this.sourceList.children('li.ui-picklist-item:visible:not(.ui-state-disabled)');
  276. this.transfer(items, this.sourceList, this.targetList, 'command');
  277. },
  278. remove: function() {
  279. var items = this.targetList.children('li.ui-picklist-item.ui-state-highlight');
  280. this.transfer(items, this.targetList, this.sourceList, 'command');
  281. },
  282. removeAll: function() {
  283. var items = this.targetList.children('li.ui-picklist-item:visible:not(.ui-state-disabled)');
  284. this.transfer(items, this.targetList, this.sourceList, 'command');
  285. },
  286. moveUp: function(list) {
  287. var _self = this,
  288. animated = _self.isAnimated(),
  289. items = list.children('.ui-state-highlight'),
  290. itemsCount = items.length,
  291. movedCount = 0;
  292. if(itemsCount) {
  293. items.each(function() {
  294. var item = $(this);
  295. if(!item.is(':first-child')) {
  296. if(animated) {
  297. item.hide(_self.cfg.effect, {}, _self.cfg.effectSpeed, function() {
  298. item.insertBefore(item.prev()).show(_self.cfg.effect, {}, _self.cfg.effectSpeed, function() {
  299. movedCount++;
  300. if(movedCount === itemsCount) {
  301. _self.saveState();
  302. _self.fireReorderEvent();
  303. }
  304. });
  305. });
  306. }
  307. else {
  308. item.hide().insertBefore(item.prev()).show();
  309. }
  310. }
  311. });
  312. if(!animated) {
  313. this.saveState();
  314. this.fireReorderEvent();
  315. }
  316. }
  317. },
  318. moveTop: function(list) {
  319. var _self = this,
  320. animated = _self.isAnimated(),
  321. items = list.children('.ui-state-highlight'),
  322. itemsCount = items.length,
  323. movedCount = 0;
  324. if(itemsCount) {
  325. items.each(function() {
  326. var item = $(this);
  327. if(!item.is(':first-child')) {
  328. if(animated) {
  329. item.hide(_self.cfg.effect, {}, _self.cfg.effectSpeed, function() {
  330. item.prependTo(item.parent()).show(_self.cfg.effect, {}, _self.cfg.effectSpeed, function(){
  331. movedCount++;
  332. if(movedCount === itemsCount) {
  333. _self.saveState();
  334. _self.fireReorderEvent();
  335. }
  336. });
  337. });
  338. }
  339. else {
  340. item.hide().prependTo(item.parent()).show();
  341. }
  342. }
  343. });
  344. if(!animated) {
  345. this.saveState();
  346. this.fireReorderEvent();
  347. }
  348. }
  349. },
  350. moveDown: function(list) {
  351. var _self = this,
  352. animated = _self.isAnimated(),
  353. items = list.children('.ui-state-highlight'),
  354. itemsCount = items.length,
  355. movedCount = 0;
  356. if(itemsCount) {
  357. $(items.get().reverse()).each(function() {
  358. var item = $(this);
  359. if(!item.is(':last-child')) {
  360. if(animated) {
  361. item.hide(_self.cfg.effect, {}, _self.cfg.effectSpeed, function() {
  362. item.insertAfter(item.next()).show(_self.cfg.effect, {}, _self.cfg.effectSpeed, function() {
  363. movedCount++;
  364. if(movedCount === itemsCount) {
  365. _self.saveState();
  366. _self.fireReorderEvent();
  367. }
  368. });
  369. });
  370. }
  371. else {
  372. item.hide().insertAfter(item.next()).show();
  373. }
  374. }
  375. });
  376. if(!animated) {
  377. this.saveState();
  378. this.fireReorderEvent();
  379. }
  380. }
  381. },
  382. moveBottom: function(list) {
  383. var _self = this,
  384. animated = _self.isAnimated(),
  385. items = list.children('.ui-state-highlight'),
  386. itemsCount = items.length,
  387. movedCount = 0;
  388. if(itemsCount) {
  389. items.each(function() {
  390. var item = $(this);
  391. if(!item.is(':last-child')) {
  392. if(animated) {
  393. item.hide(_self.cfg.effect, {}, _self.cfg.effectSpeed, function() {
  394. item.appendTo(item.parent()).show(_self.cfg.effect, {}, _self.cfg.effectSpeed, function() {
  395. movedCount++;
  396. if(movedCount === itemsCount) {
  397. _self.saveState();
  398. _self.fireReorderEvent();
  399. }
  400. });
  401. });
  402. }
  403. else {
  404. item.hide().appendTo(item.parent()).show();
  405. }
  406. }
  407. });
  408. if(!animated) {
  409. this.saveState();
  410. this.fireReorderEvent();
  411. }
  412. }
  413. },
  414. /**
  415. * Clear inputs and repopulate them from the list states
  416. */
  417. saveState: function() {
  418. this.sourceInput.children().remove();
  419. this.targetInput.children().remove();
  420. this.generateItems(this.sourceList, this.sourceInput);
  421. this.generateItems(this.targetList, this.targetInput);
  422. this.cursorItem = null;
  423. },
  424. transfer: function(items, from, to, type) {
  425. var $this = this,
  426. itemsCount = items.length,
  427. transferCount = 0;
  428. if(this.isAnimated()) {
  429. items.hide(this.cfg.effect, {}, this.cfg.effectSpeed, function() {
  430. var item = $(this);
  431. $this.unselectItem(item);
  432. item.appendTo(to).show($this.cfg.effect, {}, $this.cfg.effectSpeed, function() {
  433. transferCount++;
  434. //fire transfer when all items are transferred
  435. if(transferCount == itemsCount) {
  436. $this.saveState();
  437. $this.fireTransferEvent(items, from, to, type);
  438. }
  439. });
  440. });
  441. }
  442. else {
  443. items.hide();
  444. if(this.cfg.showCheckbox) {
  445. items.each(function() {
  446. $this.unselectItem($(this));
  447. });
  448. }
  449. items.appendTo(to).show();
  450. this.saveState();
  451. this.fireTransferEvent(items, from, to, type);
  452. }
  453. },
  454. /**
  455. * Fire transfer ajax behavior event
  456. */
  457. fireTransferEvent: function(items, from, to, type) {
  458. if(this.cfg.onTransfer) {
  459. var obj = {};
  460. obj.items = items;
  461. obj.from = from;
  462. obj.to = to;
  463. obj.type = type;
  464. this.cfg.onTransfer.call(this, obj);
  465. }
  466. if(this.cfg.behaviors) {
  467. var transferBehavior = this.cfg.behaviors['transfer'];
  468. if(transferBehavior) {
  469. var ext = {
  470. params: []
  471. },
  472. paramName = this.id + '_transferred',
  473. isAdd = from.hasClass('ui-picklist-source');
  474. items.each(function(index, item) {
  475. ext.params.push({name:paramName, value:$(item).attr('data-item-value')});
  476. });
  477. ext.params.push({name:this.id + '_add', value:isAdd});
  478. transferBehavior.call(this, ext);
  479. }
  480. }
  481. },
  482. getListName: function(element){
  483. return element.parent().hasClass("ui-picklist-source") ? "source" : "target";
  484. },
  485. hasBehavior: function(event) {
  486. if(this.cfg.behaviors) {
  487. return this.cfg.behaviors[event] != undefined;
  488. }
  489. return false;
  490. },
  491. fireItemSelectEvent: function(item) {
  492. if(this.hasBehavior('select')) {
  493. var itemSelectBehavior = this.cfg.behaviors['select'],
  494. ext = {
  495. params: [
  496. {name: this.id + '_itemIndex', value: item.index()},
  497. {name: this.id + '_listName', value: this.getListName(item)}
  498. ]
  499. };
  500. itemSelectBehavior.call(this, ext);
  501. }
  502. },
  503. fireItemUnselectEvent: function(item) {
  504. if(this.hasBehavior('unselect')) {
  505. var itemUnselectBehavior = this.cfg.behaviors['unselect'],
  506. ext = {
  507. params: [
  508. {name: this.id + '_itemIndex', value: item.index()},
  509. {name: this.id + '_listName', value: this.getListName(item)}
  510. ]
  511. };
  512. itemUnselectBehavior.call(this, ext);
  513. }
  514. },
  515. fireReorderEvent: function() {
  516. if(this.hasBehavior('reorder')) {
  517. this.cfg.behaviors['reorder'].call(this);
  518. }
  519. },
  520. isAnimated: function() {
  521. return (this.cfg.effect && this.cfg.effect != 'none');
  522. }
  523. });