silk-gui
Version:
GUI for developers and Node OS
166 lines (150 loc) • 3.39 kB
JavaScript
var _ = require('../util')
var Watcher = require('../watcher')
var Path = require('../parsers/path')
var textParser = require('../parsers/text')
var dirParser = require('../parsers/directive')
var expParser = require('../parsers/expression')
var filterRE = /[^|]\|[^|]/
/**
* Get the value from an expression on this vm.
*
* @param {String} exp
* @return {*}
*/
exports.$get = function (exp) {
var res = expParser.parse(exp)
if (res) {
try {
return res.get.call(this, this)
} catch (e) {}
}
}
/**
* Set the value from an expression on this vm.
* The expression must be a valid left-hand
* expression in an assignment.
*
* @param {String} exp
* @param {*} val
*/
exports.$set = function (exp, val) {
var res = expParser.parse(exp, true)
if (res && res.set) {
res.set.call(this, this, val)
}
}
/**
* Add a property on the VM
*
* @param {String} key
* @param {*} val
*/
exports.$add = function (key, val) {
this._data.$add(key, val)
}
/**
* Delete a property on the VM
*
* @param {String} key
*/
exports.$delete = function (key) {
this._data.$delete(key)
}
/**
* Watch an expression, trigger callback when its
* value changes.
*
* @param {String} exp
* @param {Function} cb
* @param {Boolean} [deep]
* @param {Boolean} [immediate]
* @return {Function} - unwatchFn
*/
exports.$watch = function (exp, cb, deep, immediate) {
var vm = this
var key = deep ? exp + '**deep**' : exp
var watcher = vm._userWatchers[key]
var wrappedCb = function (val, oldVal) {
cb.call(vm, val, oldVal)
}
if (!watcher) {
watcher = vm._userWatchers[key] =
new Watcher(vm, exp, wrappedCb, {
deep: deep,
user: true
})
} else {
watcher.addCb(wrappedCb)
}
if (immediate) {
wrappedCb(watcher.value)
}
return function unwatchFn () {
watcher.removeCb(wrappedCb)
if (!watcher.active) {
vm._userWatchers[key] = null
}
}
}
/**
* Evaluate a text directive, including filters.
*
* @param {String} text
* @return {String}
*/
exports.$eval = function (text) {
// check for filters.
if (filterRE.test(text)) {
var dir = dirParser.parse(text)[0]
// the filter regex check might give false positive
// for pipes inside strings, so it's possible that
// we don't get any filters here
return dir.filters
? _.applyFilters(
this.$get(dir.expression),
_.resolveFilters(this, dir.filters).read,
this
)
: this.$get(dir.expression)
} else {
// no filter
return this.$get(text)
}
}
/**
* Interpolate a piece of template text.
*
* @param {String} text
* @return {String}
*/
exports.$interpolate = function (text) {
var tokens = textParser.parse(text)
var vm = this
if (tokens) {
return tokens.length === 1
? vm.$eval(tokens[0].value)
: tokens.map(function (token) {
return token.tag
? vm.$eval(token.value)
: token.value
}).join('')
} else {
return text
}
}
/**
* Log instance data as a plain JS object
* so that it is easier to inspect in console.
* This method assumes console is available.
*
* @param {String} [path]
*/
exports.$log = function (path) {
var data = path
? Path.get(this._data, path)
: this._data
if (data) {
data = JSON.parse(JSON.stringify(data))
}
console.log(data)
}