Align.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. var _extends2 = require('babel-runtime/helpers/extends');
  6. var _extends3 = _interopRequireDefault(_extends2);
  7. var _typeof2 = require('babel-runtime/helpers/typeof');
  8. var _typeof3 = _interopRequireDefault(_typeof2);
  9. var _vueTypes = require('../_util/vue-types');
  10. var _vueTypes2 = _interopRequireDefault(_vueTypes);
  11. var _domAlign = require('dom-align');
  12. var _addEventListener = require('../vc-util/Dom/addEventListener');
  13. var _addEventListener2 = _interopRequireDefault(_addEventListener);
  14. var _util = require('./util');
  15. var _vnode = require('../_util/vnode.js');
  16. var _cloneDeep = require('lodash/cloneDeep');
  17. var _cloneDeep2 = _interopRequireDefault(_cloneDeep);
  18. var _propsUtil = require('../_util/props-util');
  19. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  20. function getElement(func) {
  21. if (typeof func !== 'function' || !func) return null;
  22. return func();
  23. }
  24. function getPoint(point) {
  25. if ((typeof point === 'undefined' ? 'undefined' : (0, _typeof3['default'])(point)) !== 'object' || !point) return null;
  26. return point;
  27. }
  28. exports['default'] = {
  29. props: {
  30. childrenProps: _vueTypes2['default'].object,
  31. align: _vueTypes2['default'].object.isRequired,
  32. target: _vueTypes2['default'].oneOfType([_vueTypes2['default'].func, _vueTypes2['default'].object]).def(function () {
  33. return window;
  34. }),
  35. monitorBufferTime: _vueTypes2['default'].number.def(50),
  36. monitorWindowResize: _vueTypes2['default'].bool.def(false),
  37. disabled: _vueTypes2['default'].bool.def(false)
  38. },
  39. data: function data() {
  40. this.aligned = false;
  41. return {};
  42. },
  43. mounted: function mounted() {
  44. var _this = this;
  45. this.$nextTick(function () {
  46. _this.prevProps = (0, _extends3['default'])({}, _this.$props);
  47. var props = _this.$props;
  48. // if parent ref not attached .... use document.getElementById
  49. !_this.aligned && _this.forceAlign();
  50. if (!props.disabled && props.monitorWindowResize) {
  51. _this.startMonitorWindowResize();
  52. }
  53. });
  54. },
  55. updated: function updated() {
  56. var _this2 = this;
  57. this.$nextTick(function () {
  58. var prevProps = _this2.prevProps;
  59. var props = _this2.$props;
  60. var reAlign = false;
  61. if (!props.disabled) {
  62. var source = _this2.$el;
  63. var sourceRect = source ? source.getBoundingClientRect() : null;
  64. if (prevProps.disabled) {
  65. reAlign = true;
  66. } else {
  67. var lastElement = getElement(prevProps.target);
  68. var currentElement = getElement(props.target);
  69. var lastPoint = getPoint(prevProps.target);
  70. var currentPoint = getPoint(props.target);
  71. if ((0, _util.isWindow)(lastElement) && (0, _util.isWindow)(currentElement)) {
  72. // Skip if is window
  73. reAlign = false;
  74. } else if (lastElement !== currentElement || // Element change
  75. lastElement && !currentElement && currentPoint || // Change from element to point
  76. lastPoint && currentPoint && currentElement || // Change from point to element
  77. currentPoint && !(0, _util.isSamePoint)(lastPoint, currentPoint)) {
  78. reAlign = true;
  79. }
  80. // If source element size changed
  81. var preRect = _this2.sourceRect || {};
  82. if (!reAlign && source && (!(0, _util.isSimilarValue)(preRect.width, sourceRect.width) || !(0, _util.isSimilarValue)(preRect.height, sourceRect.height))) {
  83. reAlign = true;
  84. }
  85. }
  86. _this2.sourceRect = sourceRect;
  87. }
  88. if (reAlign) {
  89. _this2.forceAlign();
  90. }
  91. if (props.monitorWindowResize && !props.disabled) {
  92. _this2.startMonitorWindowResize();
  93. } else {
  94. _this2.stopMonitorWindowResize();
  95. }
  96. _this2.prevProps = (0, _extends3['default'])({}, _this2.$props, { align: (0, _cloneDeep2['default'])(_this2.$props.align) });
  97. });
  98. },
  99. beforeDestroy: function beforeDestroy() {
  100. this.stopMonitorWindowResize();
  101. },
  102. methods: {
  103. startMonitorWindowResize: function startMonitorWindowResize() {
  104. if (!this.resizeHandler) {
  105. this.bufferMonitor = (0, _util.buffer)(this.forceAlign, this.$props.monitorBufferTime);
  106. this.resizeHandler = (0, _addEventListener2['default'])(window, 'resize', this.bufferMonitor);
  107. }
  108. },
  109. stopMonitorWindowResize: function stopMonitorWindowResize() {
  110. if (this.resizeHandler) {
  111. this.bufferMonitor.clear();
  112. this.resizeHandler.remove();
  113. this.resizeHandler = null;
  114. }
  115. },
  116. forceAlign: function forceAlign() {
  117. var _$props = this.$props,
  118. disabled = _$props.disabled,
  119. target = _$props.target,
  120. align = _$props.align;
  121. if (!disabled && target) {
  122. var source = this.$el;
  123. var listeners = (0, _propsUtil.getListeners)(this);
  124. var result = void 0;
  125. var element = getElement(target);
  126. var point = getPoint(target);
  127. // IE lose focus after element realign
  128. // We should record activeElement and restore later
  129. var activeElement = document.activeElement;
  130. if (element) {
  131. result = (0, _domAlign.alignElement)(source, element, align);
  132. } else if (point) {
  133. result = (0, _domAlign.alignPoint)(source, point, align);
  134. }
  135. (0, _util.restoreFocus)(activeElement, source);
  136. this.aligned = true;
  137. listeners.align && listeners.align(source, result);
  138. }
  139. }
  140. },
  141. render: function render() {
  142. var childrenProps = this.$props.childrenProps;
  143. var child = (0, _propsUtil.getSlot)(this)[0];
  144. if (child && childrenProps) {
  145. return (0, _vnode.cloneElement)(child, { props: childrenProps });
  146. }
  147. return child;
  148. }
  149. };