You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

192 lines
6.1 KiB

  1. //Varun Dewan 2019
  2. var render = {
  3. get: function(selector){
  4. var ele = document.querySelectorAll(selector);
  5. for(var i = 0; i < ele.length; i++){
  6. this.init(ele[i]);
  7. }
  8. return ele;
  9. },
  10. template: function(html){
  11. var template = document.createElement('div');
  12. template.innerHTML = html.trim();
  13. return this.init(template.childNodes[0]);
  14. },
  15. init: function(ele){
  16. ele.on = function(event, func){ this.addEventListener(event, func); }
  17. return ele;
  18. }
  19. };
  20. //Build the plugin
  21. var drop = function(info){var o = {
  22. options: info.options,
  23. selected: info.selected || [],
  24. preselected: info.preselected || [],
  25. open: false,
  26. html: {
  27. select: render.get(info.selector)[0],
  28. options: render.get(info.selector + ' option'),
  29. parent: undefined,
  30. },
  31. init: function(){
  32. //Setup Drop HTML
  33. this.html.parent = render.get(info.selector)[0].parentNode
  34. this.html.drop = render.template('<div class="drop"></div>')
  35. this.html.dropDisplay = render.template('<div class="drop-display">Display</div>')
  36. this.html.dropOptions = render.template('<div class="drop-options">Options</div>')
  37. this.html.dropScreen = render.template('<div class="drop-screen"></div>')
  38. this.html.parent.insertBefore(this.html.drop, this.html.select)
  39. this.html.drop.appendChild(this.html.dropDisplay)
  40. this.html.drop.appendChild(this.html.dropOptions)
  41. this.html.drop.appendChild(this.html.dropScreen)
  42. //Hide old select
  43. this.html.drop.appendChild(this.html.select);
  44. //Core Events
  45. var that = this;
  46. this.html.dropDisplay.on('click', function(){ that.toggle() });
  47. this.html.dropScreen.on('click', function(){ that.toggle() });
  48. //Run Render
  49. this.load()
  50. this.preselect()
  51. this.render();
  52. },
  53. toggle: function(){
  54. // if(this.html.drop.classList.contains('open')){
  55. // $(info.selector).val(this.selected.filter(i=>!i.removed).map(i=>$(info.selector).children('option')[i.index].value)).trigger('change')
  56. // }
  57. this.html.drop.classList.toggle('open');
  58. },
  59. addOption: function(e, element){
  60. var index = Number(element.dataset.index);
  61. this.clearStates()
  62. this.selected.push({
  63. index: Number(index),
  64. state: 'add',
  65. removed: false
  66. })
  67. this.options[index].state = 'remove';
  68. this.render()
  69. },
  70. removeOption: function(e, element){
  71. e.stopPropagation();
  72. this.clearStates()
  73. var index = Number(element.dataset.index);
  74. this.selected.forEach(function(select){
  75. if(select.index == index && !select.removed){
  76. select.removed = true
  77. select.state = 'remove'
  78. }
  79. })
  80. this.options[index].state = 'add'
  81. this.render();
  82. },
  83. load: function(){
  84. this.options = [];
  85. this.html.options =render.get(info.selector + ' option');
  86. for(var i = 0; i < this.html.options.length; i++){
  87. var option = this.html.options[i];
  88. if(!$(option).prop('hidden')){
  89. this.options[i] = {
  90. html: option.innerHTML,
  91. value: option.value,
  92. selected: option.selected,
  93. state: '',
  94. }
  95. }
  96. }
  97. },
  98. preselect: function(){
  99. var that = this;
  100. this.selected = [];
  101. this.preselected.forEach(function(pre){
  102. that.selected.push({
  103. index: pre,
  104. state: 'add',
  105. removed: false
  106. })
  107. that.options[pre].state = 'remove';
  108. })
  109. },
  110. render: function(){
  111. this.renderDrop()
  112. this.renderOptions()
  113. },
  114. renderDrop: function(){
  115. var that = this;
  116. var parentHTML = render.template('<div></div>')
  117. this.selected.forEach(function(select, index){
  118. var option = that.options[select.index];
  119. var childHTML = render.template('<span class="item '+ select.state +'">'+ option.html +'</span>')
  120. var childCloseHTML = render.template(
  121. '<i class="material-icons btnclose" data-index="'+select.index+'">&#xe5c9;</i></span>')
  122. childCloseHTML.on('click', function(e){ that.removeOption(e, this) })
  123. childHTML.appendChild(childCloseHTML)
  124. parentHTML.appendChild(childHTML)
  125. })
  126. this.html.dropDisplay.innerHTML = '';
  127. this.html.dropDisplay.appendChild(parentHTML)
  128. },
  129. renderOptions: function(){
  130. var that = this;
  131. var parentHTML = render.template('<div></div>')
  132. this.options.forEach(function(option, index){
  133. var childHTML = render.template(
  134. '<a href="#" data-index="'+index+'" class="'+option.state+'">'+ option.html +'</a>')
  135. childHTML.on('click', function(e){ that.addOption(e, this) })
  136. parentHTML.appendChild(childHTML)
  137. })
  138. this.html.dropOptions.innerHTML = '';
  139. this.html.dropOptions.appendChild(parentHTML)
  140. },
  141. clearStates: function(){
  142. var that = this;
  143. this.selected.forEach(function(select, index){
  144. select.state = that.changeState(select.state)
  145. })
  146. this.options.forEach(function(option){
  147. option.state = that.changeState(option.state)
  148. })
  149. },
  150. changeState: function(state){
  151. var drop = this;
  152. setTimeout(function(){
  153. $(info.selector).val(drop.selected.filter(i=>!i.removed).map(i=>$(info.selector).children('option')[i.index].value)).trigger('change');
  154. }, 1000);
  155. switch(state){
  156. case 'remove':
  157. return 'hide'
  158. case 'hide':
  159. return 'hide'
  160. default:
  161. return ''
  162. };
  163. },
  164. isSelected: function(index){
  165. var check = false
  166. this.selected.forEach(function(select){
  167. if(select.index == index && select.removed == false) check = true
  168. })
  169. return check
  170. }
  171. }; o.init(); return o;}
  172. //Set up some data
  173. // var options = [
  174. // { html: 'cats', value: 'cats' },
  175. // { html: 'fish', value: 'fish' },
  176. // { html: 'squids', value: 'squids' },
  177. // { html: 'cats', value: 'whales' },
  178. // { html: 'cats', value: 'bikes' },
  179. // ];
  180. // var myDrop = new drop({
  181. // selector: '#myMulti',
  182. // preselected: [0, 2]
  183. // });
  184. // myDrop.toggle();