drop.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. (function() {
  2. var Evented, MIRROR_ATTACH, addClass, allDrops, clickEvent, createContext, extend, hasClass, removeClass, sortAttach, touchDevice, _ref,
  3. __hasProp = {}.hasOwnProperty,
  4. __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5. __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
  6. _ref = Tether.Utils, extend = _ref.extend, addClass = _ref.addClass, removeClass = _ref.removeClass, hasClass = _ref.hasClass, Evented = _ref.Evented;
  7. touchDevice = 'ontouchstart' in document.documentElement;
  8. clickEvent = touchDevice ? 'touchstart' : 'click';
  9. sortAttach = function(str) {
  10. var first, second, _ref1, _ref2;
  11. _ref1 = str.split(' '), first = _ref1[0], second = _ref1[1];
  12. if (first === 'left' || first === 'right') {
  13. _ref2 = [second, first], first = _ref2[0], second = _ref2[1];
  14. }
  15. return [first, second].join(' ');
  16. };
  17. MIRROR_ATTACH = {
  18. left: 'right',
  19. right: 'left',
  20. top: 'bottom',
  21. bottom: 'top',
  22. middle: 'middle',
  23. center: 'center'
  24. };
  25. allDrops = {};
  26. createContext = function(options) {
  27. var DropInstance, defaultOptions, drop, _name;
  28. if (options == null) {
  29. options = {};
  30. }
  31. drop = function() {
  32. return (function(func, args, ctor) {
  33. ctor.prototype = func.prototype;
  34. var child = new ctor, result = func.apply(child, args);
  35. return Object(result) === result ? result : child;
  36. })(DropInstance, arguments, function(){});
  37. };
  38. extend(drop, {
  39. createContext: createContext,
  40. drops: [],
  41. defaults: {}
  42. });
  43. defaultOptions = {
  44. classPrefix: 'drop',
  45. defaults: {
  46. attach: 'bottom left',
  47. openOn: 'click',
  48. constrainToScrollParent: true,
  49. constrainToWindow: true,
  50. classes: '',
  51. tetherOptions: {}
  52. }
  53. };
  54. extend(drop, defaultOptions, options);
  55. extend(drop.defaults, defaultOptions.defaults, options.defaults);
  56. if (allDrops[_name = drop.classPrefix] == null) {
  57. allDrops[_name] = [];
  58. }
  59. drop.updateBodyClasses = function() {
  60. var anyOpen, _drop, _i, _len, _ref1;
  61. anyOpen = false;
  62. _ref1 = allDrops[drop.classPrefix];
  63. for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
  64. _drop = _ref1[_i];
  65. if (!(_drop.isOpened())) {
  66. continue;
  67. }
  68. anyOpen = true;
  69. break;
  70. }
  71. if (anyOpen) {
  72. return addClass(document.body, "" + drop.classPrefix + "-open");
  73. } else {
  74. return removeClass(document.body, "" + drop.classPrefix + "-open");
  75. }
  76. };
  77. DropInstance = (function(_super) {
  78. __extends(DropInstance, _super);
  79. function DropInstance(options) {
  80. this.options = options;
  81. this.options = extend({}, drop.defaults, this.options);
  82. this.target = this.options.target;
  83. if (this.target == null) {
  84. throw new Error('Drop Error: You must provide a target.');
  85. }
  86. drop.drops.push(this);
  87. allDrops[drop.classPrefix].push(this);
  88. this.setupElements();
  89. this.setupEvents();
  90. this.setupTether();
  91. }
  92. DropInstance.prototype.setupElements = function() {
  93. this.drop = document.createElement('div');
  94. addClass(this.drop, drop.classPrefix);
  95. if (this.options.classes) {
  96. addClass(this.drop, this.options.classes);
  97. }
  98. this.dropContent = document.createElement('div');
  99. addClass(this.dropContent, "" + drop.classPrefix + "-content");
  100. if (typeof this.options.content === 'object') {
  101. this.dropContent.appendChild(this.options.content);
  102. } else {
  103. this.dropContent.innerHTML = this.options.content;
  104. }
  105. return this.drop.appendChild(this.dropContent);
  106. };
  107. DropInstance.prototype.setupTether = function() {
  108. var constraints, dropAttach;
  109. dropAttach = this.options.position.split(' ');
  110. dropAttach[0] = MIRROR_ATTACH[dropAttach[0]];
  111. dropAttach = dropAttach.join(' ');
  112. constraints = [];
  113. if (this.options.constrainToScrollParent) {
  114. constraints.push({
  115. to: 'scrollParent',
  116. pin: 'top, bottom',
  117. attachment: 'together none'
  118. });
  119. }
  120. if (this.options.constrainToWindow !== false) {
  121. constraints.push({
  122. to: 'window',
  123. pin: true,
  124. attachment: 'together'
  125. });
  126. }
  127. constraints.push({
  128. to: 'scrollParent'
  129. });
  130. options = {
  131. element: this.drop,
  132. target: this.target,
  133. attachment: sortAttach(dropAttach),
  134. targetAttachment: sortAttach(this.options.position),
  135. classPrefix: drop.classPrefix,
  136. offset: '0 0',
  137. targetOffset: '0 0',
  138. enabled: false,
  139. constraints: constraints
  140. };
  141. if (this.options.tether !== false) {
  142. return this.tether = new Tether(extend({}, options, this.options.tether));
  143. }
  144. };
  145. DropInstance.prototype.setupEvents = function() {
  146. var events,
  147. _this = this;
  148. if (!this.options.openOn) {
  149. return;
  150. }
  151. events = this.options.openOn.split(' ');
  152. if (__indexOf.call(events, 'click') >= 0) {
  153. this.target.addEventListener(clickEvent, function() {
  154. return _this.toggle();
  155. });
  156. document.addEventListener(clickEvent, function(event) {
  157. if (!_this.isOpened()) {
  158. return;
  159. }
  160. if (event.target === _this.drop || _this.drop.contains(event.target)) {
  161. return;
  162. }
  163. if (event.target === _this.target || _this.target.contains(event.target)) {
  164. return;
  165. }
  166. return _this.close();
  167. });
  168. }
  169. if (__indexOf.call(events, 'hover') >= 0) {
  170. this.target.addEventListener('mouseover', function() {
  171. return _this.open();
  172. });
  173. return this.target.addEventListener('mouseout', function() {
  174. return _this.close();
  175. });
  176. }
  177. };
  178. DropInstance.prototype.isOpened = function() {
  179. return hasClass(this.drop, "" + drop.classPrefix + "-open");
  180. };
  181. DropInstance.prototype.toggle = function() {
  182. if (this.isOpened()) {
  183. return this.close();
  184. } else {
  185. return this.open();
  186. }
  187. };
  188. DropInstance.prototype.open = function() {
  189. var _ref1;
  190. if (!this.drop.parentNode) {
  191. document.body.appendChild(this.drop);
  192. }
  193. addClass(this.target, "" + drop.classPrefix + "-open");
  194. addClass(this.drop, "" + drop.classPrefix + "-open");
  195. if ((_ref1 = this.tether) != null) {
  196. _ref1.enable();
  197. }
  198. this.trigger('open');
  199. return drop.updateBodyClasses();
  200. };
  201. DropInstance.prototype.close = function() {
  202. var _ref1;
  203. removeClass(this.target, "" + drop.classPrefix + "-open");
  204. removeClass(this.drop, "" + drop.classPrefix + "-open");
  205. this.trigger('close');
  206. if ((_ref1 = this.tether) != null) {
  207. _ref1.disable();
  208. }
  209. return drop.updateBodyClasses();
  210. };
  211. return DropInstance;
  212. })(Evented);
  213. return drop;
  214. };
  215. window.Drop = createContext();
  216. document.addEventListener('DOMContentLoaded', function() {
  217. return Drop.updateBodyClasses();
  218. });
  219. }).call(this);