Commit 2aef4b5d authored by Marcus Krejpowicz's avatar Marcus Krejpowicz Committed by Sindre Sorhus

Close GH-156: rappidjs update. Fixes #140

parent 6ed23dfd
(The MIT License)
Copyright (c) 2012 M Krejpowicz <krebbl@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
# Simple Todo App build with rAppid.js
\ No newline at end of file
# Simple Todo App build with rAppid.js
This example app demonstrates the features and abilities of rAppid.js
## Documentation
### The index.html
In the index.html the application is bootStrapped by defining our main application file
(in this case Todo.xml). Because rAppid.js is a RIA framework, the whole rendering is done by javascript.
If you are now thinking 'yeah fine, but what about SEO ', don't worry, rAppid.js also support Node-Rendering, which can be used for things like SEO.
### The application file Todo.xml
The main view of the application is declarated in Todo.xml. The first tag of the Todo.xml defines the super class of our application and the namespaces used inside the application description.
```xml
<?xml version="1.0"?>
<app:TodoClass xmlns="http://www.w3.org/1999/xhtml"
xmlns:js="js.core" xmlns:ui="js.ui" xmlns:app="app" xmlns:view="app.view" xmlns:conf="js.conf">
...
</app:TodoClass>
```
As you can see, the default namespace is `"http://www.w3.org/1999/xhtml"` which allows us to use plain HTML elements to describe our view.
The other namespaces are used for custom components.
One example of a custom component is the Router configuration.
```xml
<js:Router cid="router">
<conf:Route name="default" route="^$" onexec="showAll"/>
<conf:Route name="active" route="^active$" onexec="showActive"/>
<conf:Route name="completed" route="^completed$" onexec="showCompleted"/>
</js:Router>
```
Inside this declaration all routes of the application are defined. The **route** attribute expects a regular expression, which matches the route.
The **onexec** attribute defines the function which will be called, if the route is triggered.
The rest of the markup defines the UI of our application.
To connect the view with our application model we use bindings. For example the header:
```html
<header id="header">
<h1>{i18n.translate('title')}</h1>
<input id="new-todo" placeholder="{i18n.translate('placeholder')}" type="text" onkeyup="addNewTodo"
value="{{newTodo.title}}" autofocus="autofocus"/>
</header>
```
The bindings tell the application to hold view and model in sync. If you're interested in more details, checkout the rAppid.js wiki.
### The code behind file TodoClass.js
The TodoClass.js is the code behind file for Todo.xml. It initializes the attributes used in this application and it defines the event handlers for routing and ui events.
So there is a clean seperation between application code and ui declaration.
In the initialize method inside TodoClass all binded models are created and set as attributes of the application. This is important for resolving the bindings used in the view declaration.
### The Todo Model (app/model/Todo.js)
In this model, the default attributes for an instance and some methods used inside the application are defined.
It also marks the functions `hasTitle` and `status` as bindable.
```javascript
status: function () {
return this.$.completed ? "done" : '';
}.onChange("completed"),
```
Calling the `onChange(...)` function tells the application that the binding value of this methods has to be refreshed everytime the attributes change.
See app/view/TodoView.xml for usage.
### The Todo List (app/collection/TodoList.js)
The Todo List is a bindable List which encapsulates some application logic for manipulating the todo instances.
It also declares bindable functions, which are used inside the view ...
### The Todo View (app/view/TodoView.xml)
The Todo view is a custom view for displaying and editing Todo instances.
Here we define view logic and view declaration in one file.
<?xml version="1.0"?>
<app:TodoClass xmlns="http://www.w3.org/1999/xhtml"
xmlns:js="js.core" xmlns:ui="js.ui" xmlns:app="app" xmlns:view="app.view">
<js:Injection>
<js:I18n locale="en_EN"/>
</js:Injection>
<div class="container">
<div id="todoapp">
<div class="language">
<select items="{locales}" selectedItem="{{i18n.locale}}">
<js:Template name="item">
<option value="{$item}">{i18n.translate({$item})}</option>
</js:Template>
</select>
</div>
xmlns:js="js.core" xmlns:ui="js.ui" xmlns:app="app" xmlns:view="app.view" xmlns:conf="js.conf"
xmlns:data="js.data">
<!-- LOCAL STORAGE CONFIGURATION -->
<data:LocalStorageDataSource cid="dataSource" name="todo-rappidjs">
<conf:Configuration path="todos" modelClassName="app.model.Todo"
collectionClassName="app.collection.TodoList"/>
</data:LocalStorageDataSource>
<div class="title">
<h1>{i18n.translate(title)}</h1>
</div>
<div class="content">
<div id="create-todo">
<!-- HERE WE USE TWO WAY BINDING TO SET THE CONTENT OF THE NEW TODO -->
<input id="new-todo" placeholder="{i18n.translate(placeholder)}" type="text" onkeyup="addNewTodo"
value="{{newTodo.content}}"/>
<!-- EACH ELEMENT WITH A CID IS REGISTERED IN THE ROOT SCOPE -->
<span class="ui-tooltip-top" cid="hint" visible="false">{i18n.translate(hint)}</span>
</div>
<!-- ROUTER CONFIGURATION -->
<js:Router cid="router">
<conf:Route name="default" route="^$" onexec="showAll"/>
<conf:Route name="active" route="^active$" onexec="showActive"/>
<conf:Route name="completed" route="^completed$" onexec="showCompleted"/>
</js:Router>
<div id="todo-list">
<div visible="{todoList.hasItems()}">
<input class="check mark-all-done" type="checkbox" onclick="markAllComplete" id="check-all"
checked="{todoList.areAllComplete()}"/>
<label for="check-all">{i18n.translate(markAllAsComplete)}</label>
</div>
<!-- CUSTOM UI COMPONENT FOR RENDERING A LIST OF ITEMS -> TODOs -->
<ui:ItemsView list="{todoList}" tagName="ul" id="todoList">
<js:Template name="item">
<view:TodoView todo="{$item}" tagName="li" onremove="removeTodo"/>
</js:Template>
</ui:ItemsView>
</div>
<div id="todo-stats">
<span class="todo-count" data-num="{todoList.numOpenTodos()}">
<span class="number">{data-num}</span>
{i18n.translate({data-num},item)} {i18n.translate(left)}.
</span>
<span class="todo-sort" visible="{todoList.hasItems()}">
<a href="javascript: void 0;" onclick="sort">
{i18n.translate(sortTodos)}
</a>
</span>
<span class="todo-clear" visible="{todoList.hasCompletedTodos()}">
<!-- FOR THE ITEMS STRING WE USE A FUNCTION WHICH GETS A NUMBER OF ITEMS AS INPUT -->
<a href="javascript: void 0;" onclick="clearCompleted"
data-num="{todoList.numCompletedTodos()}">
{i18n.translate(clear)}
<span class="number-done">{data-num}</span>
{i18n.translate(completed)}
<span class="word-done">
{i18n.translate({data-num},item)}
</span>
</a>
</span>
</div>
</div>
</div>
<div id="credits">
{i18n.translate(createdBy)}
<a href="http://github.com/krebbl">Marcus Krejpowicz</a>
<br/>
{i18n.translate(with)}
<a href="http://rappidjs.com">&lt;rAppid:js /&gt;</a>.
<!-- HERE WE START TO DEFINE THE UI WITH HTML AND CUSTOM UI COMPONENTS -->
<section id="todoapp">
<header id="header">
<h1>Todos</h1>
<input id="new-todo" placeholder="What needs to be done?" type="text" onkeyup="addNewTodo" autofocus="autofocus"/>
</header>
<section id="main" visible="{todoList.hasItems()}">
<input id="toggle-all" type="checkbox" onclick="markAllComplete"
checked="{todoList.areAllComplete()}"/>
<label for="toggle-all">Mark all as complete</label>
<!-- CUSTOM UI COMPONENT FOR RENDERING A LIST OF ITEMS -> TODOs -->
<ui:ItemsView items="{filterList.list}" tagName="ul" id="todo-list" itemKey="todo">
<js:Template name="item">
<view:TodoView todo="{$todo}" tagName="li" onremove="removeTodo"/>
</js:Template>
</ui:ItemsView>
</section>
<footer id="footer" data-num="{todoList.numOpenTodos()}" visible="{todoList.hasItems()}">
<span id="todo-count">
<strong>{data-num}</strong> {translateItems({data-num})} left
</span>
<ul id="filters">
<li>
<a href="#/" class="{selectedClass('all',{filterList.filter})}">All</a>
</li>
<li>
<a href="#/active" class="{selectedClass('active',{filterList.filter})}">Active</a>
</li>
<li>
<a href="#/completed" class="{selectedClass('completed',{filterList.filter})}">Completed</a>
</li>
</ul>
<button id="clear-completed" onclick="clearCompleted" visible="{todoList.hasCompletedTodos()}">
Clear completed ({todoList.numCompletedTodos()})
</button>
</footer>
</section>
<footer id="info">
<p visible="{todoList.hasItems()}">Double - click to edit a todo</p>
<p>Template by <a href="http://github.com/sindresorhus">Sindre Sorhus</a></p>
<p>
Created by <a href="http://github.com/krebbl">Marcus Krejpowicz</a> with<a href="http://rappidjs.com">&lt; rAppid:js/&gt;</a>
<br/>
{i18n.translate(creditsTo)} <a href="http://github.com/it-ony">Tony Findeisen</a>.
</div>
</div>
Big credits to <a href="http://github.com/it-ony">Tony Findeisen</a>
</p>
<p>Part of
<a href="http://todomvc.com">TodoMVC</a>
</p>
</footer>
</app:TodoClass>
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
define(["js/core/Application", "js/core/I18n", "app/model/Todo", "app/collection/TodoList", "js/data/FilterDataView", "js/data/LocalStorageDataSource"],
function (Application, I18n, Todo, TodoList, FilterDataView, DataSource) {
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("app.TodoClass",
["js.core.Application", "js.core.I18n", "app.model.Todo", "app.collection.TodoList"],
function (Application, I18n, Todo, TodoList) {
var ENTER_KEY = 13;
return Application.inherit({
inject:{
i18n:I18n
},
/**
* Initializes the app
* In this method we set the initial models
*/
initialize:function () {
this.set("todoList", new TodoList());
this.set("newTodo", new Todo());
this.set("locales",["en_EN","de_DE"]);
},
/**
* The rest is just controller stuff
*/
addNewTodo:function (e) {
if (e.$.keyCode === 13) {
var tmp = this.get("newTodo");
if (tmp.hasContent()) {
var newTodo = new Todo({content:tmp.get("content")});
newTodo.setDone(false);
this.get("todoList").add(newTodo);
tmp.set("content", "");
}
this.get("hint").set("visible", false);
} else {
// some hint stuff
var hint = this.get("hint");
if (!hint.get("visible")) {
setTimeout(function () {
hint.set("visible", true);
return Application.inherit("app.TodoClass", {
/**
* Initializes the app
* In this method we set the initial models
*/
initialize: function () {
this.set("todoList", null);
this.set("filterList", null);
this.callBase();
},
/**
* Are triggered
*/
showAll: function () {
this.$.filterList.set("filter", 'all');
},
showActive: function () {
this.$.filterList.set("filter", "active");
},
showCompleted: function () {
this.$.filterList.set("filter", "completed");
},
/**
* The rest is just controller stuff
*/
addNewTodo: function (e) {
if (e.domEvent.keyCode === ENTER_KEY) {
var title = e.target.get("value").trim();
if (title) {
var newTodo = this.$.dataSource.createEntity(Todo);
newTodo.set({title: title, completed: false});
this.get("todoList").add(newTodo);
setTimeout(function () {
hint.set("visible", false);
}, 2000);
}, 400);
}
// save the new item
newTodo.save();
e.target.set('value','');
}
}
},
markAllComplete: function (e) {
this.get("todoList").markAll(e.target.$el.checked);
},
clearCompleted: function () {
this.get("todoList").clearCompleted();
},
removeTodo: function (e) {
var todo = e.$, self = this;
todo.remove(null, function(err){
if(!err){
self.get("todoList").remove(todo);
}
},
markAllComplete:function (e, input) {
this.get("todoList").markAll(input.get("checked"));
},
clearCompleted:function (e) {
this.get("todoList").clearCompleted();
},
removeTodo:function (e, el) {
this.get("todoList").remove(e.$);
},
sort:function () {
this.get("todoList").sort(function (t1, t2) {
if (t1.get("isDone") && t2.get("isDone")) {
return 0;
} else if (t1.get("isDone") === true && !t2.get("isDone")) {
return 1;
});
},
/**
* Start the application and render it to the body ...
*/
start: function (parameter, callback) {
this.set('todoList', this.$.dataSource.createCollection(TodoList));
// fetch all todos, can be done sync because we use localStorage
this.$.todoList.fetch();
this.set('filterList', new FilterDataView({
baseList: this.get("todoList"),
filter: 'all',
filterFnc: function (item) {
var filter = this.$.filter;
if (filter == "active") {
return !item.isCompleted();
} else if (filter == "completed") {
return item.isCompleted();
} else {
return -1;
return true;
}
});
},
/**
* Start the application and render it to the body ...
*/
start:function (parameter, callback) {
// false - disables autostart
this.callBase(parameter, false);
this.$.i18n.set("locale","en_EN",{silent: true});
this.$.i18n.loadLocale("en_EN", callback);
}
});
}
);
});
\ No newline at end of file
}})
);
// false - disables autostart
this.callBase();
},
translateItems: function(num){
return (num === 1) ? "item" : "items";
},
selectedClass: function (expected, current) {
return expected == current ? "selected" : "";
}
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
define(["js/data/Collection", "app/model/Todo", "flow"], function (Collection, Todo, flow) {
return Collection.inherit("app.collection.TodoList", {
$modelFactory: Todo,
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("app.collection.TodoList", ["js.core.List"], function (List) {
return List.inherit({
markAll:function (done) {
this.each(function (todo) {
todo.setDone(done);
});
},
areAllComplete:function () {
if(this.$items.length == 0) return false;
for (var i = 0; i < this.$items.length; i++) {
if (!this.$items[i].get("isDone")) {
return false;
}
markAll: function (done) {
this.each(function (todo) {
todo.setCompleted(done);
todo.save();
});
},
areAllComplete: function () {
if (this.$items.length === 0) {
return false;
}
for (var i = 0; i < this.$items.length; i++) {
if (!this.$items[i].isCompleted()) {
return false;
}
return true;
}.on('change','add','remove'),
clearCompleted:function () {
console.log("clear completed");
for (var i = this.$items.length-1; i >= 0; i--) {
if (this.$items[i].get("isDone")) {
this.removeAt(i);
}
}
return true;
}.on('change', 'add', 'remove'),
clearCompleted: function () {
var self = this;
// remove all completed todos in a sequence
flow().seqEach(this.$items,function (todo, cb) {
if (todo.isCompleted()) {
// remove the todo
todo.remove(null, function (err) {
if (!err) {
self.remove(todo);
}
cb(err);
});
} else {
cb();
}
},
numOpenTodos:function () {
var num = 0;
for (var i = 0; i < this.$items.length; i++) {
if (!this.$items[i].get("isDone")) {
num++;
}
}).exec();
},
numOpenTodos: function () {
var num = 0;
for (var i = 0; i < this.$items.length; i++) {
if (!this.$items[i].isCompleted()) {
num++;
}
return num;
}.on('change','add','remove'),
numCompletedTodos: function(){
var num = 0;
for (var i = 0; i < this.$items.length; i++) {
if (this.$items[i].get("isDone")) {
num++;
}
}
return num;
}.on('change', 'add', 'remove'),
numCompletedTodos: function () {
var num = 0;
for (var i = 0; i < this.$items.length; i++) {
if (this.$items[i].isCompleted()) {
num++;
}
return num;
}.on('change', 'add', 'remove'),
hasCompletedTodos: function(){
return this.numCompletedTodos() > 0;
}.on('change','add','remove')
});
}
return num;
}.on('change', 'add', 'remove'),
hasCompletedTodos: function () {
return this.numCompletedTodos() > 0;
}.on('change', 'add', 'remove')
});
});
\ No newline at end of file
{
"language" : "Sprache",
"title":"Aufgaben",
"placeholder":"Was soll erledigt werden?",
"hint":"Drücke ENTER, um die Aufgabe anzulegen",
"markAllAsComplete":"Markiere alle als erledigt",
"item":"Aufgabe",
"item_plural":"Aufgaben",
"left":"offen",
"clear":"Entferne",
"completed":"erledigte",
"sortTodos":"Sortieren",
"de_DE" : "Deutsch",
"en_EN" : "Englisch",
"createdBy":"Erstellt von",
"with":"mit",
"creditsTo":"Vielen Dank an"
}
\ No newline at end of file
{
"language" : "Language",
"title":"Todos",
"placeholder":"What needs to be done?",
"hint":"Press Enter to save this task",
"markAllAsComplete":"Mark all as complete",
"item":"item",
"item_plural":"items",
"left":"left",
"clear":"Clear",
"completed":"completed",
"sortTodos":"Sort todos",
"de_DE":"German",
"en_EN":"English",
"createdBy" : "Created by",
"with":"with",
"creditsTo" : "Big credits to"
}
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("app.model.Todo", ["js.core.Bindable"], function (Bindable) {
return Bindable.inherit({
defaults:{
content:"",
isDone: false
},
setDone:function (done) {
this.set("isDone", done);
},
status: function(){
if(this.$.isDone){
return "done";
}else{
return "";
}
}.onChange("isDone","isEditing"),
hasContent:function () {
return this.$.content.length > 0;
}.onChange("content")
});
define(["js/data/Model"], function (Model) {
return Model.inherit("app.model.Todo", {
defaults: {
title: "",
completed: false
},
setCompleted: function (completed) {
this.set("completed", completed);
},
isCompleted: function () {
return this.$.completed;
},
status: function () {
return this.$.completed ? "completed" : '';
}.onChange("completed"),
hasTitle: function () {
return this.$.title.trim().length;
}.onChange("title")
});
});
\ No newline at end of file
<ui:View xmlns="http://www.w3.org/1999/xhtml"
xmlns:js="js.core" xmlns:ui="js.ui">
xmlns:js="js.core" xmlns:ui="js.ui" componentClass="{todo.status()}">
<js:Script>
<![CDATA[
(function (Base, Bindable, Content) {
(function () {
var ENTER_KEY = 13;
var INPUT_BLUR = "blur";
return {
defaults:{
componentClass: "todo",
defaults: {
editing: false
},
events: [
"remove"
],
editTodo:function (e, div) {
var todo = div.find("$item");
this.set("editing",true);
e.$.stopPropagation();
// we don't use jquery, so we have to select this the old fashioned way
div.$el.parentNode.parentNode.getElementsByTagName("input")[1].select();
$classAttributes: ['todo', 'inputElement'],
events: ["remove"],
editTodo: function (e) {
this.set("editing", true);
e.preventDefault();
this.$.inputElement.$el.select();
return false;
},
checkTodo:function (e, input) {
checkTodo: function () {
var todo = this.get("todo");
todo.setDone(!todo.get("isDone"));
todo.setCompleted(!todo.isCompleted());
todo.save();
},
preventEditing: function(e){
e.stopPropagation();
},
updateTodo:function (e, input) {
updateTodo: function (e) {
var todo;
if (e.$.keyCode === 13) {
todo = this.get("todo");
this.set("editing",false);
} else if (e.$.keyCode === 27) {
todo = this.get("todo");
var content = todo.get("content");
input.$el.blur();
todo.set("content", content);
this.set("editing",false);
} else if (e.$.type === "blur") {
if (e.domEvent.keyCode === ENTER_KEY || e.domEvent.type === INPUT_BLUR) {
todo = this.get("todo");
this.set("editing",false);
if (!todo.hasTitle()) {
this.trigger("remove", todo);
} else {
this.set("editing", false);
todo.save();
}
}
},
triggerOnRemove: function(e, el){
this.trigger("onremove",this.get("todo"));
triggerOnRemove: function () {
this.trigger("remove", this.get("todo"));
},
_renderEditing: function(editing){
if(editing){
_renderEditing: function (editing) {
if (editing) {
this.addClass("editing");
}else{
} else {
this.removeClass("editing");
this.$.inputElement.$el.blur();
}
},
trim: function(title){
if(title){
return title.trim();
}
return "";
}
}
......@@ -57,19 +62,14 @@
]]>
</js:Script>
<js:Template name="layout">
<div class="{todo.status()}">
<div class="display">
<input class="check" type="checkbox" onchange="checkTodo"
checked="{todo.isDone}"/>
<label class="todo-content" ondblclick="editTodo">{todo.content}</label>
<span class="todo-destroy" onclick="triggerOnRemove"></span>
</div>
<div class="edit">
<input class="todo-input" type="text" value="{{todo.content}}"
onkeyup="updateTodo" onblur="updateTodo"/>
<div class="view" ondblclick="editTodo">
<input class="toggle" type="checkbox" onclick="checkTodo" ondblclick="preventEditing"
checked="{todo.completed}"/>
<label>{todo.title}</label>
<button class="destroy" onclick="triggerOnRemove"/>
</div>
</div>
<input class="edit" cid="inputElement" type="text" value="{{todo.title|trim()}}"
onkeyup="updateTodo" onblur="updateTodo" updateOnEvent="change"/>
</js:Template>
</ui:View>
{
"xamlClasses": ["js.ui.Link", "js.ui.MenuButton", "js.ui.SplitButton" , "js.ui.TabView", "app.view.TodoView"],
"xamlClasses": ["app/Todo", "app/view/TodoView", "js/ui/ButtonGroup", "js/ui/Link", "js/ui/List", "js/ui/MenuButton", "js/ui/Modal", "js/ui/ScrollView", "js/ui/SplitButton", "js/ui/TabView"],
"namespaceMap": null,
"rewriteMap": null
}
"rewriteMap": null,
"paths": {
"xaml": "js/plugins/xaml",
"json": "js/plugins/json",
"raw": "js/plugins/raw",
"flow": "js/lib/flow",
"inherit": "js/lib/inherit",
"underscore": "js/lib/underscore",
"JSON": "js/lib/json2.js"
}, "shim": {
"inherit": {
"exports": "inherit"
},
"flow": {
"exports": "flow"
},
"underscore": {
"exports": "_"
},
"js/lib/parser": {
"exports": "parser"
},
"JSON": {
"exports": "JSON"
}
}}
\ No newline at end of file
.hide {
display: none;
}
\ No newline at end of file
This diff is collapsed.
<!DOCTYPE HTML>
<html>
<head>
<title>Todo</title>
<link rel="stylesheet" href="css/todo.css"/>
<script type="text/javascript" src="lib/require.js"></script>
<script type="text/javascript" src="lib/inherit.js"></script>
<script type="text/javascript" src="lib/underscore-min.js"></script>
<script type="text/javascript" src="lib/flow.js"></script>
<script type="text/javascript" src="lib/rAppid.js"></script>
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<title>TodoMVC build with rAppid.js</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link rel="stylesheet" href="../../../assets/base.css">
<!-- CSS overrides - remove if you don't need it -->
<link rel="stylesheet" href="css/app.css">
<!--[if IE]>
<script src="../../../assets/ie.js"></script>
<![endif]-->
<script type="text/javascript" src="package/rappidjs.min.js"></script>
<script type="text/javascript">
rAppid.bootStrap("app/Todo.xml", "config.json",
function (err, systemManager, application) {
if (!err) {
application.start(null, function () {
application.render(document.body);
});
} else {
console.warn(err);
}
});
</script>
</head>
<body>
<script type="text/javascript">
rAppid.bootStrap("app/Todo.xml", "config.json",
function (err, systemManager, application) {
if (!err) {
application.start(null, function () {
application.render(document.body);
});
} else {
console.warn(err);
}
});
</script>
</body>
<body></body>
</html>
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.Application",
["js.core.UIComponent", "js.core.History"], function (UIComponent, History) {
return UIComponent.inherit({
ctor: function () {
this.history = new History();
this.callBase();
},
initialize: function () {
// set up application wide vars
this.callBase();
},
_inject: function() {
// overwrite and call inside start
},
_initializeDescriptors: function() {
this.callBase();
UIComponent.prototype._inject.call(this);
},
/**
* Method called, when application is initialized
*
* @param {Object} parameter
* @param {Function} callback
*/
start: function (parameter, callback) {
this.history.start();
if (callback) {
callback(null);
}
},
render: function (target) {
var dom = this.callBase(null);
if (target) {
target.appendChild(dom);
}
return dom;
},
toString: function () {
return "js.core.Application";
}
});
}
);
});
\ No newline at end of file
// defined under rAppid.js
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.Bindable", ["js.core.EventDispatcher"],
/**
* @export js.core.Bindable
*/
function (EventDispatcher) {
/**
* @class js.core.Bindable
* @extends js.core.EventDispatcher
*/
var Bindable = EventDispatcher.inherit({
ctor: function (attributes) {
// call the base class constructor
this.callBase(null);
this.$ = {};
rAppid._.extend(this._eventAttributes, this.base._eventAttributes || {});
attributes = attributes || {};
rAppid._.defaults(attributes, this._defaultAttributes());
this.$ = attributes;
this.$previousAttributes = rAppid._.clone(attributes);
var self = this, fnc;
var bind = function(key, targetKey, method){
self.bind('change:' + key, function () {
self.set(targetKey, method.call(self));
});
};
},
defaults: {
},
_defaultAttributes: function () {
return this._generateDefaultsChain("defaults");
},
_generateDefaultsChain: function (property) {
var ret = this[property],
base = this.base;
while (base) {
rAppid._.defaults(ret, base[property]);
base = base.base;
}
// clone all attributes
for(var k in ret){
if(ret.hasOwnProperty(k) && !rAppid._.isFunction(ret[k])){
ret[k] = rAppid._.clone(ret[k]);
}
}
return ret;
},
/**
*
* @param key
* @param value
* @param options
*/
set: function (key, value, options) {
var attributes = {};
if (rAppid._.isString(key)) {
// check for path
var path = key.split(".");
if (path.length > 1) {
var scope = this.get(path.shift());
if (scope && scope.set) {
scope.set(path.join("."), value, options);
return this;
}
}
attributes[key] = value;
} else {
options = value;
attributes = key;
}
options = options || {silent: false, unset: false};
// for unsetting attributes
if (options.unset) {
for (key in attributes) {
attributes[key] = void 0;
}
}
var changedAttributes = {},
equal = true,
now = this.$,
val;
for (key in attributes) {
if (attributes.hasOwnProperty(key)) {
// get the value
val = attributes[key];
// unset attribute or change it ...
if (options.unset === true) {
delete now[key];
} else {
if (!rAppid._.isEqual(now[key], attributes[key])) {
this.$previousAttributes[key] = now[key];
now[key] = attributes[key];
changedAttributes[key] = now[key];
}
}
// if attribute has changed and there is no async changing process in the background, fire the event
}
}
this._commitChangedAttributes(changedAttributes);
if (options.silent === false && rAppid._.size(changedAttributes) > 0) {
for (key in changedAttributes) {
if (changedAttributes.hasOwnProperty(key)) {
this.trigger('change:' + key, changedAttributes[key], this);
}
}
this.trigger('change', changedAttributes, this);
}
return this;
},
get: function (key) {
//var path = key.split(".");
return this.$[key];
/*
var key;
while (path.length > 0 && prop != null) {
key = path.shift();
if (prop instanceof Bindable) {
prop = prop.get(key);
} else if (typeof(prop[key]) !== "undefined") {
prop = prop[key];
} else {
return null;
}
} */
},
has: function(key){
return typeof(this.$[key]) !== "undefined" && this.$[key] !== null;
},
_commitChangedAttributes: function (attributes) {
},
unset: function (key, options) {
(options || (options = {})).unset = true;
return this.set(key, null, options);
},
clear: function () {
return this.set(this.$, {unset: true});
}
});
return Bindable;
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.Binding", ["js.core.Bindable", "js.core.EventDispatcher"], function (Bindable, EventDispatcher) {
var $splitAtReg = /\.?(?:\w+\([^(]*\)|[^.]+)/;
var splitPath = function(path){
var matches = [];
var match = path.match($splitAtReg);
while(match[0]){
matches.push(match[0]);
path = path.substr(match[0].length+1);
match = path.search($splitAtReg);
}
if(path.length > 0){
matches.push(path);
}
return matches;
};
var splitFirst = function(path){
var match = path.match($splitAtReg);
if(match){
return match[0];
}
return path;
};
var Binding = Bindable.inherit({
defaults: {
event: 'change',
path: null,
twoWay: false,
transform: function (val) {
return val;
},
transformBack: function (val) {
return val;
}
},
ctor: function () {
this.callBase();
this.initialize();
},
initialize: function () {
this._checkAttributes();
this.$parameters = [];
this.$subBinding = null;
if (!this.$.rootScope) {
this.$.rootScope = this;
}
var scope = this.$.scope;
var keys = splitPath(this.$.path);
// split up first key
this.$.key = keys.shift();
if($fncRegex.test(this.$.key)){
var matches = this.$.key.match($fncRegex);
var fncName = matches[1];
var fncParameterStr = matches[2];
if (rAppid._.isFunction(scope[fncName])) {
var fnc = scope[fncName];
var events = [];
if(fnc._events){
events = fnc._events;
}else{
events = ['change'];
}
for (var i = 0; i < events.length; i++) {
var event = events[i];
scope.bind(event, this._callback, this);
}
var self = this;
var cb = function(){
self.trigger();
};
// TODO: implement regex for , splitting
this.$parameters = fncParameterStr.split(",");
for (var j = 0; j < this.$parameters.length; j++) {
var para = this.$parameters[j];
if($bindingRegex.test(para)){
para = Binding.create(para,this.$.target,cb);
}
this.$parameters[j] = para;
}
this.$.fnc = fnc;
}
}else{
this.$.event = "change:" + this.$.key;
// on change of this key
scope.bind(this.$.event, this._callback, this);
if (this.$.twoWay === true) {
this.$.targetEvent = 'change:' + this.$.targetKey;
this.$.target.bind(this.$.targetEvent, this._revCallback, this);
}
}
this._createSubBinding();
},
_checkAttributes: function () {
// check infrastructur
if (!this.$.path) {
throw "No path defined!";
}
if (!this.$.scope) {
throw "No scope defined!"
}
if (this.$.twoWay) {
if (!this.$.target) {
throw "TwoWay binding, but no target defined!";
}
if (!this.$.target instanceof Bindable) {
throw "Target is not a Bindable!";
}
if (!this.$.targetKey) {
throw "TwoWay binding, but no target key defined!";
}
}
},
_createSubBinding: function () {
var keys = splitPath(this.$.path);
var k = keys.shift();
if (keys.length > 0) {
var nScope;
if(this.$.fnc){
nScope = this.getValue();
}else{
nScope = this.$.scope.$[k];
}
// if keys are left and has value && is bindable
// get value for first child
if (nScope && (nScope instanceof EventDispatcher)) {
// init new binding, which triggers this binding
this.$subBinding = new Binding({scope: nScope, path: keys.join("."), target: this.$.target, targetKey: this.$.targetKey, rootScope: this.$.rootScope, callback: this.$.callback});
}
}
},
_revCallback: function (e) {
this.$.scope.set(this.$.path, this.$.transformBack(e.$, this.$.target));
},
_callback: function () {
// remove subBindings!
if (this.$subBinding) {
this.$subBinding.destroy();
this.$subBinding = null;
}
// try to create subBinding
this._createSubBinding();
this.trigger();
},
destroy: function () {
this.$.scope.unbind(this.$.event, this._callback);
if (this.$.twoWay === true) {
this.$.target.unbind(this.$.targetEvent, this._revCallback);
}
if (this.$subBinding) {
this.$subBinding.destroy();
}
// destroy parameter bindings
for (var i = 0; i < this.$parameters.length; i++) {
var par = this.$parameters[i];
if(par instanceof Binding){
par.destroy();
}
}
},
getValue: function(){
if(this.$subBinding){
return this.$subBinding.getValue();
}else{
if(this.$.fnc){
var parameters = [];
for (var i = 0; i < this.$parameters.length; i++) {
var para = this.$parameters[i];
if(para instanceof Binding){
para = para.getValue();
}
parameters.push(para);
}
return this.$.fnc.apply(this.$.scope,parameters);
}else if(this.$.path == this.$.key){
return this.$.scope.get(this.$.key);
}else{
return null;
}
}
},
// trigger
trigger: function(){
// get value
var val = this.getValue();
if(this.$.targetKey){
this.$.target.set(this.$.targetKey, this.$.transform(val, this.$.rootScope));
}else if(this.$.callback){
this.$.callback.call(this.$.target,this.$.transform(val, this.$.rootScope));
}
}
});
var $bindingRegex= /^((?:\{{2}(.+)\}{2})|(?:\{(.+)\}))$/i;
var $twoWayBindingRegex= /^\{{2}([a-z_$\}][\(\)a-z0-9$\-_.,\{]*)\}{2}$/i;
var $fncRegex = /^([a-z$_]\w*)\((.*)\)$/i;
var $fncNameRegex = /^(\w+)\(.*\)$/;
Binding.matches = function(attrValue){
return $bindingRegex.test(attrValue);
};
Binding.create = function(bindingDef, targetScope, attrKey){
var cb;
if(rAppid._.isFunction(attrKey)){
cb = attrKey;
}
var match = bindingDef.match($bindingRegex);
var path = match[2] ? match[2] : match[3];
var scopeKey = splitFirst(path);
var scope;
if($fncRegex.test(scopeKey)){
match = scopeKey.match($fncNameRegex);
scope = targetScope.getScopeForFncName(match[1]);
}else{
scope = targetScope.getScopeForKey(scopeKey);
}
if(scope && (scope != targetScope || attrKey != scopeKey)){
var twoWay = !rAppid._.isUndefined(match[2]);
var options = {scope:scope, path:path, target:targetScope, twoWay: twoWay};
if(cb){
options['callback'] = cb;
}else{
options['targetKey'] = attrKey;
}
return new Binding(options);
}
return null;
};
return Binding;
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.Content", ["js.core.Component"], function (Component) {
return Component.inherit(({
// TODO
}));
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.Element",
["js.core.Bindable"], function (Bindable) {
var undef;
function stringToPrimitive(str) {
// if it's not a string
if (rAppid._.isString(str)) {
var n = parseFloat(str);
if (!rAppid._.isNaN(n)) {
return n;
}
if (str === "true") {
return true;
} else if (str === "false") {
return false;
}
}
return str;
}
return Bindable.inherit({
ctor: function (attributes, descriptor, applicationDomain, parentScope, rootScope) {
attributes = attributes || {};
if (!descriptor) {
// created from node
if (!rootScope) {
rootScope = this;
}
}
this.$descriptor = descriptor;
this.$applicationDomain = applicationDomain;
this.$parentScope = parentScope || null;
this.$rootScope = rootScope || null;
rAppid._.extend(attributes, this._getAttributesFromDescriptor(descriptor), this._getAttributesFromDescriptor(this._$descriptor));
this.callBase(attributes);
this._initializeAttributes(this.$);
// manually constructed
if (descriptor === undef || descriptor === null) {
this._initialize(this.$creationPolicy);
}
},
_getAttributesFromDescriptor: function (descriptor) {
var attributes = {};
if (descriptor && descriptor.attributes) {
var node;
for (var a = 0; a < descriptor.attributes.length; a++) {
node = descriptor.attributes[a];
attributes[node.nodeName] = stringToPrimitive(node.value);
}
}
return attributes;
},
defaults: {
creationPolicy: "auto"
},
_initializeAttributes: function (attributes) {
},
_initializeDescriptors: function () {
},
/**
*
* @param creationPolicy
* auto - do not overwrite (default),
* all - create all children
* TODO none?
*/
_initialize: function (creationPolicy, withBindings) {
if (this.$initialized) {
return;
}
this._preinitialize();
this.initialize();
this._initializeDescriptors();
if (this == this.$rootScope || withBindings) {
this._initializeBindings();
}
this._initializationComplete();
},
_initializeBindings: function () {
},
_initializeDescriptor: function (descriptor) {
},
initialize: function () {
},
find: function (key) {
var scope = this.getScopeForKey(key);
if (this == scope) {
return this.callBase();
} else if (scope != null) {
return scope.get(key);
} else {
return null;
}
},
getScopeForKey: function (key) {
// try to find value for first key
var value = this.$[key];
// if value was found
if (!rAppid._.isUndefined(value)) {
return this;
} else if (this.$parentScope) {
return this.$parentScope.getScopeForKey(key);
} else {
return null;
}
},
getScopeForFncName: function(fncName){
var fnc = this[fncName];
if(!rAppid._.isUndefined(fnc) && rAppid._.isFunction(fnc)){
return this;
} else if(this.$parentScope){
return this.$parentScope.getScopeForFncName(fncName);
} else {
return null;
}
},
_preinitialize: function () {
},
_initializationComplete: function () {
this.$initialized = true;
},
_getTextContentFromDescriptor:function (desc) {
return desc.textContent ? desc.textContent : desc.text;
}
});
}
);
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
var a = 0;
rAppid.defineClass("js.core.EventDispatcher",
["js.core.Base"],
/**
* Base class for trigger and listen to events
* @export js/core/EventDispatcher
*/
function (Base) {
Function.prototype.on = function () {
var events = Array.prototype.slice.call(arguments, 0);
this._events = [];
for (var i = 0; i < events.length; i++) {
var event = events[i];
this._events.push(event);
}
return this;
};
Function.prototype.onChange = function () {
var events = Array.prototype.slice.call(arguments, 0);
this._events = [];
for (var i = 0; i < events.length; i++) {
var event = events[i];
event = "change:" + event;
this._events.push(event);
}
return this;
};
var undefinedValue;
var EventDispatcher = Base.inherit({
ctor: function () {
this.callBase();
this._eventHandlers = {};
},
bind: function (eventType, callback, scope) {
scope = scope || this;
// get the list for the event
var list = this._eventHandlers[eventType] || (this._eventHandlers[eventType] = []);
// and push the callback function
list.push(new EventDispatcher.EventHandler(callback, scope));
return this;
},
/**
*
* @param {String} eventType
* @param {js.core.EventDispatcher.Event|Object} event
* @param caller
*/
trigger: function (eventType, event, caller) {
if (this._eventHandlers[eventType]) {
if (!(event instanceof EventDispatcher.Event)) {
event = new EventDispatcher.Event(event);
}
if (!caller) {
caller = arguments.callee.caller;
}
event.type = eventType;
var list = this._eventHandlers[eventType];
for (var i = 0; i < list.length; i++) {
if (list[i]) {
var result = list[i].trigger(event, caller);
if (result !== undefinedValue) {
ret = result;
if (result === false) {
event.preventDefault();
event.stopPropagation();
}
}
if (event.isImmediatePropagationStopped) {
break;
}
}
}
}
return event;
},
unbind: function (eventType, callback) {
if (!eventType) {
// remove all events
this._eventHandlers = {};
} else if (!callback) {
// remove all callbacks for these event
this._eventHandlers[eventType] = [];
} else if (this._eventHandlers[eventType]) {
var list = this._eventHandlers[eventType];
for (var i = list.length - 1; i >= 0; i--) {
if (list[i].$callback == callback) {
list.splice(i, 1); // delete callback
}
}
}
}
});
EventDispatcher.Event = Base.inherit({
ctor: function (attributes) {
this.$ = attributes;
this.isDefaultPrevented = false;
this.isPropagationStopped = false;
this.isImmediatePropagationStopped = false;
},
preventDefault: function () {
this.isDefaultPrevented = true;
var e = this.orginalEvent;
if (e) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false; // IE
}
}
},
stopPropagation: function () {
this.isPropagationStopped = true;
var e = this.originalEvent;
if (e) {
if (e.stopPropagation) {
e.stopPropagation();
}
e.cancelBubble = true;
}
},
stopImmediatePropagation: function () {
this.isImmediatePropagationStopped = true;
this.stopPropagation();
}
});
EventDispatcher.EventHandler = Base.inherit({
ctor: function (callback, scope) {
this.scope = scope;
this.$callback = callback;
},
trigger: function (event, caller) {
this.$callback.call(this.scope, event, caller);
}
});
return EventDispatcher;
}
);
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.History", ["js.core.Bindable"], function (Bindable) {
var routeStripper = /^#\/?/,
undef;
return Bindable.inherit({
ctor: function () {
this.callBase();
this.$routers = [];
this.processUrl = true;
},
defaults: {
interval: 50
},
getFragment: function (fragment) {
fragment = decodeURIComponent(fragment || window.location.hash);
return fragment.replace(routeStripper, '');
},
start: function () {
var self = this;
this.$checkUrlFn = function () {
self.checkUrl.apply(self, arguments);
};
if ("onhashchange" in window) {
if (window.addEventListener) {
window.addEventListener('hashchange',
this.$checkUrlFn, false);
} else {
window.attachEvent('onhashchange', this.$checkUrlFn);
}
} else {
// polling
this.$checkUrlInterval = setInterval(this.$checkUrlFn, this.$.interval);
}
this.fragment = this.getFragment();
this.navigate(this.fragment);
},
stop: function () {
if ("onhashchange" in window) {
if (window.removeEventListener) {
window.removeEventListener('hashchange',
this.$checkUrlFn, false);
} else {
window.detachEvent('onhashchange', this.$checkUrlFn);
}
} else {
// polling
clearInterval(this.$checkUrlInterval);
}
},
addRouter: function (router) {
this.$routers.push(router);
},
checkUrl: function (e) {
if (this.processUrl) {
var currentFragment = this.getFragment();
if (currentFragment == this.fragment) {
return false;
}
}
this.processUrl = true;
},
triggerRoute: function (fragment) {
for (var i = 0; i < this.$routers.length; i++) {
if (this.$routers[i].executeRoute(fragment)) {
return true;
}
}
console.log("no route for '" + fragment + "' found.");
},
navigate: function (fragment, createHistoryEntry, triggerRoute) {
if (createHistoryEntry == undef || createHistoryEntry == null) {
createHistoryEntry = true;
}
if (triggerRoute == undef || triggerRoute == null) {
triggerRoute = true;
}
this.processUrl = false;
if (createHistoryEntry) {
window.location.hash = "/" + fragment;
} else {
// replace hash
window.location.replace("#/" + fragment);
}
this.fragment = fragment;
if (triggerRoute) {
return this.triggerRoute(fragment);
}
}
});
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.I18n", ["js.core.Component"], function(Component) {
return Component.inherit({
defaults: {
path: 'app/locale',
locale: null,
suffix: '.json',
translations: {}
},
initialize: function() {
this.callBase();
this.loadLocale(this.$.locale);
},
_commitChangedAttributes: function(attributes) {
if (attributes.locale) {
this.loadLocale(attributes.locale);
}
},
loadLocale: function(locale, callback) {
if (!locale) {
throw "locale not defined";
}
var self = this;
rAppid.require(['json!' + this.$.path + '/' + this.$.locale + this.$.suffix], function (translations) {
if (callback) {
callback();
}
self.set({
translations: translations
});
});
},
/**
* @param [num] for plural or singular
* @param key translation key
* @param - replacement for %0
* @param - replacement for %1 ...
*/
translate: function() {
var args = Array.prototype.slice.call(arguments);
var key = args.shift(), isPlural;
if(rAppid._.isNumber(key)){
isPlural = key !== 1;
key = args.shift();
}
if(isPlural){
key += "_plural";
}
var value = this.$.translations[key] || "";
for (var i = 0; i < args.length; i++) {
// replace, placeholder
value = value.split("%" + i).join(args[i]);
}
return value;
}.onChange("translations")
})
})
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.Imports", ["js.core.Element"], function (Component) {
return Component.inherit({
});
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.Injection", ["js.core.Component"], function (Component) {
var singleton;
function factoryInheritsFrom(factory, type) {
return factory == type || factory.prototype instanceof type;
}
return Component.inherit({
ctor: function () {
if (!singleton) {
this.callBase();
this.$singletonInstanceCache = [];
this.$factories = [];
singleton = this;
}
return singleton;
},
_childrenInitialized: function () {
this.callBase();
for (var c = 0; c < this.$configurations.length; c++) {
var config = this.$configurations[c];
if (config.className == "js.conf.Factory") {
this.addFactory(config.$);
}
}
},
getInstance: function (type) {
// TODO: add class hierarchy distance check
var instance;
// go to the singleton instance and look for requested instance
for (var i = 0; i < this.$singletonInstanceCache.length; i++) {
instance = this.$singletonInstanceCache[i];
if (instance instanceof type) {
return instance;
}
}
// instance not found -> go thought the factories
for (var f = 0; f < this.$factories.length; f++) {
var factory = this.$factories[f];
if (factoryInheritsFrom(factory.factory, type)) {
// create instance
instance = new factory.factory();
if (instance instanceof type) {
if (factory.singleton) {
this.addInstance(instance)
}
return instance;
}
}
}
throw "requested injection type not found";
},
addChild: function (child) {
this.addInstance(child);
},
addFactory: function (factory) {
if (factory instanceof Function) {
factory = {
factory: factory
}
}
rAppid._.defaults(factory, {
"type": null,
"factory": null,
"singleton": false
});
if (!factory.factory) {
// get factory from class
var fac = this.$applicationDomain.getDefinition(factory.type);
if (!fac) {
throw "factory for type '" + factory.type + "' not found";
}
factory.factory = fac;
}
this.$factories.push(factory);
},
addInstance: function (instance) {
if (instance instanceof Function) {
throw "got a factory instead of an instance"
}
this.$singletonInstanceCache.push(instance);
}
});
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.List", ["js.core.EventDispatcher","js.core.Bindable"], function(EventDispatcher, Bindable) {
return EventDispatcher.inherit({
ctor: function(items){
this.$items = [];
this.callBase();
if(items){
this.add(items);
}
var self = this;
this.bind('add', function () {
self.length = self.size();
});
this.bind('remove', function () {
self.length = self.size();
});
this.length = this.size();
},
hasItems: function(){
return this.$items.length > 0;
}.on("add","remove"),
push: function(item){
// TODO: add options
this.$items.push(item);
this.trigger('add', {item:item, index:this.$items.length-1});
},
pop: function(){
// TODO: add options
return this.removeAt(this.$items.length);
},
shift: function(){
// TODO: add options
return this.removeAt(0);
},
unshift: function(item){
// TODO: add options
this.$items.unshift(item);
this.trigger('add', {item:item, index: 0});
},
add: function(items, options){
options = options || {};
rAppid._.defaults(options, {silent:false, index:this.$items.length});
var index = options.index;
if(!rAppid._.isArray(items)){
items = [items];
}
var item, itemIndex;
for(var i = 0; i < items.length; i++){
item = items[i];
if(item instanceof Bindable){
item.bind('change',this._onItemChange,this);
}
itemIndex = index+i;
this.$items.splice(itemIndex,0,item);
if(options.silent !== true){
this.trigger('add', {item:item, index:itemIndex})
}
}
},
_onItemChange: function(e,item){
this.trigger('change',{item: item, index: this.$items.indexOf(item)});
},
remove: function(items, options){
if(!rAppid._.isArray(items)){
items = [items];
}
for(var i = 0 ; i < items.length; i++){
this.removeAt(this.$items.indexOf(items[i]),options);
}
},
removeAt: function(index,options){
options = options || {};
if(index > -1 && index < this.$items.length){
var items = this.$items.splice(index,1);
if(options.silent !== true){
this.trigger('remove', {item:items[0], index:index});
}
return items[0];
}
return null;
},
reset: function(items){
this.$items = items;
this.trigger('reset',{items: items});
},
sort: function(fnc){
this.trigger('sort', {items: this.$items.sort(fnc)});
},
clear: function(){
this.reset([]);
},
size: function(){
return this.$items.length;
}.on('add','remove')
,
at: function(index){
if(index < this.$items.length && index >= 0){
return this.$items[index];
}
return null;
},
each: function(fnc,scope){
scope = scope || this;
for(var i = 0; i < this.$items.length; i++){
fnc.call(scope,this.$items[i],i);
}
}
})
})
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.Module", ["js.core.UIComponent"], function (UIComponent) {
return UIComponent.inherit({
/**
* loads the
* @param callback
*/
start: function (callback) {
},
render: function (target) {
}
});
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.ModuleLoader", ["js.core.UIComponent", "js.ui.ContentPlaceHolder",
"require", "js.core.Module"],
function (UIComponent, ContentPlaceHolder, require, Module) {
var ModuleLoader = UIComponent.inherit({
ctor: function (attributes) {
this.callBase();
this.$modules = {};
},
addChild: function (child) {
this.callBase();
if (child && child.className == "js.conf.Module") {
this.addModule(child.$);
}
},
addModule: function (module) {
rAppid._.defaults(module, {
name: null,
moduleClass: null,
route: null,
cacheInstance: true
});
if (!module.name && !module.route) {
throw "module cannot be added: route or at least name is required";
}
if (!module.moduleClass) {
throw "no moduleClass defined for module";
}
if (module.name) {
if (this.modules.hasOwnProperty(module.name)) {
throw "module with name '" + module.name + "' already registered"
}
this.modules[module.name] = module;
}
if (module.route) {
if (!this.$.router) {
throw "defining modules with routes requires a router instance to be set"
}
var self = this;
this.$.router.route(module.name, module.route, function () {
// route triggered
// load module
if (module.name) {
self.loadModuleByName(module.name, null);
} else {
self.loadModule(module.moduleClass, null);
}
});
}
},
loadModuleByName: function (moduleName, callback) {
if (this.modules.hasOwnProperty(moduleName)) {
var module = this.modules[moduleName];
if (module.cacheInstance && module.moduleInstance) {
// TODO: load instance from cache
} else {
this.loadModule(module.moduleClass, callback);
}
} else {
throw "Module '" + moduleName + "' not found";
}
},
loadModule: function (moduleFqClassName, callback) {
var eventResult = this.trigger("loadModule", {
moduleClass: moduleFqClassName
});
var internalCallback = function (err) {
// TODO Dispatch events
if (callback) {
callback(err);
}
};
var self = this;
if (!eventResult.isDefaultPrevented) {
// load module
require.require([moduleFqClassName], function (moduleBaseClass) {
var moduleInstance = new moduleBaseClass(null, moduleBaseClass.prototype._$descriptor, self.$applicationDomain, null, null);
if (moduleInstance instanceof Module) {
moduleInstance._initialize("auto");
internalCallback(null);
// TODO: show and start module
} else {
internalCallback("Module '" + moduleFqClassName + "' isn't an instance of js.core.Module");
}
});
// TODO cache model instances
// Trigger events
}
},
removeChild: function (child) {
this.callBase();
var index = this.$modules.indexOf(child);
if (index != -1) {
// TODO: remove route from router
}
},
render: function () {
// render the ContentPlaceHolder
this.callBase();
},
getContentPlaceHolders: function () {
return ModuleLoader.findContentPlaceHolders(this);
}
});
ModuleLoader.findContentPlaceHolders = function (component) {
var ret = [];
for (var i = 0; i < component.$children.length; i++) {
var child = component.$children[i];
if (child instanceof ContentPlaceHolder) {
ret.push(child);
} else {
ret.concat(ModuleLoader.findContentPlaceHolders(child));
}
}
return ret;
};
return ModuleLoader;
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.Router", ["js.core.Component"],
function (Component) {
return Component.inherit({
ctor: function () {
this.$routes = [];
this.callBase();
},
initialize: function () {
this.callBase();
if (this.$.history) {
this.history = this.$.history;
} else {
this.history = rAppid.systemManager.application.history;
}
this.history.addRouter(this);
},
/**
*
* @param {Regexp|Object} route
* @param {Function} [fn]
*/
addRoute: function () {
var route;
if (arguments.length == 2) {
route = {
regex: arguments[0],
fn: arguments[1]
}
} else {
route = arguments[0];
}
rAppid._.defaults(route, {
name: null,
regex: null,
fn: null
});
if (!(route.fn && route.regex)) {
throw "fn and regex required"
}
this.$routes.push(route);
},
executeRoute: function (fragment) {
// Test routes and call callback
for (var i = 0; i < this.$routes.length; i++) {
var route = this.$routes[i];
var params = route.regex.exec(fragment);
if (params) {
params.shift();
route.fn.apply(this, params);
return true;
}
}
return false;
},
/**
* shortcut to history.navigate
* @param to
* @param createHistoryEntry
* @param triggerRoute
*/
navigate: function (to, createHistoryEntry, triggerRoute) {
return this.history.navigate(to, createHistoryEntry, triggerRoute);
}
});
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.Script", ["js.core.Element"], function (El) {
return El.inherit({
// all the crazy stuff is done in xaml.js
evaluate: function (imports) {
var textContent = this.$descriptor.textContent ? this.$descriptor.textContent : this.$descriptor.text;
var fn = eval("this.javascript = (" + textContent + ")");
return fn.apply(this, imports);
}
});
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.Template", ["js.core.Component"],
function (Component) {
// this is because circular dependency
return Component.inherit({
_initializeDescriptors: function () {
this._childrenInitialized();
},
createComponents: function (attributes, parentScope, rootScope) {
rootScope = rootScope || this.$rootScope;
parentScope = parentScope || this.$parentScope;
// foreach child Descriptor
var components = this._getChildrenFromDescriptor(this.$descriptor);
for (var c = 0; c < components.length; c++) {
components[c].$parentScope = parentScope;
components[c].$rootScope = rootScope;
components[c].set(attributes);
components[c]._initialize("auto", true);
}
return components
}
});
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.TextElement",
["js.core.Element", "js.core.Binding"], function (Element, Binding) {
var bindingRegEx = /\{(([^{]*\{[^{}]*\})|[^{}])*?}/g;
return Element.inherit({
_initializeBindings: function () {
this.$textBindings = {};
var textContent = this._getTextContentFromDescriptor(this.$descriptor);
// find bindings and register for onchange event
var key, match, binding;
while (match = bindingRegEx.exec(textContent)) {
key = match[0];
if(Binding.matches(key)){
binding = Binding.create(key, this, key);
if(binding){
this.$textBindings[key] = binding;
this.$[key] = this.$textBindings[key].getValue();
}else{
throw "could not create binding for " + key;
}
}
}
},
render: function () {
if (!this.$initialized) {
this._initialize(this.$creationPolicy);
}
this.$el = document.createTextNode("");
if (this.$descriptor) {
this._renderTextContent(this._getTextContentFromDescriptor(this.$descriptor));
}
return this.$el;
},
_renderTextContent: function (textContent) {
for(var key in this.$textBindings){
if(this.$textBindings.hasOwnProperty(key)){
var val = this.$textBindings[key].getValue();
if(rAppid._.isUndefined(val) || val == null){
val = "";
}
textContent = textContent.split(key).join(val);
}
}
if(this.$el.textContent){
this.$el.textContent = textContent;
}else{
this.$el.nodeValue = textContent;
}
},
_commitChangedAttributes: function () {
if (this.$el && this.$descriptor) {
this._renderTextContent(this._getTextContentFromDescriptor(this.$descriptor));
}
}
});
}
);
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.core.UIComponent",
["js.html.DomElement"], function (DomElement) {
return DomElement.inherit({
defaults: {
tagName: "div"
},
$behavesAsDomElement: false
});
}
);
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.data.Collection", ["js.core.List", "js.data.Model"], function (List, Model) {
var Collection = List.inherit({
ctor: function(items, options) {
this.callBase(items);
rAppid._.defaults(options, {
rootCollection: null,
chunkSize: null,
queryParameters: {},
factory: Model,
type: null
});
this.$queryCollectionsCache = {};
this.$options = options;
},
getRootCollection: function() {
return this.$options.rootCollection ? this.$options.rootCollection : this;
},
createQueryCacheKey: function(queryParameters) {
queryParameters = queryParameters || {};
var ret = [];
for (var key in queryParameters) {
if (queryParameters.hasOwnProperty(key)) {
ret.push(key + "=" + queryParameters[key]);
}
}
ret.sort();
if (ret.length == 0) {
return "root";
}
return ret.join("&");
},
createQueryCollection: function(queryParameter) {
var options = {
queryParameter: queryParameter,
rootCollection: this.getRootCollection
};
// different queryParameter, same options
rAppid._.defaults(options, this.$options);
return new Collection(null, options);
},
// fetches the complete list
fetch: function(options, callback) {
options = options || {};
},
// returns a new collections
find: function(parameters) {
var queryKey = this.createQueryCacheKey(parameters);
if (!this.$queryCollectionsCache.hasOwnProperty(queryKey)) {
this.$queryCollectionsCache[queryKey] = this.createQueryCollection(parameters);
}
return this.$queryCollectionsCache[queryKey];
}
});
return Collection;
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.data.DataSource",
["js.core.Component", "js.core.Base", "js.data.Collection"],
function (Component, Base, Collection) {
var Context = Base.inherit({
ctor: function (datasource, properties, parentContext) {
this.callBase();
this.$datasource = datasource;
this.$properties = properties;
this.$parent = parentContext;
this.$cache = {};
},
addModelToCache: function (model) {
this.$cache[Context.generateCacheIdFromModel(model)] = model;
},
addCollectionToCache: function (collection) {
this.$cache[Context.generateCacheIdFromCollection(collection)] = collection;
},
getInstanceByCacheId: function (cacheId) {
return this.$cache[cacheId];
},
createModel: function (factory, id, type) {
if (rAppid._.isFunction(factory)) {
type = type || factory.prototype.constructor.name;
var cachedItem = this.getInstanceByCacheId(Context.generateCacheId(type));
if (!cachedItem) {
// create new Collection
cachedItem = new factory({
id: id
});
// set context
cachedItem.$context = this;
cachedItem.className = type;
// and add it to the cache
this.addModelToCache(cachedItem);
}
return cachedItem;
} else {
throw "Factory has to be a function";
}
},
createCollection: function (factory, options, type) {
options = options || {};
if (rAppid._.isFunction(factory)) {
type = type || factory.prototype.constructor.name;
rAppid._.defaults(options, {
factory: factory,
type: type
});
var cachedCollection = this.getInstanceByCacheId(Context.generateCacheId(type));
if (!cachedCollection) {
// create new Collection
cachedCollection = new Collection(null, options);
// set context
cachedCollection.$context = this;
cachedCollection.className = type;
// and add it to the cache
this.addCollectionToCache(cachedCollection);
}
return cachedCollection;
} else {
throw "Factory has to be a function";
}
}
});
Context.generateCacheId = function (type, id) {
if (id) {
return type + "_" + id;
} else {
return type;
}
};
Context.generateCacheIdFromModel = function (model) {
return Context.generateCacheId(model.className, model.$.id);
};
Context.generateCacheIdFromCollection = function (collection) {
return Context.generateCacheId(collection.className);
};
var DataSource = Component.inherit({
ctor: function () {
this.callBase();
this.$configuredTypes = [];
this.$contextCache = {};
},
_childrenInitialized: function () {
this.callBase();
for (var c = 0; c < this.$configurations.length; c++) {
var config = this.$configurations[c];
if (config.className == "js.conf.Type") {
this.addTypeConfiguration(config);
}
}
},
addTypeConfiguration: function (configuration) {
if (!configuration.$.className && !configuration.$.alias) {
throw "neither className nor alias defined";
}
if (configuration.$.className && !configuration.$.alias) {
configuration.$.alias = configuration.$.className.split(".").pop();
}
if (!configuration.$.className) {
configuration.$.className = "js.data.Model";
}
this.$configuredTypes.push(configuration);
},
getFqClassName: function (alias) {
for (var i = 0; i < this.$configuredTypes.length; i++) {
var typeConfig = this.$configuredTypes[i];
if (typeConfig.$.alias == alias) {
return typeConfig.$.className;
}
}
},
getModelClassNameForAlias: function (alias) {
var fqClassname = this.getFqClassName(alias) || alias;
if (fqClassname == "js.data.Model") {
return alias;
}
return fqClassname;
},
getContext: function (properties, parentContext) {
var cacheId = this.createContextCacheId(properties, parentContext ? parentContext.$properties : null);
if (!this.$contextCache.hasOwnProperty(cacheId)) {
this.$contextCache[cacheId] = this.createContext(properties, parentContext);
}
return this.$contextCache[cacheId];
},
/**
* returns the root context
*/
root: function () {
return this.getContext();
},
createContext: function (properties, parentContext) {
return new Context(this, properties, parentContext)
},
createContextCacheId: function (properties, parentProperties) {
var ret = [];
rAppid._.each(rAppid._.extend({}, parentProperties, properties), function (value, key) {
ret.push(key + "=" + value);
});
rAppid._.sortBy(ret, function (value) {
return value;
});
if (ret.length == 0) {
return "root";
}
return ret.join("&");
},
createModel: function (factory, id, type, context) {
context = context || this.getContext();
return context.createModel(factory, id, type);
},
createCollection: function (factory, options, type, context) {
context = context || this.getContext();
return context.createCollection(factory, options, type);
},
/**
* resolve references to models and collections
* @param {js.data.Model} model
* @param {JSON} data deserialized, parsed data
* @param {Object} options
* @param {Function} callback - function (err, resolvedData)
*/
resolveReferences: function (model, data, options, callback) {
if (callback) {
callback("Abstract method", data);
}
},
loadModel: function (model, options, callback) {
if (callback) {
callback("Abstract method", model);
}
},
update: function (data, callback) {
},
remove: function (data, callback) {
},
find: function (data, callback) {
}
});
DataSource.Context = Context;
return DataSource;
});
})
;
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.data.Model", ["js.core.Bindable", "js.core.List", "flow"], function (Bindable, List, flow) {
var cid = 0;
var State = {
CREATED: 0,
LOADING: 1,
LOADED: 2,
ERROR: -1
};
var Model = Bindable.inherit({
ctor: function (attributes) {
this.callBase(attributes);
this.$cid = ++cid;
// stores the current fetch state
this._fetch = {
callbacks: [],
state: State.CREATED
}
},
save: function (options, callback) {
this.$context.$datasource.save(options, callback);
},
/**
* @param options
* @param options.fetchSubModels
*
*
* @param {Function} callback - function(err, model, options)
*/
fetch: function (options, callback) {
options = options || {};
var self = this;
if (this._fetch.state === State.LOADING) {
// currently fetching -> register callback
this._fetch.callbacks.push(function(err, model) {
modelFetchedComplete(err, model, options, callback);
});
} else if (this._fetch.state == State.LOADED) {
// completed loaded -> execute
modelFetchedComplete(null, this, options, callback);
} else {
// set state and start loading
self._fetch.state = State.LOADING;
this.$context.$datasource.loadModel(this, options, function(err, model) {
self._fetch.state = err ? State.ERROR : State.LOADED;
// execute callbacks
modelFetchedComplete(err, model, options, callback);
rAppid._.each(self._fetch.callbacks, function(cb) {
cb(err, model);
});
});
}
},
remove: function (options, callback) {
this.$context.$datasource.remove(options, callback);
},
/**
* prepares the data for serialisation
* @return {Object} all data that should be serialized
*/
prepare: function() {
var ret = {};
for (var key in this.$) {
if (this.$.hasOwnProperty(key)) {
var value = this.$[key];
if (!rAppid._.isFunction(value)) {
ret[key] = value;
}
}
}
return ret;
},
/**
* parse the deserializied data
* @param data
*/
parse: function(data) {
// convert all arrays to List
function convertArrayToList(obj) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
var value = obj[prop];
if (rAppid._.isArray(value)) {
// convert array to js.core.List
obj[prop] = new List(value);
for (var i = 0; i < value.length; i++) {
convertArrayToList(value[i]);
}
} else if (value instanceof Object) {
convertArrayToList(value);
}
}
}
}
convertArrayToList(data);
return data;
},
status: function() {
if (this.$.id === false) {
return "DELETED";
} else {
return this.$.id ? "CREATED" : "NEW";
}
}.on("id")
});
function fetchSubModels(attributes, subModelTypes, delegates) {
rAppid._.each(attributes, function (value) {
if (value instanceof Model) {
// check if the model is required
var subModelTypeEntry = subModelTypes[value.className];
if (subModelTypeEntry) {
// model required -> create delegate
subModelTypeEntry.found = true;
delegates.push(function (cb) {
value.fetch({
fetchSubModels: subModelTypeEntry.subModels
}, cb);
});
}
} else if (value instanceof Object) {
fetchSubModels(value, subModelTypes, delegates);
}
});
}
function modelFetchedComplete(err, model, options, originalCallback) {
var callback = function (err, model) {
if (originalCallback) {
originalCallback(err, model, options)
}
};
if (err) {
callback(err, model);
} else {
var delegates = [];
if (options.fetchSubModels && options.fetchSubModels.length > 0) {
// for example fetch an article with ["currency", "product/design", "product/productType"]
var subModelTypes = createSubModelLoadingChain(model, options.fetchSubModels);
fetchSubModels(model.$, subModelTypes, delegates);
// check that all subResources where found
var missingSubModels = rAppid._.filter(subModelTypes, function (subModel) {
return !subModel.found;
});
if (missingSubModels.length > 0) {
// TODO load again with fullData=true if not laoded with fullData=false
console.log(["requested submodel missing", missingSubModels]);
callback("requested submodel missing", model);
return;
}
}
// execute all delegates in parallel and then execute callback
flow()
.par(delegates)
.exec(function (err) {
callback(err, model);
});
}
}
function createSubModelLoadingChain(model, subModels) {
var ret = {},
subModelParser = /^([\w][\w.]*)(?:\/([\w][\w.]*))?$/;
rAppid._.each(subModels, function (item) {
var parts = subModelParser.exec(item);
if (parts) {
var subModelType = model.$context.$datasource.getModelClassNameForAlias(parts[1]);
var subModelSubType = parts[2];
var subModelTypeEntry = ret[subModelType];
if (!subModelTypeEntry) {
// create an entry
subModelTypeEntry = {
type: subModelType,
found: false,
subModels: []
};
}
// add required subModelTypeStrings
if (subModelSubType) {
subModelTypeEntry.subModels.push(subModelSubType);
}
ret[subModelType] = subModelTypeEntry;
}
});
return ret;
}
return Model;
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.html.Input",
["js.html.DomElement"], function (DomElement) {
return DomElement.inherit({
defaults: {
checked: false
},
_renderValue: function(value){
this.$el.value = value;
},
_renderChecked: function(checked){
this.$el.checked = checked;
},
_bindDomEvents: function(){
var self = this;
if (this.$el.type == "text" || this.$el.type == "password") {
this.addEventListener('change', function (e) {
self.set('value', self.$el.value);
});
} else if (this.$el.type == "checkbox" || this.$el.type == "radio") {
this.addEventListener('click', function (e) {
self.set('checked', self.$el.checked);
});
}
this.callBase();
}
});
}
);
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.html.Option",
["js.html.DomElement"], function (DomElement) {
return DomElement.inherit({
_renderSelected: function(selected){
this.$el.selected = selected;
}
});
}
);
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.html.Select",
["js.ui.SelectionView"], function (SelectionView) {
return SelectionView.inherit({
defaults:{
multiSelect:false,
forceSelectable:false,
tagName:'select'
},
_renderMultiSelect:function (multiSelect) {
this.$el.multiple = multiSelect;
},
_renderSelectedItems:function (items) {
var comp, ri;
// go through items, find option and set selected
for (var i = 0; i < this.$renderedItems.length; i++) {
ri = this.$renderedItems[i];
comp = ri.component;
comp.set({selected: rAppid._.contains(items, ri.item)});
}
},
_bindDomEvents:function () {
var self = this;
this.addEventListener('change', function (e) {
self._checkOptions();
});
},
_checkOptions:function () {
for (var i = 0; i < this.$childViews.length; i++) {
this.$childViews[i].set({selected:this.$childViews[i].$el.selected});
}
}
});
}
);
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.html.TextArea",
["js.html.DomElement", "js.core.TextElement"], function (DomElement, TextElement) {
return DomElement.inherit({
_renderChild: function(child){
if(child instanceof TextElement){
// contains two way binding ...
var text = this._getTextContentFromDescriptor(child.$descriptor);
/*
if(this._isBindingDefinition(text)){
this._initBinding(text,"value");
} */
}
},
_renderValue: function(value){
if(Element.textContent){
this.$el.textContent = value;
}else{
this.$el.innerText = value;
}
},
_bindDomEvents: function(){
var self = this;
this.addEventListener('change', function (e) {
self.set('value', e.target ? e.target.value : self.$el.innerText);
});
}
});
}
);
});
\ No newline at end of file
(function () {
var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
var importRegEx = /((?:xaml!)?[a-z]+(\.[a-z]+[a-z0-9]*)*)/mgi;
define(function () {
return {
version: '0.1.0',
createXhr: function () {
var xhr, i, progId;
if (typeof XMLHttpRequest !== "undefined") {
return new XMLHttpRequest();
} else {
for (i = 0; i < 3; i++) {
progId = progIds[i];
try {
xhr = new ActiveXObject(progId);
} catch (e) {
}
if (xhr) {
progIds = [progId]; // so faster next time
break;
}
}
}
if (!xhr) {
throw new Error("createXhr(): XMLHttpRequest not available");
}
return xhr;
},
get: function (url, callback) {
var xhr;
try {
xhr = this.createXhr();
xhr.open('GET', url, true);
xhr.onreadystatechange = function (evt) {
//Do not explicitly handle errors, those should be
//visible via console output in the browser.
if (xhr.readyState === 4) {
callback(null, xhr);
}
};
xhr.send(null);
} catch (e) {
callback(e);
}
},
load: function (name, req, onLoad, config) {
var jsonParse = (typeof JSON !== 'undefined' && typeof JSON.parse === 'function') ? JSON.parse : function (val) {
return eval('(' + val + ')');
};
this.get(name, function (err, xhr) {
if (!err) {
onLoad(jsonParse(xhr.responseText));
} else {
throw err;
}
});
}
};
});
}());
\ No newline at end of file
This diff is collapsed.
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.ui.Button",
["xaml!js.ui.Link", "js.core.Content"], function (Link) {
return Link.inherit({
defaults: {
'componentClass': 'btn'
},
_renderType: function (type, oldType) {
if (oldType) {
this.removeClass("btn-" + oldType);
}
if (type) {
this.addClass("btn-" + type);
}
}
});
}
);
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.ui.Button",
["xaml!js.ui.Link", "js.core.Content"], function (Link) {
return Link.inherit({
defaults: {
'tagName': 'label',
'componentClass': 'checkbox'
},
_renderLabel: function (label) {
}
});
}
);
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.ui.ContentPlaceHolder", ["js.ui.View"], function (View) {
return View.inherit(({
_renderContent: function (content) {
if (content) {
this._renderChildren(content.$children);
} else {
var cv;
for(var i = 0 ; i < this.$childViews.length; i++){
cv = this.$childViews[i];
this.$el.removeChild(cv.$el);
}
}
}
}));
});
});
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment