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.
 
 
 

180 lines
5.6 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. this.html.drop.classList.toggle('open');
  55. },
  56. addOption: function(e, element){
  57. var index = Number(element.dataset.index);
  58. this.clearStates()
  59. this.selected.push({
  60. index: Number(index),
  61. state: 'add',
  62. removed: false
  63. })
  64. this.options[index].state = 'remove';
  65. this.render()
  66. },
  67. removeOption: function(e, element){
  68. e.stopPropagation();
  69. this.clearStates()
  70. var index = Number(element.dataset.index);
  71. this.selected.forEach(function(select){
  72. if(select.index == index && !select.removed){
  73. select.removed = true
  74. select.state = 'remove'
  75. }
  76. })
  77. this.options[index].state = 'add'
  78. this.render();
  79. },
  80. load: function(){
  81. this.options = [];
  82. for(var i = 0; i < this.html.options.length; i++){
  83. var option = this.html.options[i]
  84. this.options[i] = {
  85. html: option.innerHTML,
  86. value: option.value,
  87. selected: option.selected,
  88. state: ''
  89. }
  90. }
  91. },
  92. preselect: function(){
  93. var that = this;
  94. this.selected = [];
  95. this.preselected.forEach(function(pre){
  96. that.selected.push({
  97. index: pre,
  98. state: 'add',
  99. removed: false
  100. })
  101. that.options[pre].state = 'remove';
  102. })
  103. },
  104. render: function(){
  105. this.renderDrop()
  106. this.renderOptions()
  107. },
  108. renderDrop: function(){
  109. var that = this;
  110. var parentHTML = render.template('<div></div>')
  111. this.selected.forEach(function(select, index){
  112. var option = that.options[select.index];
  113. var childHTML = render.template('<span class="item '+ select.state +'">'+ option.html +'</span>')
  114. var childCloseHTML = render.template(
  115. '<i class="material-icons btnclose" data-index="'+select.index+'">&#xe5c9;</i></span>')
  116. childCloseHTML.on('click', function(e){ that.removeOption(e, this) })
  117. childHTML.appendChild(childCloseHTML)
  118. parentHTML.appendChild(childHTML)
  119. })
  120. this.html.dropDisplay.innerHTML = '';
  121. this.html.dropDisplay.appendChild(parentHTML)
  122. },
  123. renderOptions: function(){
  124. var that = this;
  125. var parentHTML = render.template('<div></div>')
  126. this.options.forEach(function(option, index){
  127. var childHTML = render.template(
  128. '<a href="#" data-index="'+index+'" class="'+option.state+'">'+ option.html +'</a>')
  129. childHTML.on('click', function(e){ that.addOption(e, this) })
  130. parentHTML.appendChild(childHTML)
  131. })
  132. this.html.dropOptions.innerHTML = '';
  133. this.html.dropOptions.appendChild(parentHTML)
  134. },
  135. clearStates: function(){
  136. var that = this;
  137. this.selected.forEach(function(select, index){
  138. select.state = that.changeState(select.state)
  139. })
  140. this.options.forEach(function(option){
  141. option.state = that.changeState(option.state)
  142. })
  143. },
  144. changeState: function(state){
  145. switch(state){
  146. case 'remove':
  147. return 'hide'
  148. case 'hide':
  149. return 'hide'
  150. default:
  151. return ''
  152. }
  153. },
  154. isSelected: function(index){
  155. var check = false
  156. this.selected.forEach(function(select){
  157. if(select.index == index && select.removed == false) check = true
  158. })
  159. return check
  160. }
  161. }; o.init(); return o;}
  162. //Set up some data
  163. // var options = [
  164. // { html: 'cats', value: 'cats' },
  165. // { html: 'fish', value: 'fish' },
  166. // { html: 'squids', value: 'squids' },
  167. // { html: 'cats', value: 'whales' },
  168. // { html: 'cats', value: 'bikes' },
  169. // ];
  170. // var myDrop = new drop({
  171. // selector: '#myMulti',
  172. // preselected: [0, 2]
  173. // });
  174. // myDrop.toggle();