Comparing version 1.0.5 to 1.0.6
@@ -6,6 +6,2 @@ (function(global) { | ||
$scope.buttonClicked = function(text) { | ||
console.log(text); | ||
}; | ||
setTimeout(function() { | ||
@@ -12,0 +8,0 @@ $scope.title = "Hello World!"; |
@@ -6,6 +6,2 @@ (function(global) { | ||
$scope.buttonClicked = function(text) { | ||
console.log(text); | ||
}; | ||
setTimeout(function() { | ||
@@ -20,6 +16,30 @@ $scope.title = "Hello World!"; | ||
global.App.Controller('test', './test/', function($scope, _update) { | ||
$scope.getInput('text'); | ||
var appRoutes = [ | ||
{ path: '', redirect: 'home' }, | ||
{ path: 'home', controller: 'main-layout' }, | ||
{ path: 'about', controller: 'about' } | ||
]; | ||
new global.App.Router(appRoutes); | ||
})(Function('return this')()); | ||
(function(global) { | ||
global.App.Controller('about', '/about/', function($scope, _update) { | ||
$scope.buttonClicked = function(pageName) { | ||
global.App.Router().navigateTo(pageName); | ||
}; | ||
}); | ||
})(Function('return this')()); | ||
})(Function('return this')()); | ||
(function(global) { | ||
global.App.Controller('main-layout', '/main-layout/', function($scope, _update) { | ||
$scope.title = "Main Layout"; | ||
$scope.buttonClicked = function(pageName) { | ||
global.App.Router().navigateTo(pageName); | ||
}; | ||
}); | ||
})(Function('return this')()); |
@@ -1,1 +0,1 @@ | ||
Function("return this")().App.Controller("app","./",function(t,n){t.title="App works!",t.buttonClicked=function(t){console.log(t)},setTimeout(function(){t.title="Hello World!",n()},3e3)}),Function("return this")().App.Controller("test","./test/",function(t,n){t.getInput("text")}); | ||
Function("return this")().App.Controller("app","./",function(t,o){t.title="App works!",setTimeout(function(){t.title="Hello World!",o()},3e3)}),new(Function("return this")().App.Router)([{path:"",redirect:"home"},{path:"home",controller:"main-layout"},{path:"about",controller:"about"}]),function(t){t.App.Controller("about","/about/",function(o,n){o.buttonClicked=function(o){t.App.Router().navigateTo(o)}})}(Function("return this")()),function(t){t.App.Controller("main-layout","/main-layout/",function(o,n){o.title="Main Layout",o.buttonClicked=function(o){t.App.Router().navigateTo(o)}})}(Function("return this")()); |
@@ -70,15 +70,20 @@ (function(global) { | ||
updateObject: function(origin, update, ignore) { | ||
var changes = 0; | ||
if(typeof origin === 'object' && typeof update === 'object') { | ||
for(var property in update) if(update.hasOwnProperty(property) && !isIgnored(property)) { | ||
switch(typeof update[property]) { | ||
case 'object': | ||
changes += ObjectFuncs.updateObject(origin[property], update[property]); | ||
break; | ||
default: | ||
if(origin[property] !== update[property]) { | ||
origin[property] = update[property]; | ||
changes++; | ||
} | ||
break; | ||
if(origin && update) { | ||
var changes = 0; | ||
if(typeof origin === 'object' && typeof update === 'object') { | ||
for(var property in update) if(update.hasOwnProperty(property) && !isIgnored(property)) { | ||
switch(typeof update[property]) { | ||
case 'object': | ||
if(Array.isArray(update[property])) { | ||
console.warning('[Utils:Object] "updateObject" does not support merging arrays.'); | ||
} else | ||
changes += ObjectFuncs.updateObject(origin[property], update[property]); | ||
break; | ||
default: | ||
if(origin[property] !== update[property]) { | ||
origin[property] = update[property]; | ||
changes++; | ||
} | ||
break; | ||
} | ||
} | ||
@@ -166,5 +171,7 @@ } | ||
}, | ||
toDictionary: function(str, separator) { | ||
toDictionary: function(str, separator, equalizer) { | ||
if(typeof separator !== 'string') | ||
separator = ','; | ||
if(typeof equalizer !== 'string') | ||
equalizer = ':'; | ||
var entries = str.split(separator), | ||
@@ -174,4 +181,6 @@ matchGroups, | ||
entries.forEach(function(entry) { | ||
matchGroups = (/([\w-]+): *(.+)/g).exec(entry.trim()); | ||
dic[matchGroups[1]] = matchGroups[2]; | ||
var regexp = new RegExp('([\\w-]+)' + equalizer + ' *(.+)'); | ||
matchGroups = regexp.exec(entry.trim()); | ||
if(Array.isArray(matchGroups) && matchGroups.length === 3) | ||
dic[matchGroups[1]] = matchGroups[2]; | ||
}); | ||
@@ -196,4 +205,5 @@ return dic; | ||
CompNode.prototype.compare = function($scope) { | ||
var updated = false; | ||
CompNode.prototype.compare = function(comp) { | ||
var updated = false, $scope = comp.$scope; | ||
if(Array.isArray(this.viewNode.directives)) { | ||
@@ -204,3 +214,3 @@ var directives = this.viewNode.directives, | ||
injectable = directives[i].injectable; | ||
getterValue = injectable.getter(directives[i].statement, $scope); | ||
getterValue = injectable.getter(directives[i].statement, comp); | ||
@@ -237,10 +247,14 @@ // If injectable getter with current scope result is | ||
// Ignoring the iterator directive for now | ||
viewNode.directives[tempDirectivePos] = undefined; | ||
for(i = 0; i < iterator.array.length; i++) { | ||
// Injecting the proper value to scope | ||
$scope[iterator.varName] = iterator.array[i]; | ||
if(this.children[i] instanceof CompNode) { | ||
this.children[i].compare($scope); | ||
this.children[i].compare(comp); | ||
this.children[i].iteratorValue = iterator.array[i]; | ||
} else { | ||
newCompNode = viewNode.generate($scope); | ||
newCompNode = viewNode.generate(comp); | ||
newCompNode.iteratorValue = iterator.array[i]; | ||
@@ -255,3 +269,3 @@ this.appendChild(newCompNode); | ||
this.children.forEach(function(child) { | ||
child.compare($scope); | ||
child.compare(comp); | ||
}); | ||
@@ -261,3 +275,3 @@ } | ||
// If there were changes, generate a new node. | ||
var newNode = this.viewNode.generate($scope); | ||
var newNode = this.viewNode.generate(comp); | ||
@@ -271,6 +285,4 @@ if(this.iteratorValue) | ||
// Finally if node is a component bootstrap it. | ||
if(newNode.isComponent()) { | ||
newNode.comp = global.Core.Bootstrap(newNode.self, newNode.inputs); | ||
newNode.self = newNode.comp.nodeTree.self; | ||
} | ||
if(newNode.isComponent()) | ||
newNode.bootstrap(comp); | ||
} | ||
@@ -322,7 +334,9 @@ }; | ||
CompNode.prototype.isComponent = function() { | ||
return this.self && this.self.nodeType === 1 && this.viewNode.controller && !this.iterator; | ||
return this.self && this.self.nodeType === 1 && | ||
(this.viewNode.controller || typeof this.self.getAttribute('controller') === 'string') && | ||
!this.iterator; | ||
}; | ||
CompNode.prototype.bootstrap = function() { | ||
this.comp = global.Core.Bootstrap(this.self, this.inputs); | ||
CompNode.prototype.bootstrap = function(parent) { | ||
this.comp = global.Core.Bootstrap(this.self, parent, this.inputs); | ||
this.self = this.comp.nodeTree.self; | ||
@@ -337,4 +351,9 @@ }; | ||
var Component = function(el, $scope) { | ||
var Component = function(el, parent, $scope) { | ||
this.el = el; | ||
if(parent instanceof Component) { | ||
this.parent = parent; | ||
parent.children = parent.children || []; | ||
parent.children.push(this); | ||
} | ||
this.$scope = $scope; | ||
@@ -350,3 +369,4 @@ }; | ||
Component.prototype.update = function() { | ||
this.nodeTree.compare(this.$scope); | ||
if(this.nodeTree instanceof global.Base.CompNode) | ||
this.nodeTree.compare(this); | ||
}; | ||
@@ -374,3 +394,3 @@ | ||
Controller.prototype.generateComponent = function(el, inputs) { | ||
Controller.prototype.generateComponent = function(el, parent, inputs) { | ||
// Creating new scope object | ||
@@ -380,4 +400,9 @@ var $scope = {}; | ||
// Generating new component | ||
var comp = new global.Base.Component(el, $scope); | ||
var comp = new global.Base.Component(el, parent, $scope); | ||
// Keeping the element's content as original HTML | ||
if(el.innerHTML.length > 0) { | ||
comp.subView = new global.Base.View('content-outlet', null, el.innerHTML); | ||
} | ||
// If inputs assigning them to comp | ||
@@ -396,3 +421,3 @@ if(typeof inputs === 'object') | ||
// Eventually setting the view for the component | ||
comp.setView(this.view.generate($scope)); | ||
comp.setView(this.view.generate(comp)); | ||
@@ -429,8 +454,9 @@ return comp; | ||
this.justModify = !!options.justModify; | ||
this.useComponentInGetter = !!options.useComponentInGetter; | ||
}; | ||
Injectable.prototype.getter = function(statement, $scope) { | ||
Injectable.prototype.getter = function(statement, comp) { | ||
var result; | ||
try { | ||
with($scope) { result = eval(statement); } | ||
with(comp.$scope) { result = eval(statement); } | ||
} catch(err) { | ||
@@ -515,7 +541,93 @@ console.error(TAG, this.name + ':', "Couldn't evaluate '" + statement + "'."); | ||
var TAG = "[Route]"; | ||
var Route = function(options) { | ||
if(options.hasOwnProperty('path')) | ||
this.path = options.path.split('/'); | ||
else | ||
throw { message: TAG + " Route must have a path." }; | ||
if(options.hasOwnProperty('controller')) { | ||
this.controller = options.controller; | ||
} else if(options.hasOwnProperty('redirect')) | ||
this.redirect = options.redirect; | ||
else | ||
throw { message: TAG + " Route must have a controller." }; | ||
if(Array.isArray(options.children)) | ||
this.children = options.children.map(function(child) { | ||
return new Route(child); | ||
}); | ||
}; | ||
Route.prototype.checkUrl = function(urlParts, matchesArr) { | ||
var matchingParts = 0; | ||
if(this.path.length > urlParts.length) | ||
return false; | ||
for(var i = 0; i < this.path.length; i++) { | ||
if(this.path[i] === urlParts[i]) | ||
matchingParts++; | ||
} | ||
if(this.path.length === matchingParts) { | ||
if(this.redirect) { | ||
return { redirect: this.redirect }; | ||
} | ||
if(!Array.isArray(matchesArr)) | ||
matchesArr = []; | ||
matchesArr.push(this.controller); | ||
if(this.path.length < urlParts.length) { | ||
if(!Array.isArray(this.children)) | ||
return false; | ||
var wasFound = false; | ||
urlParts.splice(0, matchingParts); | ||
for(i = 0; i < this.children.length; i++) { | ||
if(this.children[i].checkUrl(urlParts, matchesArr)) { | ||
wasFound = matchesArr; | ||
break; | ||
} | ||
} | ||
return wasFound | ||
} else if(Array.isArray(this.children)) { | ||
var child = this.children.filter(function(c) { | ||
return c.path.length === 1 && c.path[0] === ''; | ||
}); | ||
while(Array.isArray(child) && child.length > 0) { | ||
child = child[0]; | ||
matchesArr.push(child.controller); | ||
if(Array.isArray(child.children)) | ||
child = child.children.filter(function(c) { | ||
return c.path.length === 0; | ||
}); | ||
} | ||
} | ||
return { | ||
controllers: matchesArr | ||
}; | ||
} | ||
return false; | ||
}; | ||
global.Base = global.Base || {}; | ||
global.Base.Route = Route; | ||
})(Function('return this')()); | ||
(function(global) { | ||
var viewOptions = global.Config.viewOptions; | ||
var View = function(name, relPath) { | ||
var View = function(name, relPath, template) { | ||
this.name = name; | ||
this.loadTemplate(relPath); | ||
if(!template) | ||
this.loadTemplate(relPath); | ||
else { | ||
this.templateSrc = template; | ||
} | ||
this.buildNodeTree(); | ||
@@ -563,6 +675,6 @@ }; | ||
View.prototype.generate = function($scope) { | ||
View.prototype.generate = function(comp) { | ||
var componentTree = new global.Base.CompNode(this.nodeTree); | ||
for(var c = 0; c < this.nodeTree.children.length; c++) { | ||
componentTree.appendChild(this.nodeTree.children[c].generate($scope, componentTree)); | ||
componentTree.appendChild(this.nodeTree.children[c].generate(comp)); | ||
} | ||
@@ -610,4 +722,5 @@ return componentTree; | ||
ViewNode.prototype.generate = function($scope) { | ||
var compNode = new global.Base.CompNode(this); | ||
ViewNode.prototype.generate = function(comp) { | ||
var compNode = new global.Base.CompNode(this), | ||
$scope = comp.$scope; | ||
@@ -622,3 +735,3 @@ if(Array.isArray(this.directives)) { | ||
// Get value from injectable getter | ||
var value = directive.injectable.getter(directive.statement, $scope); | ||
var value = directive.injectable.getter(directive.statement, comp); | ||
@@ -653,7 +766,7 @@ // Running modifier on created compNode with getter value | ||
$scope[compNode.iterator.varName] = arr[i]; | ||
childNode = this.generate($scope); | ||
childNode = this.generate(comp); | ||
childNode.iteratorValue = arr[i]; | ||
if(childNode.self) childCount++; | ||
compNode.appendChild(childNode); | ||
if(childNode.isComponent()) childNode.bootstrap(); | ||
if(childNode.isComponent()) childNode.bootstrap(comp); | ||
} | ||
@@ -675,6 +788,10 @@ | ||
for(var i = 0; i < viewNode.children.length; i++) { | ||
generated = viewNode.children[i].generate($scope, node); | ||
generated = viewNode.children[i].generate(comp); | ||
node.appendChild(generated); | ||
if(generated.isComponent()) generated.bootstrap(); | ||
if(generated.replaceSelfWith) { | ||
generated.self.parentNode.replaceChild(generated.replaceSelfWith.self, generated.self); | ||
delete generated.replaceSelfWith; | ||
} | ||
if(generated.isComponent()) generated.bootstrap(comp); | ||
} | ||
@@ -690,7 +807,7 @@ } | ||
var Bootstrap = function(el, inputs) { | ||
var Bootstrap = function(el, parent, inputs) { | ||
if(el.nodeType === 1) { | ||
var controller = getControllerFromEl(el); | ||
if(controller instanceof global.Base.Controller) { | ||
return controller.generateComponent(el, inputs); | ||
return controller.generateComponent(el, parent, inputs); | ||
} else | ||
@@ -717,6 +834,215 @@ throw { message: "Controller " + el.getAttribute('controller') + " not found." }; | ||
var Controllers = {}; | ||
var Injectables = {}; | ||
var Models = {}; | ||
var TAG = "[Router]", routerInstance; | ||
var Router = function(routes) { | ||
// Singleton | ||
if(routerInstance) | ||
return routerInstance; | ||
if(Array.isArray(routes)) { | ||
// Initializing onhashchange: | ||
window.onhashchange = function() { | ||
if(!this.navigating) { | ||
this.navigateTo(location.hash); | ||
} | ||
this.navigating = false; | ||
}.bind(this); | ||
// Initializing Router | ||
try { | ||
this.routes = routes.map(function(r) { | ||
return new global.Base.Route(r); | ||
}); | ||
} catch(err) { | ||
throw err; | ||
} | ||
routerInstance = this; | ||
this.navigateTo(location.hash); | ||
} else | ||
throw { message: TAG + " 'routes' should be an array of routes." }; | ||
}; | ||
Router.prototype.navigateTo = function(url) { | ||
// First validate url | ||
if(url[0] === '#') { | ||
if(url[1] !== '/') { | ||
url = url.slice(1, url.length); | ||
} else | ||
url = url.slice(2, url.length); | ||
} | ||
if(url !== this.currentPath) { | ||
this.currentPath = url; | ||
var resultsObj = this.parseUrl(url); | ||
if(resultsObj) { | ||
var results = resultsObj.results; | ||
if(results.redirect) { | ||
this.navigateTo(results.redirect); | ||
} else { | ||
if(typeof resultsObj.params === 'string' && resultsObj.params.length > 0) { | ||
resultsObj.params = global.Utils.String.toDictionary(resultsObj.params, '&', '='); | ||
} | ||
history.pushState(null, '', '#/' + url); | ||
this.stateChange(resultsObj) | ||
} | ||
} else | ||
console.error("UNKNOWN ROUTE " + url); | ||
} | ||
}; | ||
Router.prototype.parseUrl = function(url) { | ||
var urlParts = url.split('?'), | ||
paramsString = urlParts[1]; | ||
// First handling the URL | ||
urlParts = urlParts[0].split('/').filter(function(p) { | ||
return p !== '#'; | ||
}); | ||
var results; | ||
for(var r = 0; r < this.routes.length && !results; r++) { | ||
results = this.routes[r].checkUrl(urlParts); | ||
} | ||
if(results) { | ||
return { | ||
results: results, | ||
params: paramsString | ||
} | ||
} else | ||
return false; | ||
}; | ||
Router.prototype.stateChange = function(urlParseResults) { | ||
var results = urlParseResults.results; | ||
if(!this.state) | ||
this.state = { | ||
controllers: results.controllers, | ||
params: urlParseResults.params, | ||
nextController: results.controllers[0] | ||
}; | ||
else { | ||
var affectedCompNode; | ||
for(var i = 0; i < results.controllers.length; i++) { | ||
if(results.controllers[i] !== this.state.controllers[i]) { | ||
for(var j = i; j < results.controllers.length; j++) { | ||
this.state.controllers[j] = results.controllers[j]; | ||
} | ||
if(j < this.state.controllers.length) | ||
this.state.controllers.splice(j, this.state.controllers.length); | ||
this.state.nextController = results.controllers[i]; | ||
affectedCompNode = this.state.compNodes[i]; | ||
break; | ||
} | ||
} | ||
// Params check | ||
if(typeof urlParseResults.params === 'object') { | ||
for(var param in urlParseResults.params) if(urlParseResults.params.hasOwnProperty(param)) | ||
this.updateParam(param, urlParseResults.params[param]); | ||
for(param in this.state.params) if(this.state.params.hasOwnProperty(param)) | ||
if(!urlParseResults.params[param]) | ||
this.updateParam(param); | ||
} else { | ||
var stateParams = this.state.params; | ||
if(typeof stateParams === 'object') | ||
for(param in stateParams) if(stateParams.hasOwnProperty(param)) | ||
this.updateParam(param); | ||
} | ||
if(affectedCompNode instanceof global.Base.CompNode) { | ||
var comp = affectedCompNode.comp, | ||
newCompNode = affectedCompNode.viewNode.generate(comp); | ||
affectedCompNode.parent.replaceChild(newCompNode, affectedCompNode); | ||
newCompNode.bootstrap(comp.parent); | ||
} | ||
} | ||
}; | ||
Router.prototype.nextController = function(compNode) { | ||
if(this.state && this.state.nextController) { | ||
// Saving nextController and clearing it's data | ||
var nextController = this.state.nextController; | ||
this.state.nextController = undefined; | ||
// Searching for it's place in the stack | ||
for(var i = 0; i < this.state.controllers.length; i++) { | ||
if(nextController === this.state.controllers[i]) { | ||
// Creating an array to save compNodes accordingly | ||
if(!Array.isArray(this.state.compNodes)) this.state.compNodes = []; | ||
// Assigning next controller on the stack to nextController | ||
this.state.nextController = this.state.controllers[i+1]; | ||
// Placing the compNode in it's correct place | ||
this.state.compNodes[i] = compNode; | ||
break; | ||
} | ||
} | ||
return nextController; | ||
} else | ||
console.error(TAG, "Failed to load next controller, end of list."); | ||
}; | ||
Router.prototype.updateParam = function(key, value) { | ||
var params = this.params(), changes = 0; | ||
if(params[key] !== value) { | ||
if(!value || value.length === 0) | ||
delete params[key]; | ||
else | ||
params[key] = value; | ||
changes++; | ||
// emit to subscriptions | ||
if(this.paramSubscriptions) { | ||
var subsObservable = this.paramSubscriptions[key]; | ||
if(subsObservable instanceof global.Utils.Observable) { | ||
subsObservable.next(value); | ||
} | ||
} | ||
} | ||
if(changes > 0) { | ||
this.navigating = true; | ||
var currUrl = location.hash; | ||
currUrl = currUrl.split('?')[0] + '?'; | ||
for(var param in params) if(params.hasOwnProperty(param)) { | ||
currUrl += param + '=' + params[param] + '&' | ||
} | ||
location.hash = currUrl.substr(0, currUrl.length - 1); | ||
this.currentPath = location.hash.substr(2, location.hash.length); | ||
} | ||
if(this.state) this.state.params = params; | ||
}; | ||
Router.prototype.subscribeToParam = function(param, listener) { | ||
if(typeof this.paramSubscriptions !== 'object') | ||
this.paramSubscriptions = {}; | ||
var subs = this.paramSubscriptions; | ||
if(!(subs[param] instanceof global.Utils.Observable)) | ||
subs[param] = new global.Utils.Observable(); | ||
var subscription = subs[param].subscribe(listener); | ||
if(this.state && this.state.params) { | ||
listener(this.state.params[param]); | ||
} | ||
return subscription; | ||
}; | ||
Router.prototype.params = function() { | ||
return (this.state && typeof this.state.params === 'object') ? | ||
this.state.params : | ||
{}; | ||
}; | ||
global.Core = global.Core || {}; | ||
global.Core.Router = Router; | ||
})(Function('return this')()); | ||
(function(global) { | ||
var Controllers = {}, | ||
Injectables = {}, | ||
Models = {}, | ||
routerInstance; | ||
global.App = { | ||
@@ -738,3 +1064,4 @@ // Getters | ||
Injectable: generateInjectable, | ||
Model: createModel | ||
Model: createModel, | ||
Router: getRouter | ||
}; | ||
@@ -789,2 +1116,9 @@ | ||
function getRouter(routes) { | ||
if(!routerInstance) | ||
routerInstance = new global.Core.Router(routes); | ||
return routerInstance; | ||
} | ||
})(Function('return this')()); | ||
@@ -798,7 +1132,7 @@ (function(global) { | ||
// Functions | ||
getter: function(statement, $scope) { | ||
getter: function(statement, comp) { | ||
var classes = global.Utils.String.toDictionary(statement), | ||
value; | ||
try { | ||
with($scope) { | ||
with(comp.$scope) { | ||
for(var className in classes) if(classes.hasOwnProperty(className)) { | ||
@@ -827,6 +1161,6 @@ value = eval(classes[className]); | ||
global.App.Injectable('bind-if', { | ||
getter: function(statement, $scope) { | ||
getter: function(statement, comp) { | ||
var result; | ||
try { | ||
with($scope) { result = eval(statement); } | ||
with(comp.$scope) { result = eval(statement); } | ||
} catch(err) { | ||
@@ -847,4 +1181,19 @@ throw this.name + ": Couldn't evaluate '" + statement + "'."; | ||
global.App.Injectable('content-outlet', { | ||
// Functions | ||
getter: function(statement, comp) { | ||
return comp; | ||
}, | ||
modifier: function(compNode, comp) { | ||
if(comp.subView) { | ||
compNode.replaceSelfWith = comp.subView.generate(comp.parent); | ||
} | ||
} | ||
}); | ||
})(Function('return this')()); | ||
(function(global) { | ||
global.App.Injectable('bind-events', { | ||
getter: function(statement, $scope) { | ||
getter: function(statement, comp) { | ||
var events = global.Utils.String.toDictionary(statement), | ||
@@ -856,19 +1205,30 @@ matches, funcName, variables; | ||
matches = events[event].match(regEx); | ||
if(!Array.isArray(matches) || matches.length < 2) | ||
throw (this.name + ": Invalid statement, expecting: [event: func()]"); | ||
funcName = matches[1]; | ||
variables = matches[2].split(','); | ||
events[event] = function(funcName, variables) { | ||
for(var i = 0; i < variables.length; i++) { | ||
try { | ||
with(comp.$scope) { | ||
variables[i] = eval(variables[i]); | ||
} | ||
} catch(err) { | ||
throw (this.name + ": " + err.message) | ||
} | ||
} | ||
events[event] = function(funcName, variables, el) { | ||
var func; | ||
try { | ||
with($scope) { | ||
with(comp.$scope) { | ||
func = eval(funcName); | ||
} | ||
var values = []; | ||
for(var i = 0; i < variables.length; i++) { | ||
values[i] = $scope[variables[i]]; | ||
} | ||
func.apply(undefined, values); | ||
} catch(err) { | ||
throw (this.name + ": " + err.message) | ||
} | ||
if(typeof func === 'function') | ||
func.apply(el, variables); | ||
}.bind(this, funcName, variables); | ||
@@ -883,3 +1243,3 @@ } | ||
try { | ||
callback(); | ||
callback(e.target); | ||
} catch(err) { | ||
@@ -900,7 +1260,7 @@ console.error('[Injectable]', err); | ||
global.App.Injectable('input', { | ||
getter: function(statement, $scope) { | ||
getter: function(statement, comp) { | ||
var inputs = global.Utils.String.toDictionary(statement); | ||
try { | ||
for(var input in inputs) if(inputs.hasOwnProperty(input)) { | ||
with($scope) { | ||
with(comp.$scope) { | ||
inputs[input] = eval(inputs[input]); | ||
@@ -933,3 +1293,3 @@ } | ||
global.App.Injectable('bind-for', { | ||
getter: function(statement, $scope) { | ||
getter: function(statement, comp) { | ||
var words = statement.split(' '), | ||
@@ -940,3 +1300,3 @@ result = {}; | ||
try { | ||
with($scope) { | ||
with(comp.$scope) { | ||
result.array = eval(words[w+1]); | ||
@@ -965,2 +1325,22 @@ } | ||
var TAG = "[Router-Outlet]"; | ||
global.App.Injectable('router-outlet', { | ||
getter: function(statement, comp) { | ||
return true; | ||
}, | ||
modifier: function(compNode, value) { | ||
var Router = global.App.Router(), | ||
controllerName = Router.nextController(compNode), | ||
controller = global.App.getController(controllerName); | ||
if(controller instanceof global.Base.Controller) { | ||
compNode.self.setAttribute('controller', controllerName); | ||
} | ||
} | ||
}); | ||
})(Function('return this')()); | ||
(function(global) { | ||
global.App.Injectable('bind-value', { | ||
@@ -967,0 +1347,0 @@ // Options |
@@ -1,1 +0,1 @@ | ||
Function("return this")().Config={viewOptions:{templatesFolder:"app"}},function(e){var t={get:function(e,t,n){var r=new XMLHttpRequest;if("object"==typeof t.headers)for(var i in t.headers)t.headers.hasOwnProperty(i)&&r.setRequestHeader(i,t.headers[i]);if("object"==typeof t.params){var s="?";for(var o in t.params)t.params.hasOwnProperty(o)&&(s+=o+"="+t.params[o]+"&");e+=s}r.open("GET",e,!0),r.onreadystatechange=function(){200===r.status&&4===r.readyState&&n(JSON.parse(r.responseText))},r.send()},post:function(e,t,n){var r=new XMLHttpRequest;if(r.open("POST",e,!0),"object"==typeof t.headers)for(var i in t.headers)t.headers.hasOwnProperty(i)&&r.setRequestHeader(i,t.headers[i]);"object"==typeof t.body&&(t=t.body),r.onreadystatechange=function(){200===r.status&&4===r.readyState&&n(JSON.parse(r.responseText))},r.send(JSON.stringify(t))}};e.Utils=e.Utils||{},e.Utils.Http=t}(Function("return this")()),function(e){var t={updateObject:function(e,n,r){var i=0;if("object"==typeof e&&"object"==typeof n)for(var s in n)if(n.hasOwnProperty(s)&&!function(e){if(Array.isArray(r)){for(var t=0;t<r.length;t++)if(e===r[t])return!0}else if(e===r)return!0;return!1}(s))switch(typeof n[s]){case"object":i+=t.updateObject(e[s],n[s]);break;default:e[s]!==n[s]&&(e[s]=n[s],i++)}return i}};e.Utils=e.Utils||{},e.Utils.Object=t}(Function("return this")()),function(e){var t=function(){this.listeners=[],this.lastMessage=void 0};t.prototype={subscribe:function(e){if("function"==typeof e)return this.listeners.push(e),{unsubscribe:this.unsubscribe.bind(this,e)};console.error(e,"is not a function. Cannot subscribe to Observable.")},unsubscribe:function(e){for(var t=this.listeners.length-1;t>=0;t--)this.listeners[t]===e&&this.listeners.splice(t,1)},next:function(e){this.listeners.forEach(function(t){t(e)}),this.lastMessage=e}},e.Utils=e.Utils||{},e.Utils.Observable=t}(Function("return this")()),function(e){e.Utils=e.Utils||{},e.Utils.String={toKeyValueArray:function(e,t){"string"!=typeof t&&(t=",");var n,r=[];return e.split(t).forEach(function(e){n=/([\w-]+): *(.+)/g.exec(e.trim()),r.push({key:n[1],value:n[2]})}),r},toDictionary:function(e,t){"string"!=typeof t&&(t=",");var n,r={};return e.split(t).forEach(function(e){n=/([\w-]+): *(.+)/g.exec(e.trim()),r[n[1]]=n[2]}),r}}}(Function("return this")()),function(e){var t=function(e,t){this.viewNode=e,this.self=e.self.cloneNode(!1),Array.isArray(t)&&(this.values=t),this.children=[]};t.prototype.compare=function(n){var r=!1;if(Array.isArray(this.viewNode.directives))for(var i,s,o=this.viewNode.directives,a=0,l=0;l<o.length;l++)if(o[l])if(i=o[l].injectable,s=i.getter(o[l].statement,n),i.compare(this.values[l-a],s)){if(s&&Array.isArray(s.array))break}else{if(this.values[l-a]=s,!i.justModify||!this.self){r=!0;break}i.modifier(this,s)}else a++;if(r){var c=this.viewNode.generate(n);this.iteratorValue&&(c.iteratorValue=this.iteratorValue),this.parent.replaceChild(c,this),c.isComponent()&&(c.comp=e.Core.Bootstrap(c.self,c.inputs),c.self=c.comp.nodeTree.self)}else if(this.multipleNodes){var u,h=this.viewNode,f=this.iterator,p=n[f.varName],d=h.directives[l],v=l;for(h.directives[v]=void 0,l=0;l<f.array.length;l++)n[f.varName]=f.array[l],this.children[l]instanceof t?(this.children[l].compare(n),this.children[l].iteratorValue=f.array[l]):((u=h.generate(n)).iteratorValue=f.array[l],this.appendChild(u));n[f.varName]=p,h.directives[v]=d}else this.children.forEach(function(e){e.compare(n)})},t.prototype.appendChild=function(e){this.children.push(e),e.parent=this,e.self&&this.self.appendChild(e.self)},t.prototype.replaceChild=function(e,t){if(e.parent=t.parent,e.self&&t.self)this.self.replaceChild(e.self,t.self),this.children.splice(this.children.indexOf(t),1,e);else if(e.self&&!t.self){var n=this.children.indexOf(t);if(n>=0){this.children.splice(n,1,e);for(var r;!r&&n<this.children.length-1;)this.children[++n].self&&(r=this.children[n].self);r?r.parentNode.insertBefore(e.self,r):this.self.appendChild(e.self)}else console.error("CompNode: replaceChild failed, 2nd parameter is not a child of this node.")}else!e.self&&t.self&&this.removeChild(t)},t.prototype.removeChild=function(e){this.self.removeChild(e.self),e.self=void 0,e.children.splice(0,e.children.length)},t.prototype.isComponent=function(){return this.self&&1===this.self.nodeType&&this.viewNode.controller&&!this.iterator},t.prototype.bootstrap=function(){this.comp=e.Core.Bootstrap(this.self,this.inputs),this.self=this.comp.nodeTree.self},e.Base=e.Base||{},e.Base.CompNode=t}(Function("return this")()),function(e){var t=function(e,t){this.el=e,this.$scope=t};t.prototype.setView=function(e){this.el.parentNode.replaceChild(e.self,this.el),this.nodeTree=e,this.el=e.self},t.prototype.update=function(){this.nodeTree.compare(this.$scope)},t.prototype.getInput=function(e){if(this.inputs&&this.inputs.hasOwnProperty(e))return this.inputs[e];throw{message:"Input "+e+" doesn't exist."}},e.Base=e.Base||{},e.Base.Component=t}(Function("return this")()),function(e){var t=function(e,t,n){this.name=e,this.view=t,this.constructor=n};t.prototype.generateComponent=function(t,n){var r={},i=new e.Base.Component(t,r);return"object"==typeof n&&(i.inputs=n),r.getInput=function(e){r[e]=this.getInput(e)}.bind(i),this.constructor.call(this,r,i.update.bind(i)),i.setView(this.view.generate(r)),i},e.Base=e.Base||{},e.Base.Controller=t}(Function("return this")()),function(global){var TAG="[Injectable]",Injectable=function(e,t){this.name=e;try{this.modifier=t.modifier.bind(this)}catch(e){console.error(TAG,this.name+": No modifier set.")}"function"==typeof t.getter&&(this.getter=t.getter.bind(this)),"function"==typeof t.compare&&(this.compare=t.compare.bind(this)),this.keepAttribute=!!t.keepAttribute,this.justModify=!!t.justModify};Injectable.prototype.getter=function(statement,$scope){var result;try{with($scope)result=eval(statement)}catch(e){console.error(TAG,this.name+":","Couldn't evaluate '"+statement+"'.")}return result},Injectable.prototype.compare=function(e,t){if(e===t)return!0},global.Base=global.Base||{},global.Base.Injectable=Injectable}(Function("return this")()),function(e){var t=function(e,t){this.name=e,this.initFunc=t,this.events={},this.init()};t.prototype.init=function(){if("function"!=typeof this.initFunc)throw{message:this.name+": Couldn't initialize the model (initFunc err)"};this.initFunc(function(e){this.setData(e)}.bind(this))},t.prototype.setData=function(e,t){this.data=e,this.emit(t||"setData",e)},t.prototype.emit=function(){for(var e,t=[],n=0;n<arguments.length;n++)0===n?e=arguments[n]:t.push(arguments[n]);if(Array.isArray(this.events[e]))for(var r=0;r<this.events[e].length;r++)this.events[e][r].apply(void 0,t)},t.prototype.subscribe=function(e,t){return this.events[e]||(this.events[e]=[]),this.events[e].push(t),{unsubscribe:function(e){this.events.splice(this.events.indexOf(e),1)}.bind(this,t)}},e.Base=e.Base||{},e.Base.Model=t}(Function("return this")()),function(e){var t=e.Config.viewOptions,n=function(e,t){this.name=e,this.loadTemplate(t),this.buildNodeTree()};n.prototype.loadTemplate=function(e){var n=t.templatesFolder+"/"+e+this.name+".html";n=n.replace(/\/\//g,"/"),this.templateSrc=function(e){var t=new XMLHttpRequest;return t.open("GET",e,!1),t.send(),t.responseText}(n)},n.prototype.buildNodeTree=function(){function t(n){for(var r,i=new e.Base.ViewNode(n),s=0;s<n.childNodes.length;s++)(r=t(n.childNodes[s])).parent=i,i.children.push(r);return i}var n=document.createElement("temp");n.innerHTML=this.templateSrc;for(var r=new e.Base.ViewNode(document.createElement(this.name)),i=0;i<n.childNodes.length;i++)r.children.push(t(n.childNodes[i]));this.nodeTree=r},n.prototype.generate=function(t){for(var n=new e.Base.CompNode(this.nodeTree),r=0;r<this.nodeTree.children.length;r++)n.appendChild(this.nodeTree.children[r].generate(t,n));return n},e.Base=e.Base||{},e.Base.View=n}(Function("return this")()),function(e){var t=function(e){this.self=e,this.children=[],this.parseNode()};t.prototype.parseNode=function(){var t=this.self.attributes;if(t&&t.length>0)for(var n=0;n<t.length;n++)if("controller"===t[n].name)this.controller=t[n].value;else{var r=e.App.getInjectable(t[n].name);r instanceof e.Base.Injectable&&(Array.isArray(this.directives)||(this.directives=[]),this.directives.push({injectable:r,statement:t[n].value}),r.keepAttribute||(this.self.removeAttribute(t[n].name),n--))}},t.prototype.generate=function(t){var n=new e.Base.CompNode(this);if(Array.isArray(this.directives)){var r,i;for(n.values=[],i=0;i<this.directives.length&&n.self;i++)if(this.directives[i]){var s=(r=this.directives[i]).injectable.getter(r.statement,t);if(r.injectable.modifier(n,s),n.values.push(s),n.multipleNodes)break}}if(n.self)if(n.multipleNodes){var o,a=n.iterator.array,l=t[n.iterator.varName],c=this.directives[i],u=i;this.directives[i]=void 0;for(i=0;i<a.length;i++)t[n.iterator.varName]=a[i],(o=this.generate(t)).iteratorValue=a[i],o.self&&0,n.appendChild(o),o.isComponent()&&o.bootstrap();t[n.iterator.varName]=l,this.directives[u]=c}else!function(e,n){for(var r,i=0;i<e.children.length;i++)r=e.children[i].generate(t,n),n.appendChild(r),r.isComponent()&&r.bootstrap()}(this,n);return n},e.Base=e.Base||{},e.Base.ViewNode=t}(Function("return this")()),function(e){function t(t){var n=t.getAttribute("controller");if("string"==typeof n){var r=e.App.getController(n);if(r instanceof e.Base.Controller)return r}}e.Core=e.Core||{},e.Core.Bootstrap=function(n,r){if(1===n.nodeType){var i=t(n);if(i instanceof e.Base.Controller)return i.generateComponent(n,r);throw{message:"Controller "+n.getAttribute("controller")+" not found."}}throw{message:"Cannot bootstrap a non-element object."}}}(Function("return this")()),function(e){var t={},n={},r={};e.App={getController:function(e){return t[e]},getInjectable:function(e){return n[e]},getModel:function(e){return r[e]},Bootstrap:function(t){var n="[Bootstrap]",r=document.querySelector('*[controller="'+t+'"]');if(r&&1===r.nodeType){try{var i=e.Core.Bootstrap(r)}catch(e){console.error(n,e.message)}return i}console.error(n,"Could not find placeholder for '"+t+"'.")},Controller:function(n,r,i){try{var s=new e.Base.View(n,r);t[n]=new e.Base.Controller(n,s,i)}catch(e){console.error("[Controller]",e.message)}},Injectable:function(t,r){try{n[t]=new e.Base.Injectable(t,r)}catch(e){console.error("[Injectable]",e.message)}},Model:function(t,n){try{r[t]=new e.Base.Model(t,n)}catch(e){console.error("[Model]",e.message)}}}}(Function("return this")()),function(global){global.App.Injectable("bind-class",{justModify:!0,getter:function(statement,$scope){var classes=global.Utils.String.toDictionary(statement),value;try{with($scope)for(var className in classes)classes.hasOwnProperty(className)&&(value=eval(classes[className]),classes[className]=!!value)}catch(e){throw{message:this.name+": "+e.message}}return classes},modifier:function(e,t){for(var n in t)t.hasOwnProperty(n)&&(t[n]?e.self.classList.add(n):e.self.classList.remove(n))}})}(Function("return this")()),function(global){global.App.Injectable("bind-if",{getter:function(statement,$scope){var result;try{with($scope)result=eval(statement)}catch(e){throw this.name+": Couldn't evaluate '"+statement+"'."}return!!result},modifier:function(e,t){t||(e.self=void 0)}})}(Function("return this")()),function(global){global.App.Injectable("bind-events",{getter:function(statement,$scope){var events=global.Utils.String.toDictionary(statement),matches,funcName,variables;for(var event in events)if(events.hasOwnProperty(event)){var regEx=new RegExp("^(.+)\\((.*)\\)$");matches=events[event].match(regEx),funcName=matches[1],variables=matches[2].split(","),events[event]=function(funcName,variables){var func;try{with($scope)func=eval(funcName);for(var values=[],i=0;i<variables.length;i++)values[i]=$scope[variables[i]];func.apply(void 0,values)}catch(e){throw this.name+": "+e.message}}.bind(this,funcName,variables)}return events},modifier:function(e,t){for(var n in t)t.hasOwnProperty(n)&&e.self.addEventListener(n,function(e,t){t&&t.preventDefault&&t.preventDefault();try{e()}catch(e){console.error("[Injectable]",e)}}.bind(this,t[n]))},compare:function(e,t){return!0}})}(Function("return this")()),function(global){global.App.Injectable("input",{getter:function(statement,$scope){var inputs=global.Utils.String.toDictionary(statement);try{for(var input in inputs)if(inputs.hasOwnProperty(input))with($scope)inputs[input]=eval(inputs[input])}catch(e){throw{message:this.name+": "+e.message}}return inputs},modifier:function(e,t){e.inputs=t},compare:function(e,t){var n=!0;for(var r in t)if(t.hasOwnProperty(r)&&t[r]!==e[r]){n=!1;break}return n}})}(Function("return this")()),function(global){global.App.Injectable("bind-for",{getter:function(statement,$scope){for(var words=statement.split(" "),result={},w=0;w<words.length;w++)if("in"===words[w]&&w>0&&w<words.length-1){try{with($scope)result.array=eval(words[w+1])}catch(e){throw e}result.varName=words[w-1]}return result},compare:function(e,t){return e.array===t.array},modifier:function(e,t){e.self=document.createElement("iterator"),e.multipleNodes=!0,e.iterator=t}})}(Function("return this")()),Function("return this")().App.Injectable("bind-value",{justModify:!0,modifier:function(e,t){e.self.innerHTML=t}}); | ||
Function("return this")().Config={viewOptions:{templatesFolder:"app"}},function(t){var e={get:function(t,e,r){var n=new XMLHttpRequest;if("object"==typeof e.headers)for(var i in e.headers)e.headers.hasOwnProperty(i)&&n.setRequestHeader(i,e.headers[i]);if("object"==typeof e.params){var s="?";for(var o in e.params)e.params.hasOwnProperty(o)&&(s+=o+"="+e.params[o]+"&");t+=s}n.open("GET",t,!0),n.onreadystatechange=function(){200===n.status&&4===n.readyState&&r(JSON.parse(n.responseText))},n.send()},post:function(t,e,r){var n=new XMLHttpRequest;if(n.open("POST",t,!0),"object"==typeof e.headers)for(var i in e.headers)e.headers.hasOwnProperty(i)&&n.setRequestHeader(i,e.headers[i]);"object"==typeof e.body&&(e=e.body),n.onreadystatechange=function(){200===n.status&&4===n.readyState&&r(JSON.parse(n.responseText))},n.send(JSON.stringify(e))}};t.Utils=t.Utils||{},t.Utils.Http=e}(Function("return this")()),function(t){var e={updateObject:function(t,r,n){if(t&&r){var i=0;if("object"==typeof t&&"object"==typeof r)for(var s in r)if(r.hasOwnProperty(s)&&!function(t){if(Array.isArray(n)){for(var e=0;e<n.length;e++)if(t===n[e])return!0}else if(t===n)return!0;return!1}(s))switch(typeof r[s]){case"object":Array.isArray(r[s])?console.warning('[Utils:Object] "updateObject" does not support merging arrays.'):i+=e.updateObject(t[s],r[s]);break;default:t[s]!==r[s]&&(t[s]=r[s],i++)}}return i}};t.Utils=t.Utils||{},t.Utils.Object=e}(Function("return this")()),function(t){var e=function(){this.listeners=[],this.lastMessage=void 0};e.prototype={subscribe:function(t){if("function"==typeof t)return this.listeners.push(t),{unsubscribe:this.unsubscribe.bind(this,t)};console.error(t,"is not a function. Cannot subscribe to Observable.")},unsubscribe:function(t){for(var e=this.listeners.length-1;e>=0;e--)this.listeners[e]===t&&this.listeners.splice(e,1)},next:function(t){this.listeners.forEach(function(e){e(t)}),this.lastMessage=t}},t.Utils=t.Utils||{},t.Utils.Observable=e}(Function("return this")()),function(t){var e={toKeyValueArray:function(t,e){"string"!=typeof e&&(e=",");var r,n=[];return t.split(e).forEach(function(t){r=/([\w-]+): *(.+)/g.exec(t.trim()),n.push({key:r[1],value:r[2]})}),n},toDictionary:function(t,e,r){"string"!=typeof e&&(e=","),"string"!=typeof r&&(r=":");var n,i={};return t.split(e).forEach(function(t){var e=new RegExp("([\\w-]+)"+r+" *(.+)");n=e.exec(t.trim()),Array.isArray(n)&&3===n.length&&(i[n[1]]=n[2])}),i}};t.Utils=t.Utils||{},t.Utils.String=e}(Function("return this")()),function(t){var e=function(t,e){this.viewNode=t,this.self=t.self.cloneNode(!1),Array.isArray(e)&&(this.values=e),this.children=[]};e.prototype.compare=function(t){var r=!1,n=t.$scope;if(Array.isArray(this.viewNode.directives))for(var i,s,o=this.viewNode.directives,a=0,l=0;l<o.length;l++)if(o[l])if(i=o[l].injectable,s=i.getter(o[l].statement,t),i.compare(this.values[l-a],s)){if(s&&Array.isArray(s.array))break}else{if(this.values[l-a]=s,!i.justModify||!this.self){r=!0;break}i.modifier(this,s)}else a++;if(r){var c=this.viewNode.generate(t);this.iteratorValue&&(c.iteratorValue=this.iteratorValue),this.parent.replaceChild(c,this),c.isComponent()&&c.bootstrap(t)}else if(this.multipleNodes){var h,u=this.viewNode,p=this.iterator,f=n[p.varName],d=u.directives[l],m=l;for(u.directives[m]=void 0,l=0;l<p.array.length;l++)n[p.varName]=p.array[l],this.children[l]instanceof e?(this.children[l].compare(t),this.children[l].iteratorValue=p.array[l]):((h=u.generate(t)).iteratorValue=p.array[l],this.appendChild(h));n[p.varName]=f,u.directives[m]=d}else this.children.forEach(function(e){e.compare(t)})},e.prototype.appendChild=function(t){this.children.push(t),t.parent=this,t.self&&this.self.appendChild(t.self)},e.prototype.replaceChild=function(t,e){if(t.parent=e.parent,t.self&&e.self)this.self.replaceChild(t.self,e.self),this.children.splice(this.children.indexOf(e),1,t);else if(t.self&&!e.self){var r=this.children.indexOf(e);if(r>=0){this.children.splice(r,1,t);for(var n;!n&&r<this.children.length-1;)this.children[++r].self&&(n=this.children[r].self);n?n.parentNode.insertBefore(t.self,n):this.self.appendChild(t.self)}else console.error("CompNode: replaceChild failed, 2nd parameter is not a child of this node.")}else!t.self&&e.self&&this.removeChild(e)},e.prototype.removeChild=function(t){this.self.removeChild(t.self),t.self=void 0,t.children.splice(0,t.children.length)},e.prototype.isComponent=function(){return this.self&&1===this.self.nodeType&&(this.viewNode.controller||"string"==typeof this.self.getAttribute("controller"))&&!this.iterator},e.prototype.bootstrap=function(e){this.comp=t.Core.Bootstrap(this.self,e,this.inputs),this.self=this.comp.nodeTree.self},t.Base=t.Base||{},t.Base.CompNode=e}(Function("return this")()),function(t){var e=function(t,r,n){this.el=t,r instanceof e&&(this.parent=r,r.children=r.children||[],r.children.push(this)),this.$scope=n};e.prototype.setView=function(t){this.el.parentNode.replaceChild(t.self,this.el),this.nodeTree=t,this.el=t.self},e.prototype.update=function(){this.nodeTree instanceof t.Base.CompNode&&this.nodeTree.compare(this)},e.prototype.getInput=function(t){if(this.inputs&&this.inputs.hasOwnProperty(t))return this.inputs[t];throw{message:"Input "+t+" doesn't exist."}},t.Base=t.Base||{},t.Base.Component=e}(Function("return this")()),function(t){var e=function(t,e,r){this.name=t,this.view=e,this.constructor=r};e.prototype.generateComponent=function(e,r,n){var i={},s=new t.Base.Component(e,r,i);return e.innerHTML.length>0&&(s.subView=new t.Base.View("content-outlet",null,e.innerHTML)),"object"==typeof n&&(s.inputs=n),i.getInput=function(t){i[t]=this.getInput(t)}.bind(s),this.constructor.call(this,i,s.update.bind(s)),s.setView(this.view.generate(s)),s},t.Base=t.Base||{},t.Base.Controller=e}(Function("return this")()),function(global){var TAG="[Injectable]",Injectable=function(t,e){this.name=t;try{this.modifier=e.modifier.bind(this)}catch(t){console.error(TAG,this.name+": No modifier set.")}"function"==typeof e.getter&&(this.getter=e.getter.bind(this)),"function"==typeof e.compare&&(this.compare=e.compare.bind(this)),this.keepAttribute=!!e.keepAttribute,this.justModify=!!e.justModify,this.useComponentInGetter=!!e.useComponentInGetter};Injectable.prototype.getter=function(statement,comp){var result;try{with(comp.$scope)result=eval(statement)}catch(t){console.error(TAG,this.name+":","Couldn't evaluate '"+statement+"'.")}return result},Injectable.prototype.compare=function(t,e){if(t===e)return!0},global.Base=global.Base||{},global.Base.Injectable=Injectable}(Function("return this")()),function(t){var e=function(t,e){this.name=t,this.initFunc=e,this.events={},this.init()};e.prototype.init=function(){if("function"!=typeof this.initFunc)throw{message:this.name+": Couldn't initialize the model (initFunc err)"};this.initFunc(function(t){this.setData(t)}.bind(this))},e.prototype.setData=function(t,e){this.data=t,this.emit(e||"setData",t)},e.prototype.emit=function(){for(var t,e=[],r=0;r<arguments.length;r++)0===r?t=arguments[r]:e.push(arguments[r]);if(Array.isArray(this.events[t]))for(var n=0;n<this.events[t].length;n++)this.events[t][n].apply(void 0,e)},e.prototype.subscribe=function(t,e){return this.events[t]||(this.events[t]=[]),this.events[t].push(e),{unsubscribe:function(t){this.events.splice(this.events.indexOf(t),1)}.bind(this,e)}},t.Base=t.Base||{},t.Base.Model=e}(Function("return this")()),function(t){var e=function(t){if(!t.hasOwnProperty("path"))throw{message:"[Route] Route must have a path."};if(this.path=t.path.split("/"),t.hasOwnProperty("controller"))this.controller=t.controller;else{if(!t.hasOwnProperty("redirect"))throw{message:"[Route] Route must have a controller."};this.redirect=t.redirect}Array.isArray(t.children)&&(this.children=t.children.map(function(t){return new e(t)}))};e.prototype.checkUrl=function(t,e){var r=0;if(this.path.length>t.length)return!1;for(var n=0;n<this.path.length;n++)this.path[n]===t[n]&&r++;if(this.path.length===r){if(this.redirect)return{redirect:this.redirect};if(Array.isArray(e)||(e=[]),e.push(this.controller),this.path.length<t.length){if(!Array.isArray(this.children))return!1;var i=!1;for(t.splice(0,r),n=0;n<this.children.length;n++)if(this.children[n].checkUrl(t,e)){i=e;break}return i}if(Array.isArray(this.children))for(var s=this.children.filter(function(t){return 1===t.path.length&&""===t.path[0]});Array.isArray(s)&&s.length>0;)s=s[0],e.push(s.controller),Array.isArray(s.children)&&(s=s.children.filter(function(t){return 0===t.path.length}));return{controllers:e}}return!1},t.Base=t.Base||{},t.Base.Route=e}(Function("return this")()),function(t){var e=t.Config.viewOptions,r=function(t,e,r){this.name=t,r?this.templateSrc=r:this.loadTemplate(e),this.buildNodeTree()};r.prototype.loadTemplate=function(t){var r=e.templatesFolder+"/"+t+this.name+".html";r=r.replace(/\/\//g,"/"),this.templateSrc=function(t){var e=new XMLHttpRequest;return e.open("GET",t,!1),e.send(),e.responseText}(r)},r.prototype.buildNodeTree=function(){function e(r){for(var n,i=new t.Base.ViewNode(r),s=0;s<r.childNodes.length;s++)(n=e(r.childNodes[s])).parent=i,i.children.push(n);return i}var r=document.createElement("temp");r.innerHTML=this.templateSrc;for(var n=new t.Base.ViewNode(document.createElement(this.name)),i=0;i<r.childNodes.length;i++)n.children.push(e(r.childNodes[i]));this.nodeTree=n},r.prototype.generate=function(e){for(var r=new t.Base.CompNode(this.nodeTree),n=0;n<this.nodeTree.children.length;n++)r.appendChild(this.nodeTree.children[n].generate(e));return r},t.Base=t.Base||{},t.Base.View=r}(Function("return this")()),function(t){var e=function(t){this.self=t,this.children=[],this.parseNode()};e.prototype.parseNode=function(){var e=this.self.attributes;if(e&&e.length>0)for(var r=0;r<e.length;r++)if("controller"===e[r].name)this.controller=e[r].value;else{var n=t.App.getInjectable(e[r].name);n instanceof t.Base.Injectable&&(Array.isArray(this.directives)||(this.directives=[]),this.directives.push({injectable:n,statement:e[r].value}),n.keepAttribute||(this.self.removeAttribute(e[r].name),r--))}},e.prototype.generate=function(e){var r=new t.Base.CompNode(this),n=e.$scope;if(Array.isArray(this.directives)){var i,s;for(r.values=[],s=0;s<this.directives.length&&r.self;s++)if(this.directives[s]){var o=(i=this.directives[s]).injectable.getter(i.statement,e);if(i.injectable.modifier(r,o),r.values.push(o),r.multipleNodes)break}}if(r.self)if(r.multipleNodes){var a,l=r.iterator.array,c=n[r.iterator.varName],h=this.directives[s],u=s;this.directives[s]=void 0;for(s=0;s<l.length;s++)n[r.iterator.varName]=l[s],(a=this.generate(e)).iteratorValue=l[s],a.self&&0,r.appendChild(a),a.isComponent()&&a.bootstrap(e);n[r.iterator.varName]=c,this.directives[u]=h}else!function(t,r){for(var n,i=0;i<t.children.length;i++)n=t.children[i].generate(e),r.appendChild(n),n.replaceSelfWith&&(n.self.parentNode.replaceChild(n.replaceSelfWith.self,n.self),delete n.replaceSelfWith),n.isComponent()&&n.bootstrap(e)}(this,r);return r},t.Base=t.Base||{},t.Base.ViewNode=e}(Function("return this")()),function(t){function e(e){var r=e.getAttribute("controller");if("string"==typeof r){var n=t.App.getController(r);if(n instanceof t.Base.Controller)return n}}t.Core=t.Core||{},t.Core.Bootstrap=function(r,n,i){if(1===r.nodeType){var s=e(r);if(s instanceof t.Base.Controller)return s.generateComponent(r,n,i);throw{message:"Controller "+r.getAttribute("controller")+" not found."}}throw{message:"Cannot bootstrap a non-element object."}}}(Function("return this")()),function(t){var e,r=function(r){if(e)return e;if(!Array.isArray(r))throw{message:"[Router] 'routes' should be an array of routes."};window.onhashchange=function(){this.navigating||this.navigateTo(location.hash),this.navigating=!1}.bind(this);try{this.routes=r.map(function(e){return new t.Base.Route(e)})}catch(t){throw t}e=this,this.navigateTo(location.hash)};r.prototype.navigateTo=function(e){if("#"===e[0]&&(e="/"!==e[1]?e.slice(1,e.length):e.slice(2,e.length)),e!==this.currentPath){this.currentPath=e;var r=this.parseUrl(e);if(r){var n=r.results;n.redirect?this.navigateTo(n.redirect):("string"==typeof r.params&&r.params.length>0&&(r.params=t.Utils.String.toDictionary(r.params,"&","=")),history.pushState(null,"","#/"+e),this.stateChange(r))}else console.error("UNKNOWN ROUTE "+e)}},r.prototype.parseUrl=function(t){var e=t.split("?"),r=e[1];e=e[0].split("/").filter(function(t){return"#"!==t});for(var n,i=0;i<this.routes.length&&!n;i++)n=this.routes[i].checkUrl(e);return!!n&&{results:n,params:r}},r.prototype.stateChange=function(e){var r=e.results;if(this.state){for(var n,i=0;i<r.controllers.length;i++)if(r.controllers[i]!==this.state.controllers[i]){for(var s=i;s<r.controllers.length;s++)this.state.controllers[s]=r.controllers[s];s<this.state.controllers.length&&this.state.controllers.splice(s,this.state.controllers.length),this.state.nextController=r.controllers[i],n=this.state.compNodes[i];break}if("object"==typeof e.params){for(var o in e.params)e.params.hasOwnProperty(o)&&this.updateParam(o,e.params[o]);for(o in this.state.params)this.state.params.hasOwnProperty(o)&&(e.params[o]||this.updateParam(o))}else{var a=this.state.params;if("object"==typeof a)for(o in a)a.hasOwnProperty(o)&&this.updateParam(o)}if(n instanceof t.Base.CompNode){var l=n.comp,c=n.viewNode.generate(l);n.parent.replaceChild(c,n),c.bootstrap(l.parent)}}else this.state={controllers:r.controllers,params:e.params,nextController:r.controllers[0]}},r.prototype.nextController=function(t){if(this.state&&this.state.nextController){var e=this.state.nextController;this.state.nextController=void 0;for(var r=0;r<this.state.controllers.length;r++)if(e===this.state.controllers[r]){Array.isArray(this.state.compNodes)||(this.state.compNodes=[]),this.state.nextController=this.state.controllers[r+1],this.state.compNodes[r]=t;break}return e}console.error("[Router]","Failed to load next controller, end of list.")},r.prototype.updateParam=function(e,r){var n=this.params(),i=0;if(n[e]!==r&&(r&&0!==r.length?n[e]=r:delete n[e],i++,this.paramSubscriptions)){var s=this.paramSubscriptions[e];s instanceof t.Utils.Observable&&s.next(r)}if(i>0){this.navigating=!0;var o=location.hash;o=o.split("?")[0]+"?";for(var a in n)n.hasOwnProperty(a)&&(o+=a+"="+n[a]+"&");location.hash=o.substr(0,o.length-1),this.currentPath=location.hash.substr(2,location.hash.length)}this.state&&(this.state.params=n)},r.prototype.subscribeToParam=function(e,r){"object"!=typeof this.paramSubscriptions&&(this.paramSubscriptions={});var n=this.paramSubscriptions;n[e]instanceof t.Utils.Observable||(n[e]=new t.Utils.Observable);var i=n[e].subscribe(r);return this.state&&this.state.params&&r(this.state.params[e]),i},r.prototype.params=function(){return this.state&&"object"==typeof this.state.params?this.state.params:{}},t.Core=t.Core||{},t.Core.Router=r}(Function("return this")()),function(t){var e,r={},n={},i={};t.App={getController:function(t){return r[t]},getInjectable:function(t){return n[t]},getModel:function(t){return i[t]},Bootstrap:function(e){var r="[Bootstrap]",n=document.querySelector('*[controller="'+e+'"]');if(n&&1===n.nodeType){try{var i=t.Core.Bootstrap(n)}catch(t){console.error(r,t.message)}return i}console.error(r,"Could not find placeholder for '"+e+"'.")},Controller:function(e,n,i){try{var s=new t.Base.View(e,n);r[e]=new t.Base.Controller(e,s,i)}catch(t){console.error("[Controller]",t.message)}},Injectable:function(e,r){try{n[e]=new t.Base.Injectable(e,r)}catch(t){console.error("[Injectable]",t.message)}},Model:function(e,r){try{i[e]=new t.Base.Model(e,r)}catch(t){console.error("[Model]",t.message)}},Router:function(r){return e||(e=new t.Core.Router(r)),e}}}(Function("return this")()),function(global){global.App.Injectable("bind-class",{justModify:!0,getter:function(statement,comp){var classes=global.Utils.String.toDictionary(statement),value;try{with(comp.$scope)for(var className in classes)classes.hasOwnProperty(className)&&(value=eval(classes[className]),classes[className]=!!value)}catch(t){throw{message:this.name+": "+t.message}}return classes},modifier:function(t,e){for(var r in e)e.hasOwnProperty(r)&&(e[r]?t.self.classList.add(r):t.self.classList.remove(r))}})}(Function("return this")()),function(global){global.App.Injectable("bind-if",{getter:function(statement,comp){var result;try{with(comp.$scope)result=eval(statement)}catch(t){throw this.name+": Couldn't evaluate '"+statement+"'."}return!!result},modifier:function(t,e){e||(t.self=void 0)}})}(Function("return this")()),Function("return this")().App.Injectable("content-outlet",{getter:function(t,e){return e},modifier:function(t,e){e.subView&&(t.replaceSelfWith=e.subView.generate(e.parent))}}),function(global){global.App.Injectable("bind-events",{getter:function(statement,comp){var events=global.Utils.String.toDictionary(statement),matches,funcName,variables;for(var event in events)if(events.hasOwnProperty(event)){var regEx=new RegExp("^(.+)\\((.*)\\)$");if(matches=events[event].match(regEx),!Array.isArray(matches)||matches.length<2)throw this.name+": Invalid statement, expecting: [event: func()]";funcName=matches[1],variables=matches[2].split(",");for(var i=0;i<variables.length;i++)try{with(comp.$scope)variables[i]=eval(variables[i])}catch(t){throw this.name+": "+t.message}events[event]=function(funcName,variables,el){var func;try{with(comp.$scope)func=eval(funcName)}catch(t){throw this.name+": "+t.message}"function"==typeof func&&func.apply(el,variables)}.bind(this,funcName,variables)}return events},modifier:function(t,e){for(var r in e)e.hasOwnProperty(r)&&t.self.addEventListener(r,function(t,e){e&&e.preventDefault&&e.preventDefault();try{t(e.target)}catch(t){console.error("[Injectable]",t)}}.bind(this,e[r]))},compare:function(t,e){return!0}})}(Function("return this")()),function(global){global.App.Injectable("input",{getter:function(statement,comp){var inputs=global.Utils.String.toDictionary(statement);try{for(var input in inputs)if(inputs.hasOwnProperty(input))with(comp.$scope)inputs[input]=eval(inputs[input])}catch(t){throw{message:this.name+": "+t.message}}return inputs},modifier:function(t,e){t.inputs=e},compare:function(t,e){var r=!0;for(var n in e)if(e.hasOwnProperty(n)&&e[n]!==t[n]){r=!1;break}return r}})}(Function("return this")()),function(global){global.App.Injectable("bind-for",{getter:function(statement,comp){for(var words=statement.split(" "),result={},w=0;w<words.length;w++)if("in"===words[w]&&w>0&&w<words.length-1){try{with(comp.$scope)result.array=eval(words[w+1])}catch(t){throw t}result.varName=words[w-1]}return result},compare:function(t,e){return t.array===e.array},modifier:function(t,e){t.self=document.createElement("iterator"),t.multipleNodes=!0,t.iterator=e}})}(Function("return this")()),function(t){t.App.Injectable("router-outlet",{getter:function(t,e){return!0},modifier:function(e,r){var n=t.App.Router().nextController(e);t.App.getController(n)instanceof t.Base.Controller&&e.self.setAttribute("controller",n)}})}(Function("return this")()),Function("return this")().App.Injectable("bind-value",{justModify:!0,modifier:function(t,e){t.self.innerHTML=e}}); |
(function(global) { | ||
var Controllers = {}; | ||
var Injectables = {}; | ||
var Models = {}; | ||
var Controllers = {}, | ||
Injectables = {}, | ||
Models = {}, | ||
routerInstance; | ||
@@ -23,3 +24,4 @@ global.App = { | ||
Injectable: generateInjectable, | ||
Model: createModel | ||
Model: createModel, | ||
Router: getRouter | ||
}; | ||
@@ -74,2 +76,9 @@ | ||
function getRouter(routes) { | ||
if(!routerInstance) | ||
routerInstance = new global.Core.Router(routes); | ||
return routerInstance; | ||
} | ||
})(Function('return this')()); |
@@ -11,4 +11,5 @@ (function(global) { | ||
CompNode.prototype.compare = function($scope) { | ||
var updated = false; | ||
CompNode.prototype.compare = function(comp) { | ||
var updated = false, $scope = comp.$scope; | ||
if(Array.isArray(this.viewNode.directives)) { | ||
@@ -19,3 +20,3 @@ var directives = this.viewNode.directives, | ||
injectable = directives[i].injectable; | ||
getterValue = injectable.getter(directives[i].statement, $scope); | ||
getterValue = injectable.getter(directives[i].statement, comp); | ||
@@ -32,5 +33,7 @@ // If injectable getter with current scope result is | ||
} | ||
} else if(getterValue && Array.isArray(getterValue.array)) { | ||
} | ||
else if(getterValue && Array.isArray(getterValue.array)) | ||
break; | ||
} | ||
else if(getterValue === false && typeof this.self === 'undefined') | ||
break; | ||
} else | ||
@@ -53,10 +56,14 @@ skipped++; | ||
// Ignoring the iterator directive for now | ||
viewNode.directives[tempDirectivePos] = undefined; | ||
for(i = 0; i < iterator.array.length; i++) { | ||
// Injecting the proper value to scope | ||
$scope[iterator.varName] = iterator.array[i]; | ||
if(this.children[i] instanceof CompNode) { | ||
this.children[i].compare($scope); | ||
this.children[i].compare(comp); | ||
this.children[i].iteratorValue = iterator.array[i]; | ||
} else { | ||
newCompNode = viewNode.generate($scope); | ||
newCompNode = viewNode.generate(comp); | ||
newCompNode.iteratorValue = iterator.array[i]; | ||
@@ -66,2 +73,8 @@ this.appendChild(newCompNode); | ||
} | ||
while(i < this.children.length) { | ||
this.removeChild(this.children[i]); | ||
this.children.splice(i, 1); | ||
} | ||
// Reassigning values | ||
@@ -72,3 +85,3 @@ $scope[iterator.varName] = tempVal; | ||
this.children.forEach(function(child) { | ||
child.compare($scope); | ||
child.compare(comp); | ||
}); | ||
@@ -78,3 +91,3 @@ } | ||
// If there were changes, generate a new node. | ||
var newNode = this.viewNode.generate($scope); | ||
var newNode = this.viewNode.generate(comp); | ||
@@ -88,6 +101,4 @@ if(this.iteratorValue) | ||
// Finally if node is a component bootstrap it. | ||
if(newNode.isComponent()) { | ||
newNode.comp = global.Core.Bootstrap(newNode.self, newNode.inputs); | ||
newNode.self = newNode.comp.nodeTree.self; | ||
} | ||
if(newNode.isComponent()) | ||
newNode.bootstrap(comp); | ||
} | ||
@@ -108,4 +119,3 @@ }; | ||
if(newNode.self && child.self) { | ||
this.self.replaceChild(newNode.self, child.self); | ||
this.children.splice(this.children.indexOf(child), 1, newNode); | ||
this.removeChild(child, newNode) | ||
} else if(newNode.self && !child.self) { | ||
@@ -133,14 +143,29 @@ var childIndex = this.children.indexOf(child); | ||
CompNode.prototype.removeChild = function(child) { | ||
this.self.removeChild(child.self); | ||
CompNode.prototype.removeChild = function(child, replace) { | ||
if(Array.isArray(child.children)) { | ||
for(var i = 0; i < child.children.length; i++) | ||
child.removeChild(child.children[i]); | ||
} | ||
if(child.comp instanceof global.Base.Component) { | ||
child.comp.onDestroy(); | ||
delete child.comp; | ||
} | ||
if(replace) { | ||
this.children.splice(this.children.indexOf(child), 1, replace); | ||
this.self.replaceChild(replace.self, child.self); | ||
} else { | ||
this.self.removeChild(child.self); | ||
} | ||
child.self = undefined; | ||
child.children.splice(0, child.children.length); | ||
}; | ||
CompNode.prototype.isComponent = function() { | ||
return this.self && this.self.nodeType === 1 && this.viewNode.controller && !this.iterator; | ||
return this.self && this.self.nodeType === 1 && | ||
(this.viewNode.controller || typeof this.self.getAttribute('controller') === 'string') && | ||
!this.iterator; | ||
}; | ||
CompNode.prototype.bootstrap = function() { | ||
this.comp = global.Core.Bootstrap(this.self, this.inputs); | ||
CompNode.prototype.bootstrap = function(parent) { | ||
this.comp = global.Core.Bootstrap(this.self, parent, this.inputs); | ||
this.self = this.comp.nodeTree.self; | ||
@@ -147,0 +172,0 @@ }; |
(function(global) { | ||
var Component = function(el, $scope) { | ||
var Component = function(el, parent, $scope) { | ||
this.el = el; | ||
if(parent instanceof Component) { | ||
this.parent = parent; | ||
parent.children = parent.children || []; | ||
parent.children.push(this); | ||
} | ||
this.$scope = $scope; | ||
@@ -15,13 +20,28 @@ }; | ||
Component.prototype.update = function() { | ||
this.nodeTree.compare(this.$scope); | ||
if(this.nodeTree instanceof global.Base.CompNode) | ||
this.nodeTree.compare(this); | ||
}; | ||
Component.prototype.getInput = function(name) { | ||
Component.prototype.getInput = function(name, defaultValue) { | ||
if(this.inputs && this.inputs.hasOwnProperty(name)) | ||
return this.inputs[name]; | ||
else { | ||
throw { message: "Input " + name + " doesn't exist." }; | ||
return defaultValue; | ||
} | ||
}; | ||
Component.prototype.onDestroy = function() { | ||
if(Array.isArray(this.children)) | ||
while(this.children.length > 0) | ||
this.children[0].onDestroy(); | ||
if(Array.isArray(this.subscriptions)) | ||
this.subscriptions.forEach(function(subscription) { | ||
subscription.unsubscribe(); | ||
}); | ||
if(this.parent instanceof Component) | ||
this.parent.children.splice(this.parent.children.indexOf(this), 1); | ||
}; | ||
global.Base = global.Base || {}; | ||
@@ -28,0 +48,0 @@ global.Base.Component = Component; |
@@ -9,3 +9,3 @@ (function(global) { | ||
Controller.prototype.generateComponent = function(el, inputs) { | ||
Controller.prototype.generateComponent = function(el, parent, inputs) { | ||
// Creating new scope object | ||
@@ -15,4 +15,9 @@ var $scope = {}; | ||
// Generating new component | ||
var comp = new global.Base.Component(el, $scope); | ||
var comp = new global.Base.Component(el, parent, $scope); | ||
// Keeping the element's content as original HTML | ||
if(el.innerHTML.length > 0) { | ||
comp.subView = new global.Base.View('content-outlet', null, el.innerHTML); | ||
} | ||
// If inputs assigning them to comp | ||
@@ -23,6 +28,12 @@ if(typeof inputs === 'object') | ||
// Provide the $scope with a function to retrieve inputs | ||
$scope.getInput = function(name) { | ||
$scope[name] = this.getInput(name); | ||
$scope.getInput = function(name, defaultValue) { | ||
$scope[name] = this.getInput(name, defaultValue); | ||
}.bind(comp); | ||
// Provide the $scope with option to hold component subscriptions | ||
$scope.addSubscription = function(subscription) { | ||
this.subscriptions = this.subscriptions || []; | ||
this.subscriptions.push(subscription); | ||
}.bind(comp); | ||
// Running the constructor | ||
@@ -32,3 +43,3 @@ this.constructor.call(this, $scope, comp.update.bind(comp)); | ||
// Eventually setting the view for the component | ||
comp.setView(this.view.generate($scope)); | ||
comp.setView(this.view.generate(comp)); | ||
@@ -35,0 +46,0 @@ return comp; |
@@ -24,8 +24,9 @@ (function(global) { | ||
this.justModify = !!options.justModify; | ||
this.useComponentInGetter = !!options.useComponentInGetter; | ||
}; | ||
Injectable.prototype.getter = function(statement, $scope) { | ||
Injectable.prototype.getter = function(statement, comp) { | ||
var result; | ||
try { | ||
with($scope) { result = eval(statement); } | ||
with(comp.$scope) { result = eval(statement); } | ||
} catch(err) { | ||
@@ -32,0 +33,0 @@ console.error(TAG, this.name + ':', "Couldn't evaluate '" + statement + "'."); |
@@ -14,2 +14,4 @@ (function(global) { | ||
Model.prototype.init = function() { | ||
this.data = []; | ||
if(typeof this.initFunc !== 'function') { | ||
@@ -19,3 +21,3 @@ throw { message: this.name + ": Couldn't initialize the model (initFunc err)" }; | ||
this.initFunc(function(data) { | ||
this.setData(data); | ||
this.setData(data, true); | ||
}.bind(this)); | ||
@@ -25,7 +27,13 @@ } | ||
Model.prototype.setData = function(data, /*optional:*/ eventName) { | ||
this.data = data; | ||
Model.prototype.setData = function(data, merge, eventName) { | ||
merge = !!merge; | ||
if(!merge || !this.data) | ||
this.data = data; | ||
else { | ||
for(var i = 0; i < data.length; i++) | ||
this.data.push(data[i]); | ||
} | ||
// If eventName isn't specified default to 'setData'. | ||
this.emit(eventName || 'setData', data); | ||
this.emit(eventName || 'setData', this.data); | ||
}; | ||
@@ -56,5 +64,6 @@ | ||
return { | ||
unsubscribe: function(listener) { | ||
this.events.splice(this.events.indexOf(listener), 1); | ||
}.bind(this, listener) | ||
unsubscribe: function(event, listener) { | ||
var index = this.events[event].indexOf(listener); | ||
this.events[event].splice(index, 1); | ||
}.bind(this, event, listener) | ||
}; | ||
@@ -61,0 +70,0 @@ }; |
@@ -5,5 +5,11 @@ (function(global) { | ||
var View = function(name, relPath) { | ||
var View = function(name, relPath, template) { | ||
this.name = name; | ||
this.loadTemplate(relPath); | ||
if(!template) | ||
this.loadTemplate(relPath); | ||
else { | ||
this.templateSrc = template; | ||
} | ||
this.buildNodeTree(); | ||
@@ -51,6 +57,6 @@ }; | ||
View.prototype.generate = function($scope) { | ||
View.prototype.generate = function(comp) { | ||
var componentTree = new global.Base.CompNode(this.nodeTree); | ||
for(var c = 0; c < this.nodeTree.children.length; c++) { | ||
componentTree.appendChild(this.nodeTree.children[c].generate($scope, componentTree)); | ||
componentTree.appendChild(this.nodeTree.children[c].generate(comp)); | ||
} | ||
@@ -57,0 +63,0 @@ return componentTree; |
@@ -35,4 +35,5 @@ (function(global) { | ||
ViewNode.prototype.generate = function($scope) { | ||
var compNode = new global.Base.CompNode(this); | ||
ViewNode.prototype.generate = function(comp) { | ||
var compNode = new global.Base.CompNode(this), | ||
$scope = comp.$scope; | ||
@@ -47,3 +48,3 @@ if(Array.isArray(this.directives)) { | ||
// Get value from injectable getter | ||
var value = directive.injectable.getter(directive.statement, $scope); | ||
var value = directive.injectable.getter(directive.statement, comp); | ||
@@ -78,7 +79,7 @@ // Running modifier on created compNode with getter value | ||
$scope[compNode.iterator.varName] = arr[i]; | ||
childNode = this.generate($scope); | ||
childNode = this.generate(comp); | ||
childNode.iteratorValue = arr[i]; | ||
if(childNode.self) childCount++; | ||
compNode.appendChild(childNode); | ||
if(childNode.isComponent()) childNode.bootstrap(); | ||
if(childNode.isComponent()) childNode.bootstrap(comp); | ||
} | ||
@@ -100,6 +101,10 @@ | ||
for(var i = 0; i < viewNode.children.length; i++) { | ||
generated = viewNode.children[i].generate($scope, node); | ||
generated = viewNode.children[i].generate(comp); | ||
node.appendChild(generated); | ||
if(generated.isComponent()) generated.bootstrap(); | ||
if(generated.replaceSelfWith) { | ||
generated.self.parentNode.replaceChild(generated.replaceSelfWith.self, generated.self); | ||
delete generated.replaceSelfWith; | ||
} | ||
if(generated.isComponent()) generated.bootstrap(comp); | ||
} | ||
@@ -106,0 +111,0 @@ } |
@@ -8,7 +8,7 @@ (function(global) { | ||
// Functions | ||
getter: function(statement, $scope) { | ||
getter: function(statement, comp) { | ||
var classes = global.Utils.String.toDictionary(statement), | ||
value; | ||
try { | ||
with($scope) { | ||
with(comp.$scope) { | ||
for(var className in classes) if(classes.hasOwnProperty(className)) { | ||
@@ -15,0 +15,0 @@ value = eval(classes[className]); |
(function(global) { | ||
global.App.Injectable('bind-if', { | ||
getter: function(statement, $scope) { | ||
getter: function(statement, comp) { | ||
var result; | ||
try { | ||
with($scope) { result = eval(statement); } | ||
with(comp.$scope) { result = eval(statement); } | ||
} catch(err) { | ||
@@ -9,0 +9,0 @@ throw this.name + ": Couldn't evaluate '" + statement + "'."; |
(function(global) { | ||
global.App.Injectable('bind-events', { | ||
getter: function(statement, $scope) { | ||
getter: function(statement, comp) { | ||
var events = global.Utils.String.toDictionary(statement), | ||
@@ -11,19 +11,30 @@ matches, funcName, variables; | ||
matches = events[event].match(regEx); | ||
if(!Array.isArray(matches) || matches.length < 2) | ||
throw (this.name + ": Invalid statement, expecting: [event: func()]"); | ||
funcName = matches[1]; | ||
variables = matches[2].split(','); | ||
events[event] = function(funcName, variables) { | ||
for(var i = 0; i < variables.length; i++) { | ||
try { | ||
with(comp.$scope) { | ||
variables[i] = eval(variables[i]); | ||
} | ||
} catch(err) { | ||
throw (this.name + ": " + err.message) | ||
} | ||
} | ||
events[event] = function(funcName, variables, el) { | ||
var func; | ||
try { | ||
with($scope) { | ||
with(comp.$scope) { | ||
func = eval(funcName); | ||
} | ||
var values = []; | ||
for(var i = 0; i < variables.length; i++) { | ||
values[i] = $scope[variables[i]]; | ||
} | ||
func.apply(undefined, values); | ||
} catch(err) { | ||
throw (this.name + ": " + err.message) | ||
} | ||
if(typeof func === 'function') | ||
func.apply(el, variables); | ||
}.bind(this, funcName, variables); | ||
@@ -38,3 +49,3 @@ } | ||
try { | ||
callback(); | ||
callback(e.currentTarget); | ||
} catch(err) { | ||
@@ -41,0 +52,0 @@ console.error('[Injectable]', err); |
(function(global) { | ||
global.App.Injectable('input', { | ||
getter: function(statement, $scope) { | ||
getter: function(statement, comp) { | ||
var inputs = global.Utils.String.toDictionary(statement); | ||
try { | ||
for(var input in inputs) if(inputs.hasOwnProperty(input)) { | ||
with($scope) { | ||
with(comp.$scope) { | ||
inputs[input] = eval(inputs[input]); | ||
@@ -10,0 +10,0 @@ } |
(function(global) { | ||
global.App.Injectable('bind-for', { | ||
getter: function(statement, $scope) { | ||
getter: function(statement, comp) { | ||
var words = statement.split(' '), | ||
@@ -10,3 +10,3 @@ result = {}; | ||
try { | ||
with($scope) { | ||
with(comp.$scope) { | ||
result.array = eval(words[w+1]); | ||
@@ -22,5 +22,2 @@ } | ||
}, | ||
compare: function(oldVal, newVal) { | ||
return oldVal.array === newVal.array; | ||
}, | ||
modifier: function(compNode, value) { | ||
@@ -30,2 +27,5 @@ compNode.self = document.createElement('iterator'); | ||
compNode.iterator = value; | ||
}, | ||
compare: function(oldVal, newVal) { | ||
return oldVal.array === newVal.array; | ||
} | ||
@@ -32,0 +32,0 @@ }); |
(function(global) { | ||
var Bootstrap = function(el, inputs) { | ||
var Bootstrap = function(el, parent, inputs) { | ||
if(el.nodeType === 1) { | ||
var controller = getControllerFromEl(el); | ||
if(controller instanceof global.Base.Controller) { | ||
return controller.generateComponent(el, inputs); | ||
return controller.generateComponent(el, parent, inputs); | ||
} else | ||
@@ -9,0 +9,0 @@ throw { message: "Controller " + el.getAttribute('controller') + " not found." }; |
@@ -5,15 +5,20 @@ (function(global) { | ||
updateObject: function(origin, update, ignore) { | ||
var changes = 0; | ||
if(typeof origin === 'object' && typeof update === 'object') { | ||
for(var property in update) if(update.hasOwnProperty(property) && !isIgnored(property)) { | ||
switch(typeof update[property]) { | ||
case 'object': | ||
changes += ObjectFuncs.updateObject(origin[property], update[property]); | ||
break; | ||
default: | ||
if(origin[property] !== update[property]) { | ||
origin[property] = update[property]; | ||
changes++; | ||
} | ||
break; | ||
if(origin && update) { | ||
var changes = 0; | ||
if(typeof origin === 'object' && typeof update === 'object') { | ||
for(var property in update) if(update.hasOwnProperty(property) && !isIgnored(property)) { | ||
switch(typeof update[property]) { | ||
case 'object': | ||
if(Array.isArray(update[property])) { | ||
console.warning('[Utils:Object] "updateObject" does not support merging arrays.'); | ||
} else | ||
changes += ObjectFuncs.updateObject(origin[property], update[property]); | ||
break; | ||
default: | ||
if(origin[property] !== update[property]) { | ||
origin[property] = update[property]; | ||
changes++; | ||
} | ||
break; | ||
} | ||
} | ||
@@ -20,0 +25,0 @@ } |
@@ -20,5 +20,7 @@ (function(global) { | ||
}, | ||
toDictionary: function(str, separator) { | ||
toDictionary: function(str, separator, equalizer) { | ||
if(typeof separator !== 'string') | ||
separator = ','; | ||
if(typeof equalizer !== 'string') | ||
equalizer = ':'; | ||
var entries = str.split(separator), | ||
@@ -28,4 +30,6 @@ matchGroups, | ||
entries.forEach(function(entry) { | ||
matchGroups = (/([\w-]+): *(.+)/g).exec(entry.trim()); | ||
dic[matchGroups[1]] = matchGroups[2]; | ||
var regexp = new RegExp('([\\w-]+)' + equalizer + ' *(.+)'); | ||
matchGroups = regexp.exec(entry.trim()); | ||
if(Array.isArray(matchGroups) && matchGroups.length === 3) | ||
dic[matchGroups[1]] = matchGroups[2]; | ||
}); | ||
@@ -32,0 +36,0 @@ return dic; |
{ | ||
"name": "mvc-lite", | ||
"version": "1.0.5", | ||
"version": "1.0.6", | ||
"description": "Lite MVC Library using pure EcmaScript5", | ||
@@ -5,0 +5,0 @@ "main": "main.js", |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
120194
42
2382