From 77354dced4c70637f5531a3df992d67a06006bb2 Mon Sep 17 00:00:00 2001 From: David Neukirchen Date: Sun, 26 Feb 2017 07:54:02 +0100 Subject: [PATCH 1/5] Bring back the ugly joomla toolbar --- .../layouts/toolbar/create-folder.php | 14 + .../com_media/layouts/toolbar/delete.php | 14 + .../com_media/layouts/toolbar/upload.php | 14 + .../resources/styles/mediamanager.scss | 6 +- .../com_media/views/media/view.html.php | 42 + media/com_media/css/mediamanager.css | 5 +- media/com_media/js/mediamanager.js | 3221 ++++++++--------- 7 files changed, 1659 insertions(+), 1657 deletions(-) create mode 100644 administrator/components/com_media/layouts/toolbar/create-folder.php create mode 100644 administrator/components/com_media/layouts/toolbar/delete.php create mode 100644 administrator/components/com_media/layouts/toolbar/upload.php diff --git a/administrator/components/com_media/layouts/toolbar/create-folder.php b/administrator/components/com_media/layouts/toolbar/create-folder.php new file mode 100644 index 0000000000..1b59338d24 --- /dev/null +++ b/administrator/components/com_media/layouts/toolbar/create-folder.php @@ -0,0 +1,14 @@ + + \ No newline at end of file diff --git a/administrator/components/com_media/layouts/toolbar/delete.php b/administrator/components/com_media/layouts/toolbar/delete.php new file mode 100644 index 0000000000..408926a490 --- /dev/null +++ b/administrator/components/com_media/layouts/toolbar/delete.php @@ -0,0 +1,14 @@ + + \ No newline at end of file diff --git a/administrator/components/com_media/layouts/toolbar/upload.php b/administrator/components/com_media/layouts/toolbar/upload.php new file mode 100644 index 0000000000..10de2bee10 --- /dev/null +++ b/administrator/components/com_media/layouts/toolbar/upload.php @@ -0,0 +1,14 @@ + + \ No newline at end of file diff --git a/administrator/components/com_media/resources/styles/mediamanager.scss b/administrator/components/com_media/resources/styles/mediamanager.scss index a2a80a8cc7..4cdbf9c40f 100644 --- a/administrator/components/com_media/resources/styles/mediamanager.scss +++ b/administrator/components/com_media/resources/styles/mediamanager.scss @@ -5,9 +5,9 @@ $sidebar-width: 16.666666%; .media-container { height: 100%; flex-direction: column; - margin-top: -57px; - margin-left: -15px; - margin-right: -15px; + //margin-top: -57px; + //margin-left: -15px; + //margin-right: -15px; } .media-main { diff --git a/administrator/components/com_media/views/media/view.html.php b/administrator/components/com_media/views/media/view.html.php index 75b0f02d96..f26a3b8bb3 100644 --- a/administrator/components/com_media/views/media/view.html.php +++ b/administrator/components/com_media/views/media/view.html.php @@ -43,7 +43,49 @@ public function display($tpl = null) */ protected function prepareToolbar() { + // Get the toolbar object instance + $bar = JToolbar::getInstance('toolbar'); + $user = JFactory::getUser(); + // Set the title JToolbarHelper::title(JText::_('COM_MEDIA'), 'images mediamanager'); + + // Add an upload button + if ($user->authorise('core.create', 'com_media')) + { + // Instantiate a new JLayoutFile instance and render the layout + $layout = new JLayoutFile('toolbar.upload', JPATH_COMPONENT_ADMINISTRATOR . '/legacy/layouts'); + + $bar->appendButton('Custom', $layout->render(array()), 'upload'); + JToolbarHelper::divider(); + } + + // Add an upload button + if ($user->authorise('core.create', 'com_media')) + { + // Instantiate a new JLayoutFile instance and render the layout + $layout = new JLayoutFile('toolbar.create-folder', JPATH_COMPONENT_ADMINISTRATOR . '/legacy/layouts'); + + $bar->appendButton('Custom', $layout->render(array()), 'new'); + JToolbarHelper::divider(); + } + + // Add a delete button + if ($user->authorise('core.delete', 'com_media')) + { + // Instantiate a new JLayoutFile instance and render the layout + $layout = new JLayoutFile('toolbar.delete', JPATH_COMPONENT_ADMINISTRATOR . '/legacy/layouts'); + $bar->appendButton('Custom', $layout->render(array()), 'upload'); + JToolbarHelper::divider(); + } + + // Add the preferences button + if ($user->authorise('core.admin', 'com_media') || $user->authorise('core.options', 'com_media')) + { + JToolbarHelper::preferences('com_media'); + JToolbarHelper::divider(); + } + + JToolbarHelper::help('JHELP_CONTENT_MEDIA_MANAGER'); } } diff --git a/media/com_media/css/mediamanager.css b/media/com_media/css/mediamanager.css index 63dd214cd8..98a8d4149d 100644 --- a/media/com_media/css/mediamanager.css +++ b/media/com_media/css/mediamanager.css @@ -1,10 +1,7 @@ /* General layout */ .media-container { height: 100%; - flex-direction: column; - margin-top: -57px; - margin-left: -15px; - margin-right: -15px; } + flex-direction: column; } .media-main { min-height: 100%; diff --git a/media/com_media/js/mediamanager.js b/media/com_media/js/mediamanager.js index ed8e77037d..47d76f7e18 100644 --- a/media/com_media/js/mediamanager.js +++ b/media/com_media/js/mediamanager.js @@ -409,10 +409,136 @@ process.chdir = function (dir) { process.umask = function() { return 0; }; },{}],3:[function(require,module,exports){ +var Vue // late bind +var map = window.__VUE_HOT_MAP__ = Object.create(null) +var installed = false +var isBrowserify = false +var initHookName = 'beforeCreate' + +exports.install = function (vue, browserify) { + if (installed) return + installed = true + + Vue = vue + isBrowserify = browserify + + // compat with < 2.0.0-alpha.7 + if (Vue.config._lifecycleHooks.indexOf('init') > -1) { + initHookName = 'init' + } + + exports.compatible = Number(Vue.version.split('.')[0]) >= 2 + if (!exports.compatible) { + console.warn( + '[HMR] You are using a version of vue-hot-reload-api that is ' + + 'only compatible with Vue.js core ^2.0.0.' + ) + return + } +} + +/** + * Create a record for a hot module, which keeps track of its constructor + * and instances + * + * @param {String} id + * @param {Object} options + */ + +exports.createRecord = function (id, options) { + var Ctor = null + if (typeof options === 'function') { + Ctor = options + options = Ctor.options + } + makeOptionsHot(id, options) + map[id] = { + Ctor: Vue.extend(options), + instances: [] + } +} + +/** + * Make a Component options object hot. + * + * @param {String} id + * @param {Object} options + */ + +function makeOptionsHot (id, options) { + injectHook(options, initHookName, function () { + map[id].instances.push(this) + }) + injectHook(options, 'beforeDestroy', function () { + var instances = map[id].instances + instances.splice(instances.indexOf(this), 1) + }) +} + +/** + * Inject a hook to a hot reloadable component so that + * we can keep track of it. + * + * @param {Object} options + * @param {String} name + * @param {Function} hook + */ + +function injectHook (options, name, hook) { + var existing = options[name] + options[name] = existing + ? Array.isArray(existing) + ? existing.concat(hook) + : [existing, hook] + : [hook] +} + +function tryWrap (fn) { + return function (id, arg) { + try { fn(id, arg) } catch (e) { + console.error(e) + console.warn('Something went wrong during Vue component hot-reload. Full reload required.') + } + } +} + +exports.rerender = tryWrap(function (id, fns) { + var record = map[id] + record.Ctor.options.render = fns.render + record.Ctor.options.staticRenderFns = fns.staticRenderFns + record.instances.slice().forEach(function (instance) { + instance.$options.render = fns.render + instance.$options.staticRenderFns = fns.staticRenderFns + instance._staticTrees = [] // reset static trees + instance.$forceUpdate() + }) +}) + +exports.reload = tryWrap(function (id, options) { + makeOptionsHot(id, options) + var record = map[id] + record.Ctor.extendOptions = options + var newCtor = Vue.extend(options) + record.Ctor.options = newCtor.options + record.Ctor.cid = newCtor.cid + if (newCtor.release) { + // temporary global mixin strategy used in < 2.0.0-alpha.6 + newCtor.release() + } + record.instances.slice().forEach(function (instance) { + if (instance.$vnode && instance.$vnode.context) { + instance.$vnode.context.$forceUpdate() + } else { + console.warn('Root or manually mounted instance modified. Full reload required.') + } + }) +}) + +},{}],4:[function(require,module,exports){ (function (process,global){ /*! - * Vue.js v2.1.10 - * (c) 2014-2017 Evan You + * Vue.js v2.1.8 + * (c) 2014-2016 Evan You * Released under the MIT License. */ 'use strict'; @@ -435,8 +561,8 @@ function _toString (val) { * If the conversion fails, return original string. */ function toNumber (val) { - var n = parseFloat(val); - return isNaN(n) ? val : n + var n = parseFloat(val, 10); + return (n || n === 0) ? n : val } /** @@ -501,7 +627,7 @@ function cached (fn) { } /** - * Camelize a hyphen-delimited string. + * Camelize a hyphen-delmited string. */ var camelizeRE = /-(\w)/g; var camelize = cached(function (str) { @@ -1911,953 +2037,808 @@ if (process.env.NODE_ENV !== 'production') { /* */ -var VNode = function VNode ( - tag, - data, - children, - text, - elm, - context, - componentOptions -) { - this.tag = tag; - this.data = data; - this.children = children; - this.text = text; - this.elm = elm; - this.ns = undefined; - this.context = context; - this.functionalContext = undefined; - this.key = data && data.key; - this.componentOptions = componentOptions; - this.componentInstance = undefined; - this.parent = undefined; - this.raw = false; - this.isStatic = false; - this.isRootInsert = true; - this.isComment = false; - this.isCloned = false; - this.isOnce = false; -}; - -var prototypeAccessors = { child: {} }; - -// DEPRECATED: alias for componentInstance for backwards compat. -/* istanbul ignore next */ -prototypeAccessors.child.get = function () { - return this.componentInstance -}; - -Object.defineProperties( VNode.prototype, prototypeAccessors ); - -var createEmptyVNode = function () { - var node = new VNode(); - node.text = ''; - node.isComment = true; - return node -}; - -function createTextVNode (val) { - return new VNode(undefined, undefined, undefined, String(val)) -} -// optimized shallow clone -// used for static nodes and slot nodes because they may be reused across -// multiple renders, cloning them avoids errors when DOM manipulations rely -// on their elm reference. -function cloneVNode (vnode) { - var cloned = new VNode( - vnode.tag, - vnode.data, - vnode.children, - vnode.text, - vnode.elm, - vnode.context, - vnode.componentOptions - ); - cloned.ns = vnode.ns; - cloned.isStatic = vnode.isStatic; - cloned.key = vnode.key; - cloned.isCloned = true; - return cloned -} +var queue = []; +var has$1 = {}; +var circular = {}; +var waiting = false; +var flushing = false; +var index = 0; -function cloneVNodes (vnodes) { - var res = new Array(vnodes.length); - for (var i = 0; i < vnodes.length; i++) { - res[i] = cloneVNode(vnodes[i]); +/** + * Reset the scheduler's state. + */ +function resetSchedulerState () { + queue.length = 0; + has$1 = {}; + if (process.env.NODE_ENV !== 'production') { + circular = {}; } - return res + waiting = flushing = false; } -/* */ +/** + * Flush both queues and run the watchers. + */ +function flushSchedulerQueue () { + flushing = true; -var hooks = { init: init, prepatch: prepatch, insert: insert, destroy: destroy$1 }; -var hooksToMerge = Object.keys(hooks); + // Sort queue before flush. + // This ensures that: + // 1. Components are updated from parent to child. (because parent is always + // created before the child) + // 2. A component's user watchers are run before its render watcher (because + // user watchers are created before the render watcher) + // 3. If a component is destroyed during a parent component's watcher run, + // its watchers can be skipped. + queue.sort(function (a, b) { return a.id - b.id; }); -function createComponent ( - Ctor, - data, - context, - children, - tag -) { - if (!Ctor) { - return + // do not cache length because more watchers might be pushed + // as we run existing watchers + for (index = 0; index < queue.length; index++) { + var watcher = queue[index]; + var id = watcher.id; + has$1[id] = null; + watcher.run(); + // in dev build, check and stop circular updates. + if (process.env.NODE_ENV !== 'production' && has$1[id] != null) { + circular[id] = (circular[id] || 0) + 1; + if (circular[id] > config._maxUpdateCount) { + warn( + 'You may have an infinite update loop ' + ( + watcher.user + ? ("in watcher with expression \"" + (watcher.expression) + "\"") + : "in a component render function." + ), + watcher.vm + ); + break + } + } } - var baseCtor = context.$options._base; - if (isObject(Ctor)) { - Ctor = baseCtor.extend(Ctor); + // devtool hook + /* istanbul ignore if */ + if (devtools && config.devtools) { + devtools.emit('flush'); } - if (typeof Ctor !== 'function') { - if (process.env.NODE_ENV !== 'production') { - warn(("Invalid Component definition: " + (String(Ctor))), context); - } - return - } + resetSchedulerState(); +} - // async component - if (!Ctor.cid) { - if (Ctor.resolved) { - Ctor = Ctor.resolved; +/** + * Push a watcher into the watcher queue. + * Jobs with duplicate IDs will be skipped unless it's + * pushed when the queue is being flushed. + */ +function queueWatcher (watcher) { + var id = watcher.id; + if (has$1[id] == null) { + has$1[id] = true; + if (!flushing) { + queue.push(watcher); } else { - Ctor = resolveAsyncComponent(Ctor, baseCtor, function () { - // it's ok to queue this on every render because - // $forceUpdate is buffered by the scheduler. - context.$forceUpdate(); - }); - if (!Ctor) { - // return nothing if this is indeed an async component - // wait for the callback to trigger parent update. - return + // if already flushing, splice the watcher based on its id + // if already past its id, it will be run next immediately. + var i = queue.length - 1; + while (i >= 0 && queue[i].id > watcher.id) { + i--; } + queue.splice(Math.max(i, index) + 1, 0, watcher); } - } - - // resolve constructor options in case global mixins are applied after - // component constructor creation - resolveConstructorOptions(Ctor); - - data = data || {}; - - // extract props - var propsData = extractProps(data, Ctor); - - // functional component - if (Ctor.options.functional) { - return createFunctionalComponent(Ctor, propsData, data, context, children) - } - - // extract listeners, since these needs to be treated as - // child component listeners instead of DOM listeners - var listeners = data.on; - // replace with listeners with .native modifier - data.on = data.nativeOn; - - if (Ctor.options.abstract) { - // abstract components do not keep anything - // other than props & listeners - data = {}; - } - - // merge component management hooks onto the placeholder node - mergeHooks(data); - - // return a placeholder vnode - var name = Ctor.options.name || tag; - var vnode = new VNode( - ("vue-component-" + (Ctor.cid) + (name ? ("-" + name) : '')), - data, undefined, undefined, undefined, context, - { Ctor: Ctor, propsData: propsData, listeners: listeners, tag: tag, children: children } - ); - return vnode -} - -function createFunctionalComponent ( - Ctor, - propsData, - data, - context, - children -) { - var props = {}; - var propOptions = Ctor.options.props; - if (propOptions) { - for (var key in propOptions) { - props[key] = validateProp(key, propOptions, propsData); - } - } - // ensure the createElement function in functional components - // gets a unique context - this is necessary for correct named slot check - var _context = Object.create(context); - var h = function (a, b, c, d) { return createElement(_context, a, b, c, d, true); }; - var vnode = Ctor.options.render.call(null, h, { - props: props, - data: data, - parent: context, - children: children, - slots: function () { return resolveSlots(children, context); } - }); - if (vnode instanceof VNode) { - vnode.functionalContext = context; - if (data.slot) { - (vnode.data || (vnode.data = {})).slot = data.slot; - } - } - return vnode -} - -function createComponentInstanceForVnode ( - vnode, // we know it's MountedComponentVNode but flow doesn't - parent, // activeInstance in lifecycle state - parentElm, - refElm -) { - var vnodeComponentOptions = vnode.componentOptions; - var options = { - _isComponent: true, - parent: parent, - propsData: vnodeComponentOptions.propsData, - _componentTag: vnodeComponentOptions.tag, - _parentVnode: vnode, - _parentListeners: vnodeComponentOptions.listeners, - _renderChildren: vnodeComponentOptions.children, - _parentElm: parentElm || null, - _refElm: refElm || null - }; - // check inline-template render functions - var inlineTemplate = vnode.data.inlineTemplate; - if (inlineTemplate) { - options.render = inlineTemplate.render; - options.staticRenderFns = inlineTemplate.staticRenderFns; - } - return new vnodeComponentOptions.Ctor(options) -} - -function init ( - vnode, - hydrating, - parentElm, - refElm -) { - if (!vnode.componentInstance || vnode.componentInstance._isDestroyed) { - var child = vnode.componentInstance = createComponentInstanceForVnode( - vnode, - activeInstance, - parentElm, - refElm - ); - child.$mount(hydrating ? vnode.elm : undefined, hydrating); - } else if (vnode.data.keepAlive) { - // kept-alive components, treat as a patch - var mountedNode = vnode; // work around flow - prepatch(mountedNode, mountedNode); - } -} - -function prepatch ( - oldVnode, - vnode -) { - var options = vnode.componentOptions; - var child = vnode.componentInstance = oldVnode.componentInstance; - child._updateFromParent( - options.propsData, // updated props - options.listeners, // updated listeners - vnode, // new parent vnode - options.children // new children - ); -} - -function insert (vnode) { - if (!vnode.componentInstance._isMounted) { - vnode.componentInstance._isMounted = true; - callHook(vnode.componentInstance, 'mounted'); - } - if (vnode.data.keepAlive) { - vnode.componentInstance._inactive = false; - callHook(vnode.componentInstance, 'activated'); - } -} - -function destroy$1 (vnode) { - if (!vnode.componentInstance._isDestroyed) { - if (!vnode.data.keepAlive) { - vnode.componentInstance.$destroy(); - } else { - vnode.componentInstance._inactive = true; - callHook(vnode.componentInstance, 'deactivated'); + // queue the flush + if (!waiting) { + waiting = true; + nextTick(flushSchedulerQueue); } } } -function resolveAsyncComponent ( - factory, - baseCtor, - cb -) { - if (factory.requested) { - // pool callbacks - factory.pendingCallbacks.push(cb); - } else { - factory.requested = true; - var cbs = factory.pendingCallbacks = [cb]; - var sync = true; - - var resolve = function (res) { - if (isObject(res)) { - res = baseCtor.extend(res); - } - // cache resolved - factory.resolved = res; - // invoke callbacks only if this is not a synchronous resolve - // (async resolves are shimmed as synchronous during SSR) - if (!sync) { - for (var i = 0, l = cbs.length; i < l; i++) { - cbs[i](res); - } - } - }; - - var reject = function (reason) { - process.env.NODE_ENV !== 'production' && warn( - "Failed to resolve async component: " + (String(factory)) + - (reason ? ("\nReason: " + reason) : '') - ); - }; - - var res = factory(resolve, reject); - - // handle promise - if (res && typeof res.then === 'function' && !factory.resolved) { - res.then(resolve, reject); - } - - sync = false; - // return in case resolved synchronously - return factory.resolved - } -} +/* */ -function extractProps (data, Ctor) { - // we are only extracting raw values here. - // validation and default values are handled in the child - // component itself. - var propOptions = Ctor.options.props; - if (!propOptions) { - return - } - var res = {}; - var attrs = data.attrs; - var props = data.props; - var domProps = data.domProps; - if (attrs || props || domProps) { - for (var key in propOptions) { - var altKey = hyphenate(key); - checkProp(res, props, key, altKey, true) || - checkProp(res, attrs, key, altKey) || - checkProp(res, domProps, key, altKey); - } - } - return res -} +var uid$2 = 0; -function checkProp ( - res, - hash, - key, - altKey, - preserve +/** + * A watcher parses an expression, collects dependencies, + * and fires callback when the expression value changes. + * This is used for both the $watch() api and directives. + */ +var Watcher = function Watcher ( + vm, + expOrFn, + cb, + options ) { - if (hash) { - if (hasOwn(hash, key)) { - res[key] = hash[key]; - if (!preserve) { - delete hash[key]; - } - return true - } else if (hasOwn(hash, altKey)) { - res[key] = hash[altKey]; - if (!preserve) { - delete hash[altKey]; - } - return true + this.vm = vm; + vm._watchers.push(this); + // options + if (options) { + this.deep = !!options.deep; + this.user = !!options.user; + this.lazy = !!options.lazy; + this.sync = !!options.sync; + } else { + this.deep = this.user = this.lazy = this.sync = false; + } + this.cb = cb; + this.id = ++uid$2; // uid for batching + this.active = true; + this.dirty = this.lazy; // for lazy watchers + this.deps = []; + this.newDeps = []; + this.depIds = new _Set(); + this.newDepIds = new _Set(); + this.expression = process.env.NODE_ENV !== 'production' + ? expOrFn.toString() + : ''; + // parse expression for getter + if (typeof expOrFn === 'function') { + this.getter = expOrFn; + } else { + this.getter = parsePath(expOrFn); + if (!this.getter) { + this.getter = function () {}; + process.env.NODE_ENV !== 'production' && warn( + "Failed watching path: \"" + expOrFn + "\" " + + 'Watcher only accepts simple dot-delimited paths. ' + + 'For full control, use a function instead.', + vm + ); } } - return false -} + this.value = this.lazy + ? undefined + : this.get(); +}; -function mergeHooks (data) { - if (!data.hook) { - data.hook = {}; - } - for (var i = 0; i < hooksToMerge.length; i++) { - var key = hooksToMerge[i]; - var fromParent = data.hook[key]; - var ours = hooks[key]; - data.hook[key] = fromParent ? mergeHook$1(ours, fromParent) : ours; +/** + * Evaluate the getter, and re-collect dependencies. + */ +Watcher.prototype.get = function get () { + pushTarget(this); + var value = this.getter.call(this.vm, this.vm); + // "touch" every property so they are all tracked as + // dependencies for deep watching + if (this.deep) { + traverse(value); } -} + popTarget(); + this.cleanupDeps(); + return value +}; -function mergeHook$1 (one, two) { - return function (a, b, c, d) { - one(a, b, c, d); - two(a, b, c, d); +/** + * Add a dependency to this directive. + */ +Watcher.prototype.addDep = function addDep (dep) { + var id = dep.id; + if (!this.newDepIds.has(id)) { + this.newDepIds.add(id); + this.newDeps.push(dep); + if (!this.depIds.has(id)) { + dep.addSub(this); + } } -} +}; -/* */ +/** + * Clean up for dependency collection. + */ +Watcher.prototype.cleanupDeps = function cleanupDeps () { + var this$1 = this; -function mergeVNodeHook (def, hookKey, hook, key) { - key = key + hookKey; - var injectedHash = def.__injected || (def.__injected = {}); - if (!injectedHash[key]) { - injectedHash[key] = true; - var oldHook = def[hookKey]; - if (oldHook) { - def[hookKey] = function () { - oldHook.apply(this, arguments); - hook.apply(this, arguments); - }; - } else { - def[hookKey] = hook; + var i = this.deps.length; + while (i--) { + var dep = this$1.deps[i]; + if (!this$1.newDepIds.has(dep.id)) { + dep.removeSub(this$1); } } -} - -/* */ + var tmp = this.depIds; + this.depIds = this.newDepIds; + this.newDepIds = tmp; + this.newDepIds.clear(); + tmp = this.deps; + this.deps = this.newDeps; + this.newDeps = tmp; + this.newDeps.length = 0; +}; -var normalizeEvent = cached(function (name) { - var once = name.charAt(0) === '~'; // Prefixed last, checked first - name = once ? name.slice(1) : name; - var capture = name.charAt(0) === '!'; - name = capture ? name.slice(1) : name; - return { - name: name, - once: once, - capture: capture +/** + * Subscriber interface. + * Will be called when a dependency changes. + */ +Watcher.prototype.update = function update () { + /* istanbul ignore else */ + if (this.lazy) { + this.dirty = true; + } else if (this.sync) { + this.run(); + } else { + queueWatcher(this); } -}); - -function createEventHandle (fn) { - var handle = { - fn: fn, - invoker: function () { - var arguments$1 = arguments; +}; - var fn = handle.fn; - if (Array.isArray(fn)) { - for (var i = 0; i < fn.length; i++) { - fn[i].apply(null, arguments$1); +/** + * Scheduler job interface. + * Will be called by the scheduler. + */ +Watcher.prototype.run = function run () { + if (this.active) { + var value = this.get(); + if ( + value !== this.value || + // Deep watchers and watchers on Object/Arrays should fire even + // when the value is the same, because the value may + // have mutated. + isObject(value) || + this.deep + ) { + // set new value + var oldValue = this.value; + this.value = value; + if (this.user) { + try { + this.cb.call(this.vm, value, oldValue); + } catch (e) { + /* istanbul ignore else */ + if (config.errorHandler) { + config.errorHandler.call(null, e, this.vm); + } else { + process.env.NODE_ENV !== 'production' && warn( + ("Error in watcher \"" + (this.expression) + "\""), + this.vm + ); + throw e + } } } else { - fn.apply(null, arguments); - } - } - }; - return handle -} - -function updateListeners ( - on, - oldOn, - add, - remove$$1, - vm -) { - var name, cur, old, event; - for (name in on) { - cur = on[name]; - old = oldOn[name]; - event = normalizeEvent(name); - if (!cur) { - process.env.NODE_ENV !== 'production' && warn( - "Invalid handler for event \"" + (event.name) + "\": got " + String(cur), - vm - ); - } else if (!old) { - if (!cur.invoker) { - cur = on[name] = createEventHandle(cur); + this.cb.call(this.vm, value, oldValue); } - add(event.name, cur.invoker, event.once, event.capture); - } else if (cur !== old) { - old.fn = cur; - on[name] = old; - } - } - for (name in oldOn) { - if (!on[name]) { - event = normalizeEvent(name); - remove$$1(event.name, oldOn[name].invoker, event.capture); } } -} +}; -/* */ +/** + * Evaluate the value of the watcher. + * This only gets called for lazy watchers. + */ +Watcher.prototype.evaluate = function evaluate () { + this.value = this.get(); + this.dirty = false; +}; -// The template compiler attempts to minimize the need for normalization by -// statically analyzing the template at compile time. -// -// For plain HTML markup, normalization can be completely skipped because the -// generated render function is guaranteed to return Array. There are -// two cases where extra normalization is needed: +/** + * Depend on all deps collected by this watcher. + */ +Watcher.prototype.depend = function depend () { + var this$1 = this; -// 1. When the children contains components - because a functional component -// may return an Array instead of a single root. In this case, just a simple -// nomralization is needed - if any child is an Array, we flatten the whole -// thing with Array.prototype.concat. It is guaranteed to be only 1-level deep -// because functional components already normalize their own children. -function simpleNormalizeChildren (children) { - for (var i = 0; i < children.length; i++) { - if (Array.isArray(children[i])) { - return Array.prototype.concat.apply([], children) + var i = this.deps.length; + while (i--) { + this$1.deps[i].depend(); + } +}; + +/** + * Remove self from all dependencies' subscriber list. + */ +Watcher.prototype.teardown = function teardown () { + var this$1 = this; + + if (this.active) { + // remove self from vm's watcher list + // this is a somewhat expensive operation so we skip it + // if the vm is being destroyed. + if (!this.vm._isBeingDestroyed) { + remove$1(this.vm._watchers, this); + } + var i = this.deps.length; + while (i--) { + this$1.deps[i].removeSub(this$1); } + this.active = false; } - return children -} +}; -// 2. When the children contains constrcuts that always generated nested Arrays, -// e.g.