var config = require('./config'), ViewModel = require('./viewmodel'), utils = require('./utils'), makeHash = utils.hash, assetTypes = ['directive', 'filter', 'partial', 'effect', 'component'] // require these so Browserify can catch them // so they can be used in Vue.require require('./observer') require('./transition') ViewModel.options = config.globalAssets = { directives : require('./directives'), filters : require('./filters'), partials : makeHash(), effects : makeHash(), components : makeHash() } /** * Expose asset registration methods */ assetTypes.forEach(function (type) { ViewModel[type] = function (id, value) { var hash = this.options[type + 's'] if (!hash) { hash = this.options[type + 's'] = makeHash() } if (!value) return hash[id] if (type === 'partial') { value = utils.toFragment(value) } else if (type === 'component') { value = utils.toConstructor(value) } else if (type === 'filter') { utils.checkFilter(value) } hash[id] = value return this } }) /** * Set config options */ ViewModel.config = function (opts, val) { if (typeof opts === 'string') { if (val === undefined) { return config[opts] } else { config[opts] = val } } else { utils.extend(config, opts) } return this } /** * Expose an interface for plugins */ ViewModel.use = function (plugin) { if (typeof plugin === 'string') { try { plugin = require(plugin) } catch (e) { utils.warn('Cannot find plugin: ' + plugin) return } } // additional parameters var args = [].slice.call(arguments, 1) args.unshift(this) if (typeof plugin.install === 'function') { plugin.install.apply(plugin, args) } else { plugin.apply(null, args) } return this } /** * Expose internal modules for plugins */ ViewModel.require = function (path) { return require('./' + path) } ViewModel.extend = extend ViewModel.nextTick = utils.nextTick /** * Expose the main ViewModel class * and add extend method */ function extend (options) { var ParentVM = this // extend data options need to be copied // on instantiation if (options.data) { options.defaultData = options.data delete options.data } // inherit options // but only when the super class is not the native Vue. if (ParentVM !== ViewModel) { options = inheritOptions(options, ParentVM.options, true) } utils.processOptions(options) var ExtendedVM = function (opts, asParent) { if (!asParent) { opts = inheritOptions(opts, options, true) } ParentVM.call(this, opts, true) } // inherit prototype props var proto = ExtendedVM.prototype = Object.create(ParentVM.prototype) utils.defProtected(proto, 'constructor', ExtendedVM) // allow extended VM to be further extended ExtendedVM.extend = extend ExtendedVM.super = ParentVM ExtendedVM.options = options // allow extended VM to add its own assets assetTypes.forEach(function (type) { ExtendedVM[type] = ViewModel[type] }) // allow extended VM to use plugins ExtendedVM.use = ViewModel.use ExtendedVM.require = ViewModel.require return ExtendedVM } /** * Inherit options * * For options such as `data`, `vms`, `directives`, 'partials', * they should be further extended. However extending should only * be done at top level. * * `proto` is an exception because it's handled directly on the * prototype. * * `el` is an exception because it's not allowed as an * extension option, but only as an instance option. */ function inheritOptions (child, parent, topLevel) { child = child || {} if (!parent) return child for (var key in parent) { if (key === 'el') continue var val = child[key], parentVal = parent[key] if (topLevel && typeof val === 'function' && parentVal) { // merge hook functions into an array child[key] = [val] if (Array.isArray(parentVal)) { child[key] = child[key].concat(parentVal) } else { child[key].push(parentVal) } } else if ( topLevel && (utils.isTrueObject(val) || utils.isTrueObject(parentVal)) && !(parentVal instanceof ViewModel) ) { // merge toplevel object options child[key] = inheritOptions(val, parentVal) } else if (val === undefined) { // inherit if child doesn't override child[key] = parentVal } } return child } module.exports = ViewModel