|
1607 | 1607 | .service(Mixer, function () {
|
1608 | 1608 | var _this = this;
|
1609 | 1609 |
|
| 1610 | + // Used to store method's caller |
| 1611 | + var caller = void 0; |
| 1612 | + |
1610 | 1613 | this._mixins = [];
|
1611 | 1614 | // Apply mixins automatically on specified contexts
|
1612 | 1615 | this._autoExtend = [];
|
|
1649 | 1652 | };
|
1650 | 1653 |
|
1651 | 1654 | // Extend prototype with the defined mixins
|
1652 |
| - this._extend = function (obj) { |
| 1655 | + this._extend = function (obj, options) { |
1653 | 1656 | var _ref;
|
1654 | 1657 |
|
1655 |
| - return (_ref = _).extend.apply(_ref, [obj].concat(_toConsumableArray(_this._mixins))); |
| 1658 | + var _$defaults = _.defaults({}, options, { |
| 1659 | + pattern: /.*/ }); |
| 1660 | + |
| 1661 | + var pattern = _$defaults.pattern; |
| 1662 | + var context = _$defaults.context; |
| 1663 | + // The patterns of the keys which will be filtered |
| 1664 | + |
| 1665 | + |
| 1666 | + var mixins = _this._mixins.map(function (mixin) { |
| 1667 | + // Filtering the keys by the specified pattern |
| 1668 | + var keys = _.keys(mixin).filter(function (k) { |
| 1669 | + return k.match(pattern); |
| 1670 | + }).filter(function (k) { |
| 1671 | + return _.isFunction(mixin[k]); |
| 1672 | + }); |
| 1673 | + |
| 1674 | + return keys.reduce(function (boundMixin, methodName) { |
| 1675 | + var methodHandler = mixin[methodName]; |
| 1676 | + |
| 1677 | + // Note that this is not an arrow function so we can conserve the conetxt |
| 1678 | + boundMixin[methodName] = function () { |
| 1679 | + // Storing original caller so we will know who actually called the |
| 1680 | + // method event though it is bound to another context |
| 1681 | + var methodContext = context || this; |
| 1682 | + var recentCaller = caller; |
| 1683 | + caller = this; |
| 1684 | + |
| 1685 | + try { |
| 1686 | + for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { |
| 1687 | + args[_key2] = arguments[_key2]; |
| 1688 | + } |
| 1689 | + |
| 1690 | + return methodHandler.apply(methodContext, args); |
| 1691 | + } finally { |
| 1692 | + // No matter what happens, restore variable to the previous one |
| 1693 | + caller = recentCaller; |
| 1694 | + } |
| 1695 | + }; |
| 1696 | + |
| 1697 | + return boundMixin; |
| 1698 | + }, {}); |
| 1699 | + }); |
| 1700 | + |
| 1701 | + return (_ref = _).extend.apply(_ref, [obj].concat(_toConsumableArray(mixins))); |
1656 | 1702 | };
|
| 1703 | + |
| 1704 | + // Caller property can not be set |
| 1705 | + Object.defineProperty(this, 'caller', { |
| 1706 | + configurable: true, |
| 1707 | + enumerable: true, |
| 1708 | + |
| 1709 | + get: function get() { |
| 1710 | + return caller; |
| 1711 | + } |
| 1712 | + }); |
1657 | 1713 | });
|
1658 | 1714 |
|
1659 | 1715 | /***/ },
|
|
1870 | 1926 |
|
1871 | 1927 | // Gets an object, wraps it with scope functions and returns it
|
1872 | 1928 | $$ViewModel.viewModel = function (vm) {
|
1873 |
| - var _this = this; |
1874 |
| - |
1875 | 1929 | if (!_.isObject(vm)) {
|
1876 | 1930 | throw Error('argument 1 must be an object');
|
1877 | 1931 | }
|
1878 | 1932 |
|
1879 |
| - // Apply mixin functions |
1880 |
| - $Mixer._mixins.forEach(function (mixin) { |
1881 |
| - // Reject methods which starts with double $ |
1882 |
| - var keys = _.keys(mixin).filter(function (k) { |
1883 |
| - return k.match(/^(?!\$\$).*$/); |
1884 |
| - }); |
1885 |
| - var proto = _.pick(mixin, keys); |
1886 |
| - // Bind all the methods to the prototype |
1887 |
| - var boundProto = $$utils.bind(proto, _this); |
1888 |
| - // Add the methods to the view model |
1889 |
| - _.extend(vm, boundProto); |
| 1933 | + // Apply extend view model with mixin functions |
| 1934 | + $Mixer._extend(vm, { |
| 1935 | + pattern: /^(?!\$\$).*$/, |
| 1936 | + context: this |
1890 | 1937 | });
|
1891 | 1938 |
|
1892 |
| - // Apply mixin constructors on the view model |
| 1939 | + // Apply mixin constructors on scope with view model |
1893 | 1940 | $Mixer._construct(this, vm);
|
1894 | 1941 | return vm;
|
1895 | 1942 | };
|
|
1908 | 1955 | .service(reactive, [_utils.utils, function ($$utils) {
|
1909 | 1956 | var Reactive = function () {
|
1910 | 1957 | function Reactive(vm) {
|
1911 |
| - var _this2 = this; |
| 1958 | + var _this = this; |
1912 | 1959 |
|
1913 | 1960 | _classCallCheck(this, Reactive);
|
1914 | 1961 |
|
|
1917 | 1964 | }
|
1918 | 1965 |
|
1919 | 1966 | _.defer(function () {
|
1920 |
| - if (!_this2._attached) { |
| 1967 | + if (!_this._attached) { |
1921 | 1968 | console.warn('view model was not attached to any scope');
|
1922 | 1969 | }
|
1923 | 1970 | });
|
|
1980 | 2027 | A mixin which enhance our reactive abilities by providing methods
|
1981 | 2028 | that are capable of updating our scope reactively.
|
1982 | 2029 | */
|
1983 |
| - .factory(Reactive, ['$parse', _utils.utils, function ($parse, $$utils) { |
| 2030 | + .factory(Reactive, ['$parse', _utils.utils, _mixer.Mixer, function ($parse, $$utils, $Mixer) { |
1984 | 2031 | function $$Reactive() {
|
1985 | 2032 | var vm = arguments.length <= 0 || arguments[0] === undefined ? this : arguments[0];
|
1986 | 2033 |
|
|
2021 | 2068 | throw Error('argument 2 must be a boolean');
|
2022 | 2069 | }
|
2023 | 2070 |
|
2024 |
| - return this.$$reactivateEntity(k, this.$watch, isDeep); |
| 2071 | + return this.$$reactivateEntity($Mixer.caller, k, this.$watch, isDeep); |
2025 | 2072 | };
|
2026 | 2073 |
|
2027 | 2074 | // Gets a collection reactively
|
2028 | 2075 | $$Reactive.getCollectionReactively = function (k) {
|
2029 |
| - return this.$$reactivateEntity(k, this.$watchCollection); |
| 2076 | + return this.$$reactivateEntity($Mixer.caller, k, this.$watchCollection); |
2030 | 2077 | };
|
2031 | 2078 |
|
2032 | 2079 | // Gets an entity reactively, and once it has been changed the computation will be recomputed
|
2033 |
| - $$Reactive.$$reactivateEntity = function (k, watcher) { |
| 2080 | + $$Reactive.$$reactivateEntity = function (context, k, watcher) { |
2034 | 2081 | if (!_.isString(k)) {
|
2035 | 2082 | throw Error('argument 1 must be a string');
|
2036 | 2083 | }
|
2037 | 2084 |
|
2038 | 2085 | if (!this.$$vm.$$dependencies[k]) {
|
2039 | 2086 | this.$$vm.$$dependencies[k] = new Tracker.Dependency();
|
2040 | 2087 |
|
2041 |
| - for (var _len = arguments.length, watcherArgs = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { |
2042 |
| - watcherArgs[_key - 2] = arguments[_key]; |
| 2088 | + for (var _len = arguments.length, watcherArgs = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) { |
| 2089 | + watcherArgs[_key - 3] = arguments[_key]; |
2043 | 2090 | }
|
2044 | 2091 |
|
2045 |
| - this.$$watchEntity.apply(this, [k, watcher].concat(watcherArgs)); |
| 2092 | + this.$$watchEntity.apply(this, [context, k, watcher].concat(watcherArgs)); |
2046 | 2093 | }
|
2047 | 2094 |
|
2048 | 2095 | this.$$vm.$$dependencies[k].depend();
|
2049 |
| - return $parse(k)(this.$$vm); |
| 2096 | + return $parse(k)(context); |
2050 | 2097 | };
|
2051 | 2098 |
|
2052 | 2099 | // Watches for changes in the view model, and if so will notify a change
|
2053 |
| - $$Reactive.$$watchEntity = function (k, watcher) { |
| 2100 | + $$Reactive.$$watchEntity = function (context, k, watcher) { |
2054 | 2101 | var _this2 = this;
|
2055 | 2102 |
|
2056 |
| - // Gets a deep property from the view model |
2057 |
| - var getVal = _.partial($parse(k), this.$$vm); |
| 2103 | + // Gets a deep property from the caller |
| 2104 | + var getVal = _.partial($parse(k), context); |
2058 | 2105 | var initialVal = getVal();
|
2059 | 2106 |
|
2060 | 2107 | // Watches for changes in the view model
|
2061 | 2108 |
|
2062 |
| - for (var _len2 = arguments.length, watcherArgs = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { |
2063 |
| - watcherArgs[_key2 - 2] = arguments[_key2]; |
| 2109 | + for (var _len2 = arguments.length, watcherArgs = Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++) { |
| 2110 | + watcherArgs[_key2 - 3] = arguments[_key2]; |
2064 | 2111 | }
|
2065 | 2112 |
|
2066 | 2113 | watcher.call.apply(watcher, [this, getVal, function (val, oldVal) {
|
|
0 commit comments