Ohm-Management - Projektarbeit B-ME
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.

menuable.js 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  6. var _vue = require('vue');
  7. var _vue2 = _interopRequireDefault(_vue);
  8. var _positionable = require('./positionable');
  9. var _positionable2 = _interopRequireDefault(_positionable);
  10. var _stackable = require('./stackable');
  11. var _stackable2 = _interopRequireDefault(_stackable);
  12. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  13. /* eslint-disable object-property-newline */
  14. var dimensions = {
  15. activator: {
  16. top: 0, left: 0,
  17. bottom: 0, right: 0,
  18. width: 0, height: 0,
  19. offsetTop: 0, scrollHeight: 0
  20. },
  21. content: {
  22. top: 0, left: 0,
  23. bottom: 0, right: 0,
  24. width: 0, height: 0,
  25. offsetTop: 0, scrollHeight: 0
  26. },
  27. hasWindow: false
  28. };
  29. /* eslint-enable object-property-newline */
  30. /**
  31. * Menuable
  32. *
  33. * @mixin
  34. *
  35. * Used for fixed or absolutely positioning
  36. * elements within the DOM
  37. * Can calculate X and Y axis overflows
  38. * As well as be manually positioned
  39. */
  40. /* @vue/component */
  41. exports.default = _vue2.default.extend({
  42. name: 'menuable',
  43. mixins: [_positionable2.default, _stackable2.default],
  44. props: {
  45. activator: {
  46. default: null,
  47. validator: function validator(val) {
  48. return ['string', 'object'].includes(typeof val === 'undefined' ? 'undefined' : _typeof(val));
  49. }
  50. },
  51. allowOverflow: Boolean,
  52. inputActivator: Boolean,
  53. light: Boolean,
  54. dark: Boolean,
  55. maxWidth: {
  56. type: [Number, String],
  57. default: 'auto'
  58. },
  59. minWidth: [Number, String],
  60. nudgeBottom: {
  61. type: [Number, String],
  62. default: 0
  63. },
  64. nudgeLeft: {
  65. type: [Number, String],
  66. default: 0
  67. },
  68. nudgeRight: {
  69. type: [Number, String],
  70. default: 0
  71. },
  72. nudgeTop: {
  73. type: [Number, String],
  74. default: 0
  75. },
  76. nudgeWidth: {
  77. type: [Number, String],
  78. default: 0
  79. },
  80. offsetOverflow: Boolean,
  81. positionX: {
  82. type: Number,
  83. default: null
  84. },
  85. positionY: {
  86. type: Number,
  87. default: null
  88. },
  89. zIndex: {
  90. type: [Number, String],
  91. default: null
  92. }
  93. },
  94. data: function data() {
  95. return {
  96. absoluteX: 0,
  97. absoluteY: 0,
  98. activatorFixed: false,
  99. dimensions: Object.assign({}, dimensions),
  100. isContentActive: false,
  101. pageWidth: 0,
  102. pageYOffset: 0,
  103. stackClass: 'v-menu__content--active',
  104. stackMinZIndex: 6
  105. };
  106. },
  107. computed: {
  108. computedLeft: function computedLeft() {
  109. var a = this.dimensions.activator;
  110. var c = this.dimensions.content;
  111. var activatorLeft = (this.isAttached ? a.offsetLeft : a.left) || 0;
  112. var minWidth = Math.max(a.width, c.width);
  113. var left = 0;
  114. left += this.left ? activatorLeft - (minWidth - a.width) : activatorLeft;
  115. if (this.offsetX) {
  116. var maxWidth = isNaN(this.maxWidth) ? a.width : Math.min(a.width, this.maxWidth);
  117. left += this.left ? -maxWidth : a.width;
  118. }
  119. if (this.nudgeLeft) left -= parseInt(this.nudgeLeft);
  120. if (this.nudgeRight) left += parseInt(this.nudgeRight);
  121. return left;
  122. },
  123. computedTop: function computedTop() {
  124. var a = this.dimensions.activator;
  125. var c = this.dimensions.content;
  126. var top = 0;
  127. if (this.top) top += a.height - c.height;
  128. if (this.isAttached) top += a.offsetTop;else top += a.top + this.pageYOffset;
  129. if (this.offsetY) top += this.top ? -a.height : a.height;
  130. if (this.nudgeTop) top -= parseInt(this.nudgeTop);
  131. if (this.nudgeBottom) top += parseInt(this.nudgeBottom);
  132. return top;
  133. },
  134. hasActivator: function hasActivator() {
  135. return !!this.$slots.activator || !!this.$scopedSlots.activator || this.activator || this.inputActivator;
  136. },
  137. isAttached: function isAttached() {
  138. return this.attach !== false;
  139. }
  140. },
  141. watch: {
  142. disabled: function disabled(val) {
  143. val && this.callDeactivate();
  144. },
  145. isActive: function isActive(val) {
  146. if (this.disabled) return;
  147. val ? this.callActivate() : this.callDeactivate();
  148. },
  149. positionX: 'updateDimensions',
  150. positionY: 'updateDimensions'
  151. },
  152. beforeMount: function beforeMount() {
  153. this.checkForWindow();
  154. },
  155. methods: {
  156. absolutePosition: function absolutePosition() {
  157. return {
  158. offsetTop: 0,
  159. offsetLeft: 0,
  160. scrollHeight: 0,
  161. top: this.positionY || this.absoluteY,
  162. bottom: this.positionY || this.absoluteY,
  163. left: this.positionX || this.absoluteX,
  164. right: this.positionX || this.absoluteX,
  165. height: 0,
  166. width: 0
  167. };
  168. },
  169. activate: function activate() {},
  170. calcLeft: function calcLeft(menuWidth) {
  171. return (this.isAttached ? this.computedLeft : this.calcXOverflow(this.computedLeft, menuWidth)) + 'px';
  172. },
  173. calcTop: function calcTop() {
  174. return (this.isAttached ? this.computedTop : this.calcYOverflow(this.computedTop)) + 'px';
  175. },
  176. calcXOverflow: function calcXOverflow(left, menuWidth) {
  177. var xOverflow = left + menuWidth - this.pageWidth + 12;
  178. if ((!this.left || this.right) && xOverflow > 0) {
  179. left = Math.max(left - xOverflow, 0);
  180. } else {
  181. left = Math.max(left, 12);
  182. }
  183. return left + this.getOffsetLeft();
  184. },
  185. calcYOverflow: function calcYOverflow(top) {
  186. var documentHeight = this.getInnerHeight();
  187. var toTop = this.pageYOffset + documentHeight;
  188. var activator = this.dimensions.activator;
  189. var contentHeight = this.dimensions.content.height;
  190. var totalHeight = top + contentHeight;
  191. var isOverflowing = toTop < totalHeight;
  192. // If overflowing bottom and offset
  193. // TODO: set 'bottom' position instead of 'top'
  194. if (isOverflowing && this.offsetOverflow &&
  195. // If we don't have enough room to offset
  196. // the overflow, don't offset
  197. activator.top > contentHeight) {
  198. top = this.pageYOffset + (activator.top - contentHeight);
  199. // If overflowing bottom
  200. } else if (isOverflowing && !this.allowOverflow) {
  201. top = toTop - contentHeight - 12;
  202. // If overflowing top
  203. } else if (top < this.pageYOffset && !this.allowOverflow) {
  204. top = this.pageYOffset + 12;
  205. }
  206. return top < 12 ? 12 : top;
  207. },
  208. callActivate: function callActivate() {
  209. if (!this.hasWindow) return;
  210. this.activate();
  211. },
  212. callDeactivate: function callDeactivate() {
  213. this.isContentActive = false;
  214. this.deactivate();
  215. },
  216. checkForWindow: function checkForWindow() {
  217. if (!this.hasWindow) {
  218. this.hasWindow = typeof window !== 'undefined';
  219. }
  220. },
  221. checkForPageYOffset: function checkForPageYOffset() {
  222. if (this.hasWindow) {
  223. this.pageYOffset = this.activatorFixed ? 0 : this.getOffsetTop();
  224. }
  225. },
  226. checkActivatorFixed: function checkActivatorFixed() {
  227. if (this.attach !== false) return;
  228. var el = this.getActivator();
  229. while (el) {
  230. if (window.getComputedStyle(el).position === 'fixed') {
  231. this.activatorFixed = true;
  232. return;
  233. }
  234. el = el.offsetParent;
  235. }
  236. this.activatorFixed = false;
  237. },
  238. deactivate: function deactivate() {},
  239. getActivator: function getActivator(e) {
  240. if (this.inputActivator) {
  241. return this.$el.querySelector('.v-input__slot');
  242. }
  243. if (this.activator) {
  244. return typeof this.activator === 'string' ? document.querySelector(this.activator) : this.activator;
  245. }
  246. if (this.$refs.activator) {
  247. return this.$refs.activator.children.length > 0 ? this.$refs.activator.children[0] : this.$refs.activator;
  248. }
  249. if (e) {
  250. this.activatedBy = e.currentTarget || e.target;
  251. return this.activatedBy;
  252. }
  253. if (this.activatedBy) return this.activatedBy;
  254. if (this.activatorNode) {
  255. var activator = Array.isArray(this.activatorNode) ? this.activatorNode[0] : this.activatorNode;
  256. var el = activator && activator.elm;
  257. if (el) return el;
  258. }
  259. },
  260. getInnerHeight: function getInnerHeight() {
  261. if (!this.hasWindow) return 0;
  262. return window.innerHeight || document.documentElement.clientHeight;
  263. },
  264. getOffsetLeft: function getOffsetLeft() {
  265. if (!this.hasWindow) return 0;
  266. return window.pageXOffset || document.documentElement.scrollLeft;
  267. },
  268. getOffsetTop: function getOffsetTop() {
  269. if (!this.hasWindow) return 0;
  270. return window.pageYOffset || document.documentElement.scrollTop;
  271. },
  272. getRoundedBoundedClientRect: function getRoundedBoundedClientRect(el) {
  273. var rect = el.getBoundingClientRect();
  274. return {
  275. top: Math.round(rect.top),
  276. left: Math.round(rect.left),
  277. bottom: Math.round(rect.bottom),
  278. right: Math.round(rect.right),
  279. width: Math.round(rect.width),
  280. height: Math.round(rect.height)
  281. };
  282. },
  283. measure: function measure(el) {
  284. if (!el || !this.hasWindow) return null;
  285. var rect = this.getRoundedBoundedClientRect(el);
  286. // Account for activator margin
  287. if (this.isAttached) {
  288. var style = window.getComputedStyle(el);
  289. rect.left = parseInt(style.marginLeft);
  290. rect.top = parseInt(style.marginTop);
  291. }
  292. return rect;
  293. },
  294. sneakPeek: function sneakPeek(cb) {
  295. var _this = this;
  296. requestAnimationFrame(function () {
  297. var el = _this.$refs.content;
  298. if (!el || _this.isShown(el)) return cb();
  299. el.style.display = 'inline-block';
  300. cb();
  301. el.style.display = 'none';
  302. });
  303. },
  304. startTransition: function startTransition() {
  305. var _this2 = this;
  306. return new Promise(function (resolve) {
  307. return requestAnimationFrame(function () {
  308. _this2.isContentActive = _this2.hasJustFocused = _this2.isActive;
  309. resolve();
  310. });
  311. });
  312. },
  313. isShown: function isShown(el) {
  314. return el.style.display !== 'none';
  315. },
  316. updateDimensions: function updateDimensions() {
  317. var _this3 = this;
  318. this.checkForWindow();
  319. this.checkActivatorFixed();
  320. this.checkForPageYOffset();
  321. this.pageWidth = document.documentElement.clientWidth;
  322. var dimensions = {};
  323. // Activator should already be shown
  324. if (!this.hasActivator || this.absolute) {
  325. dimensions.activator = this.absolutePosition();
  326. } else {
  327. var activator = this.getActivator();
  328. dimensions.activator = this.measure(activator);
  329. dimensions.activator.offsetLeft = activator.offsetLeft;
  330. if (this.isAttached) {
  331. // account for css padding causing things to not line up
  332. // this is mostly for v-autocomplete, hopefully it won't break anything
  333. dimensions.activator.offsetTop = activator.offsetTop;
  334. } else {
  335. dimensions.activator.offsetTop = 0;
  336. }
  337. }
  338. // Display and hide to get dimensions
  339. this.sneakPeek(function () {
  340. dimensions.content = _this3.measure(_this3.$refs.content);
  341. _this3.dimensions = dimensions;
  342. });
  343. }
  344. }
  345. });
  346. //# sourceMappingURL=menuable.js.map