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
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
font-family: inherit;
vertical-align: baseline;
}
body {
line-height: 1;
color: black;
background: white;
}
ol, ul {
list-style: none;
}
a img {
border: none;
}
html {
background: #eeeeee;
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.4em;
background: #eeeeee;
color: #333333;
}
#todoapp {
width: 480px;
margin: 0 auto 40px;
background: white;
padding: 20px;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
}
#todoapp h1 {
font-size: 36px;
font-weight: bold;
text-align: center;
padding: 20px 0 30px 0;
line-height: 1;
}
#create-todo {
position: relative;
}
#create-todo input {
width: 466px;
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
padding: 6px;
border: 1px solid #999999;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
}
#create-todo span {
position: absolute;
z-index: 999;
width: 170px;
left: 50%;
top: 50px;
margin-left: -85px;
}
#todo-list {
margin-top: 10px;
}
#todo-list li {
padding: 12px 20px 11px 0;
position: relative;
font-size: 24px;
line-height: 1.1em;
border-bottom: 1px solid #cccccc;
}
#todo-list li:after {
content: "\0020";
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden;
}
#todo-list li.editing {
padding: 0;
border-bottom: 0;
}
#todo-list .editing .display,
#todo-list .edit {
display: none;
}
#todo-list .editing .edit {
display: block;
}
#todo-list .editing input {
width: 444px;
font-size: 24px;
font-family: inherit;
margin: 0;
line-height: 1.6em;
border: 0;
outline: none;
padding: 4px 7px 0px 27px;
border: 1px solid #999999;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
}
#todo-list .check {
position: relative;
top: 9px;
margin: 0 10px 0 7px;
float: left;
}
#todo-list .done .todo-content {
text-decoration: line-through;
color: #777777;
}
#todo-list .todo-destroy {
position: absolute;
right: 5px;
top: 14px;
display: none;
cursor: pointer;
width: 20px;
height: 20px;
background: url(destroy.png) no-repeat 0 0;
}
#todo-list li:hover .todo-destroy {
display: block;
}
#todo-list .todo-destroy:hover {
background-position: 0 -20px;
}
#todo-stats {
*zoom: 1;
margin-top: 10px;
color: #777777;
}
#todo-stats:after {
content: "\0020";
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden;
}
#todo-stats .todo-count {
float: left;
}
#todo-stats .todo-count .number {
font-weight: bold;
color: #333333;
}
#todo-stats .todo-clear,
#todo-stats .todo-sort {
float: right;
}
#todo-stats .todo-sort {
margin-left: 5px;
}
#todo-stats .todo-clear a,
#todo-stats .todo-sort a {
color: #777777;
font-size: 12px;
}
#todo-stats .todo-clear a:visited {
color: #777777;
}
#todo-stats .todo-clear a:hover {
color: #336699;
}
#instructions {
width: 520px;
margin: 10px auto;
color: #777777;
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
text-align: center;
}
#instructions a {
color: #336699;
}
#credits {
width: 520px;
margin: 30px auto;
color: #999;
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
text-align: center;
}
#credits a {
color: #888;
}
/*
* François 'cahnory' Germain
*/
.ui-tooltip, .ui-tooltip-top, .ui-tooltip-right, .ui-tooltip-bottom, .ui-tooltip-left {
color: #ffffff;
cursor: normal;
display: -moz-inline-stack;
display: inline-block;
font-size: 12px;
font-family: arial;
padding: .5em 1em;
position: relative;
text-align: center;
text-shadow: 0 -1px 1px #111111;
-webkit-border-top-left-radius: 4px;
-webkit-border-top-right-radius: 4px;
-webkit-border-bottom-right-radius: 4px;
-webkit-border-bottom-left-radius: 4px;
-khtml-border-top-left-radius: 4px;
-khtml-border-top-right-radius: 4px;
-khtml-border-bottom-right-radius: 4px;
-khtml-border-bottom-left-radius: 4px;
-moz-border-radius-topleft: 4px;
-moz-border-radius-topright: 4px;
-moz-border-radius-bottomright: 4px;
-moz-border-radius-bottomleft: 4px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom-left-radius: 4px;
-o-box-shadow: 0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
-moz-box-shadow: 0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
-khtml-box-shadow: 0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
-webkit-box-shadow: 0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
box-shadow: 0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
background-color: #3b3b3b;
background-image: -moz-linear-gradient(top, #555555, #222222);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #555555), color-stop(1, #222222));
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr = #555555, EndColorStr = #222222);
-ms-filter: progid: DXImageTransform . Microsoft . gradient(startColorStr = #555555, EndColorStr = #222222);
}
.ui-tooltip:after, .ui-tooltip-top:after, .ui-tooltip-right:after, .ui-tooltip-bottom:after, .ui-tooltip-left:after {
content: "\25B8";
display: block;
font-size: 2em;
height: 0;
line-height: 0;
position: absolute;
}
.ui-tooltip:after, .ui-tooltip-bottom:after {
color: #2a2a2a;
bottom: 0;
left: 1px;
text-align: center;
text-shadow: 1px 0 2px #000000;
-o-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-khtml-transform: rotate(90deg);
-webkit-transform: rotate(90deg);
width: 100%;
}
.ui-tooltip-top:after {
bottom: auto;
color: #4f4f4f;
left: -2px;
top: 0;
text-align: center;
text-shadow: none;
-o-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-khtml-transform: rotate(-90deg);
-webkit-transform: rotate(-90deg);
width: 100%;
}
.ui-tooltip-right:after {
color: #222222;
right: -0.375em;
top: 50%;
margin-top: -.05em;
text-shadow: 0 1px 2px #000000;
-o-transform: rotate(0);
-moz-transform: rotate(0);
-khtml-transform: rotate(0);
-webkit-transform: rotate(0);
}
.ui-tooltip-left:after {
color: #222222;
left: -0.375em;
top: 50%;
margin-top: .1em;
text-shadow: 0 -1px 2px #000000;
-o-transform: rotate(180deg);
-moz-transform: rotate(180deg);
-khtml-transform: rotate(180deg);
-webkit-transform: rotate(180deg);
}
/*the following changes require some cleanup and integration with the above.**/
/* line 9 */
/* line 17 */
#todoapp {
background: white;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
-moz-border-radius-bottomleft: 5px;
-webkit-border-bottom-left-radius: 5px;
-o-border-bottom-left-radius: 5px;
-ms-border-bottom-left-radius: 5px;
-khtml-border-bottom-left-radius: 5px;
border-bottom-left-radius: 5px;
-moz-border-radius-bottomright: 5px;
-webkit-border-bottom-right-radius: 5px;
-o-border-bottom-right-radius: 5px;
-ms-border-bottom-right-radius: 5px;
-khtml-border-bottom-right-radius: 5px;
border-bottom-right-radius: 5px;
}
/* line 24 */
/* line 32 */
#todoapp .content #create-todo {
position: relative;
}
/* line 34 */
#todoapp .content #create-todo input {
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
padding: 6px;
border: 1px solid #999999;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
}
/* line 47 */
#todoapp .content #create-todo span {
position: absolute;
z-index: 999;
width: 170px;
left: 50%;
margin-left: -85px;
}
/* line 55 */
#todoapp .content ul#todo-list {
margin-top: 10px;
}
/* line 57 */
#todoapp .content ul#todo-list li {
padding: 15px 20px 15px 0;
position: relative;
font-size: 24px;
border-bottom: 1px solid #cccccc;
*zoom: 1;
cursor: move;
}
/* line 22, /opt/ree/lib/ruby/gems/1.8/gems/compass-0.10.5/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */
#todoapp .content ul#todo-list li:after {
content: "\0020";
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden;
}
/* line 64 */
#todoapp .content ul#todo-list li.editing {
padding: 0;
border-bottom: 0;
}
/* line 67 */
#todoapp .content ul#todo-list li.editing .todo-input {
display: block;
width: 466px;
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
padding: 6px;
border: 1px solid #999999;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
}
/* line 79 */
#todoapp .content ul#todo-list li.editing .todo-content {
display: none;
}
/* line 81 */
#todoapp .content ul#todo-list li.editing .todo-check {
display: none;
}
/* line 83 */
#todoapp .content ul#todo-list li.editing .todo-destroy {
display: none !important;
}
/* line 85 */
#todoapp .content ul#todo-list li .todo-input {
display: none;
}
/* line 87 */
#todoapp .content ul#todo-list li .todo-check {
position: relative;
top: 6px;
margin: 0 10px 0 7px;
float: left;
}
/* line 93 */
#todoapp .content ul#todo-list li.done .todo-content {
text-decoration: line-through;
color: #777777;
}
/* line 96 */
#todoapp .content ul#todo-list li .todo-destroy {
position: absolute;
right: 0px;
top: 16px;
display: none;
cursor: pointer;
width: 20px;
height: 20px;
}
/* line 106 */
#todoapp .content ul#todo-list li:hover .todo-destroy {
display: block;
}
/* line 109 */
#todoapp #todo-stats {
*zoom: 1;
margin-top: 10px;
color: #555555;
-moz-border-radius-bottomleft: 5px;
-webkit-border-bottom-left-radius: 5px;
-o-border-bottom-left-radius: 5px;
-ms-border-bottom-left-radius: 5px;
-khtml-border-bottom-left-radius: 5px;
border-bottom-left-radius: 5px;
-moz-border-radius-bottomright: 5px;
-webkit-border-bottom-right-radius: 5px;
-o-border-bottom-right-radius: 5px;
-ms-border-bottom-right-radius: 5px;
-khtml-border-bottom-right-radius: 5px;
border-bottom-right-radius: 5px;
background: #f4fce8;
border-top: 1px solid #ededed;
padding: 0 20px;
line-height: 36px;
}
/* line 22, /opt/ree/lib/ruby/gems/1.8/gems/compass-0.10.5/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */
#todoapp #todo-stats:after {
content: "\0020";
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden;
}
/* line 118 */
#todoapp #todo-stats .todo-count {
float: left;
}
/* line 120 */
#todoapp #todo-stats .todo-count .number {
font-weight: bold;
color: #555555;
}
/* line 123 */
#todoapp #todo-stats .todo-clear {
float: right;
}
/* line 125 */
#todoapp #todo-stats .todo-clear a,
#todoapp #todo-stats .todo-sort a{
display: block;
line-height: 20px;
text-decoration: none;
-moz-border-radius: 12px;
-webkit-border-radius: 12px;
-o-border-radius: 12px;
-ms-border-radius: 12px;
-khtml-border-radius: 12px;
border-radius: 12px;
background: rgba(0, 0, 0, 0.1);
color: #555555;
font-size: 11px;
margin-top: 8px;
padding: 0 10px 1px;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
}
/* line 136 */
#todoapp #todo-stats .todo-clear a:hover, #todoapp #todo-stats .todo-clear a:focus {
background: rgba(0, 0, 0, 0.15);
-moz-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
-o-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
}
/* line 139 */
#todoapp #todo-stats .todo-clear a:active {
position: relative;
top: 1px;
}
.language {
text-align: right;
}
.hidden {
display: none;
}
\ No newline at end of file
<!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.Component",
["js.core.Element", "js.core.TextElement", "js.core.Binding"],
function (Element, TextElement, Binding) {
return Element.inherit({
ctor: function (attributes, descriptor, applicationDomain, parentScope, rootScope) {
this.$components = [];
this.$templates = {};
this.$configurations = [];
this.$children = [];
this.callBase();
},
events:[],
/**
* values to be injected
* @key {String} name of the variable for this.$key
* @value {Required Class}
*/
inject: {
},
_injectChain: function () {
return this._generateDefaultsChain("inject");
},
_preinitialize: function () {
this.callBase();
this._inject();
},
_inject: function () {
var inject = this._injectChain();
if (rAppid._.keys(inject).length > 0) {
// we need to inject at least on item
// synchronous singleton instantiation of Injection,
// because if module requires injection, application also depends on
// Injection.js and class should be installed.
var injection = this.$applicationDomain.createInstance("js.core.Injection");
for (var name in inject) {
if (inject.hasOwnProperty(name)) {
this.$[name] = injection.getInstance(inject[name]);
}
}
}
},
addComponent: function (component) {
if (!component) {
throw "component null";
}
this.$components.push(component);
if (this.$rootScope && component.$.cid) {
// register component by cid in the root scope
this.$rootScope.set(component.$.cid, component);
}
},
removeComponent: function (component) {
// TODO: implement and remove cid from rootscope
},
addChild: function (child) {
if (!(child instanceof Element)) {
throw "only children of type js.core.Component can be added"
}
this.addComponent(child);
child.$parent = this;
this.$children.push(child);
},
removeChild: function (child) {
if (!(child instanceof Element)) {
throw "only children of type js.core.Component can be removed"
}
var index = this.$children.indexOf(child);
if (index != -1) {
// child found
child.$parent = null;
this.$children.splice(index, 1);
}
if (this.$templates.hasOwnProperty(child.$.name)) {
// remove it from templates
delete this.$templates[child.$.name];
}
index = this.$children.indexOf(child);
if (index != -1) {
this.$configurations.splice(index, 1);
}
},
addTemplate: function (template) {
if (!template.$.name) {
throw "template without name";
}
this.addComponent(template);
this.$templates[template.$.name] = template;
},
addConfiguration: function (config) {
this.addComponent(config);
this.$configurations.push(config);
},
getTemplate: function (name) {
var tpl = this.$templates[name];
if (tpl) {
return tpl;
} else if (this.$parent && this.$parent != this) {
return this.$parent.getTemplate(name);
} else {
return null
}
},
// /**
// *
// * @param descriptor
// * auto - do not overwrite (default),
// * all - create all children
// * TODO none?
// */
// _initializeDescriptor: function (descriptor) {
// var childrenFromDescriptor = this._createChildrenFromDescriptor(descriptor);
//
// this._initializeChildren(childrenFromDescriptor);
//
// this._childrenInitialized();
// },
_initializeChildren: function (childComponents) {
for (var i = 0; i < childComponents.length; i++) {
// FIRST ADD CHILD
var child = childComponents[i];
if (child.constructor.name == "js.core.Template") {
this.addTemplate(child);
} else if (child.className.indexOf("js.conf") == 0) {
this.addConfiguration(child);
} else {
this.addChild(childComponents[i]);
}
// THEN INITIALIZE !
if (this.$creationPolicy == "auto") {
child._initialize(this.$creationPolicy);
}
}
},
_initializeAttributes: function (attributes) {
this.callBase();
if (this.$creationPolicy != "full") {
if (attributes.hasOwnProperty("creationPolicy")) {
this.$creationPolicy = attributes.creationPolicy;
delete attributes.creationPolicy;
}
}
},
_initializeDescriptors: function () {
var children = [];
var descriptors = [];
// go inherit tree up and search for descriptors
var current = this;
while (current) {
if (current._$descriptor) {
descriptors.unshift(current._$descriptor);
}
current = current.base;
}
// and add outside descriptor
descriptors.push(this.$descriptor);
for (var d = 0; d < descriptors.length; d++) {
children = children.concat(this._getChildrenFromDescriptor(descriptors[d]));
}
this._initializeChildren(children);
this._childrenInitialized();
},
/**
* an array of attributes names, which will expect handler functions
*/
_isEventAttribute:function (attributeName) {
return attributeName.indexOf("on") == 0;
// return this._eventAttributes.hasOwnProperty(attributeName);
},
_isComponentEvent: function(event){
for(var i = 0 ; i < this.events.length; i++){
if(event == this.events[i]){
return true;
}
}
return false;
},
_getEventTypeForAttribute:function (eventName) {
// TODO: implement eventAttribites as hash
return this._eventAttributes[eventName];
},
_initializeBindings: function () {
this.$bindings = [];
this.$eventDefinitions = [];
var attributes = this.$;
var self = this;
var binding, twoWay;
// Resolve bindings and events
for (var key in attributes) {
if (attributes.hasOwnProperty(key)) {
var value = attributes[key];
if (this._isEventAttribute(key)) {
if(this.$rootScope[value]){
this.$eventDefinitions.push({
name:key,
scope:this.$rootScope,
fncName:value
});
if(this._isComponentEvent(key.substr(2))){
this.bind(key,this.$rootScope[value], this.$rootScope);
}
}else{
throw "Couldn't find callback " + value + " for " + key + " event";
}
delete attributes[key];
} else if (Binding.matches(value)) {
binding = Binding.create(value, this, key);
if(binding){
this.$[key] = binding.getValue();
}else{
throw "Binding " + value + " couldn't be created";
}
}
}
}
for (var c = 0; c < this.$components.length; c++) {
this.$components[c]._initializeBindings();
}
},
_createComponentForNode: function (node, attributes) {
attributes = attributes || {};
// only instantiation and construction but no initialization
var appDomain = this.$applicationDomain;
var fqClassName = appDomain.getFqClassName(node.namespaceURI, this._localNameFromDomNode(node), true);
var className = appDomain.getFqClassName(node.namespaceURI, this._localNameFromDomNode(node), false);
return appDomain.createInstance(fqClassName, [attributes, node, appDomain, this, this.$rootScope], className);
},
_createTextElementForNode: function (node) {
// only instantiation and construction but no initialization
var appDomain = this.$applicationDomain;
return appDomain.createInstance("js.core.TextElement", [null, node, appDomain, this, this.$rootScope]);
},
_getChildrenFromDescriptor: function (descriptor) {
var childrenFromDescriptor = [], node, component;
if (descriptor) {
for (var i = 0; i < descriptor.childNodes.length; i++) {
node = descriptor.childNodes[i];
if (node.nodeType == 1) { // Elements
component = this._createComponentForNode(node);
childrenFromDescriptor.push(component);
} else if (node.nodeType == 3) { // Textnodes
// remove whitespaces from text textnodes
var text = node.textContent ? node.textContent : node.text;
if (text.trim().length > 0) {
if (node.textContent) {
node.textContent = text;
}
childrenFromDescriptor.push(this._createTextElementForNode(node));
}
}
}
}
return childrenFromDescriptor;
},
_childrenInitialized: function () {
},
initialize: function (scope) {
},
/**
* IE8 FIXES
* @param domNode
*/
_localNameFromDomNode: function (domNode) {
if (domNode.localName) return domNode.localName;
var st = domNode.tagName.split(":");
return st[st.length - 1];
}
});
}
);
});
\ 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.data.RestDataSource",
["js.data.DataSource", "js.core.Base", "js.core.List"], function (DataSource, Base, List) {
var RestContext = DataSource.Context.inherit({
createCollection: function(factory, options, type) {
options = options || {};
rAppid._.defaults(options, {
chunkSize: 1000
});
return this.callBase(factory, options, type);
},
getPathComponents: function() {
return [];
},
getQueryParameter: function() {
return {};
}
});
var referenceCollectionTypeExtractor = /^.*\/([^/]+)$/i,
referenceModelTypeExtractor = /^.*\/([^/]+)\/(\w+)$/i;
var RestDataSource = DataSource.inherit({
ctor: function() {
this.callBase();
this.$processors = [];
this.initializeProcessors();
},
initializeProcessors: function () {
this.$processors.push({
regex: /json/,
processor: new RestDataSource.JsonProcessor()
});
},
defaults: {
endPoint: null,
gateway: null,
identifierProperty: "id",
referenceProperty: "href"
},
initialize: function () {
if (!this.$.endPoint) {
console.warn("No end-point for RestDataSource defined");
}
if (!this.$.gateway) {
this.$.gateway = this.$.endPoint;
}
},
getClass: function (type) {
if (rAppid._.isFunction(type)) {
return type;
} else {
return rAppid.getDefinition(this.getFqClassName(type));
}
},
createContext: function (properties, parentContext) {
return new RestContext(this, properties, parentContext);
},
loadClass: function (type, callback) {
if (rAppid._.isFunction(type)) {
callback(null, type);
} else {
var className = this.getFqClassName(type);
if (className) {
rAppid.require(className, function (klass) {
callback(null, klass);
});
} else {
callback("className not found for type '" + type + "'");
}
}
},
getRestPathForModel: function(fqClassname) {
var typeConfig,
i;
// first search via className
for (i = 0; i < this.$configuredTypes.length; i++) {
typeConfig = this.$configuredTypes[i];
if (typeConfig.$.className == fqClassname) {
return typeConfig.$.path;
}
}
// search via alias
for (i = 0; i < this.$configuredTypes.length; i++) {
typeConfig = this.$configuredTypes[i];
if (typeConfig.$.alias == fqClassname) {
return typeConfig.$.path;
}
}
return null;
},
getPathComponentsForModel: function(model) {
var path = this.getRestPathForModel(model.className);
if (path) {
var ret = [path];
if (model.status() == "CREATED"){
ret.push(model.$.id);
}
return ret;
}
return null;
},
/**
* serialize the data
* @param data
*/
serialize: function (data) {
return JSON.stringify(data);
},
/**
* deserialize
* @param input
*/
deserialize: function (input) {
// TODO: enable IE7 and FF3 support? Or should the user add json2.js lib
return JSON.parse(input);
},
getQueryParameter: function() {
return {};
},
/**
*
* @param obj
*/
isReferencedModel: function(obj) {
return obj[this.$.identifierProperty] && obj[this.$.referenceProperty] &&
rAppid._.keys(obj).length == 2;
},
isReferencedCollection: function(obj) {
return obj[this.$.referenceProperty] && rAppid._.keys(obj).length == 1;
},
getContextPropertiesFromReference: function(reference) {
return null;
},
getReferenceInformation: function(reference, id) {
// url is something like
// http://example.com/api/context/resourceType/id
var extractor = id ? referenceModelTypeExtractor : referenceCollectionTypeExtractor;
var match = extractor.exec(reference);
if (match) {
var path = match[1];
for (var i = 0; i < this.$configuredTypes.length; i++) {
var config = this.$configuredTypes[i];
if (config.$.path == path) {
return {
context: this.getContextPropertiesFromReference(reference),
className: config.$.className,
requireClassName: config.$.className.replace(/\./g, "/"),
type: config.$.alias,
id: id
}
}
}
}
// could not retrieve reference information
return null;
},
resolveReferences: function(model, data, options, callback) {
// in REST models and collections will be referenced by href
// first identify all needed model classes
var referenceInformation = [],
self = this;
function findReferences(obj, api) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
var value = obj[prop];
// TODO: test if we need also go through array value and convert them
// or if this is actually done
if (value instanceof List) {
value.each(function(item) {
findReferences(item, api);
});
} else if (value instanceof Object) {
// value is object and could contain sub objects with references
// first resolve references
findReferences(value, api);
if (self.isReferencedModel(value) || self.isReferencedCollection(value)) {
var info = self.getReferenceInformation(value[self.$.referenceProperty], value[self.$.identifierProperty]);
if (info) {
info.referenceObject = obj;
info.propertyName = prop;
referenceInformation.push(info);
} else {
throw "Cannot determinate referenceInformation for reference '" + value[self.$.referenceProperty] + "'.";
}
}
}
}
}
}
findReferences(data);
var requiredClasses = [];
for (var i = 0; i < referenceInformation.length; i++) {
var info = referenceInformation[i];
var requiredClassname = info.requireClassName;
if (rAppid._.indexOf(requiredClasses, requiredClassname) == -1) {
requiredClasses.push(requiredClassname);
}
}
// require model classes
// TODO: how to handle errors here? require.onError?
// some unique hash and extending of requirejs required
rAppid.require(requiredClasses, function () {
var factories = Array.prototype.slice.call(arguments);
for (var i = 0; i < referenceInformation.length; i++) {
var info = referenceInformation[i];
var factory = factories[rAppid._.indexOf(requiredClasses, info.requireClassName)];
if (factory) {
// create instance in correct context
var context = self.getContext(info.context, model.$context);
var isModel = info.id;
var referenceInstance = isModel ?
self.createModel(factory, info.id, info.type, context) :
self.createCollection(factory, null, info.type, context);
if (referenceInstance) {
var value = info.referenceObject[info.propertyName];
info.referenceObject[info.propertyName] = referenceInstance;
if (isModel) {
referenceInstance.set(value);
} else {
// TODO: set loaded data for collection, if available in payload
}
} else {
callback("Instance for model '" + info.className + "' couldn't be created");
}
} else {
callback("Factory for class '" + info.className + "' missing");
}
}
callback(null, data);
});
},
/**
*
* @param model
* @param options
* @param callback function(err, model, options)
*/
loadModel: function (model, options, callback) {
// map model to url
var modelPathComponents = this.getPathComponentsForModel(model);
if (!modelPathComponents) {
callback("path for model unknown", null, options);
return;
}
// build uri
var uri = [this.$.gateway];
uri = uri.concat(model.$context.getPathComponents());
uri = uri.concat(modelPathComponents);
// get queryParameter
var params = rAppid._.defaults(model.$context.getQueryParameter(),this.getQueryParameter());
// create url
var url = uri.join("/");
var self = this;
// send request
rAppid.ajax(url, {
type: "GET",
queryParameter: params
}, function (err, xhr) {
if (!err && (xhr.status == 200 || xhr.status == 304)) {
// find processor that matches the content-type
var processor,
contentType = xhr.getResponseHeader("Content-Type");
for (var i = 0; i < self.$processors.length; i++) {
var processorEntry = self.$processors[i];
if (processorEntry.regex.test(contentType)) {
processor = processorEntry.processor;
break;
}
}
if (!processor) {
callback("No processor for content type '" + contentType + "' found", null, options);
return;
}
try {
// deserialize data with processor
var data = processor.deserialize(xhr.responses);
// parse data inside model
data = model.parse(data);
self.resolveReferences(model, data, options, function(err, resolvedData) {
// set data
model.set(resolvedData);
// and return
callback(null, model, options);
});
} catch (e) {
callback(e, null, options);
}
} else {
// TODO: better error handling
err = err || "wrong status code";
callback(err, null, options);
}
});
}
});
RestDataSource.RestContext = RestContext;
RestDataSource.Processor = Base.inherit({
serialize: function(data) {
throw "abstract method";
},
deserialize: function(responses) {
throw "abstract method";
}
});
RestDataSource.JsonProcessor = RestDataSource.Processor.inherit({
serialize: function (data) {
return JSON.stringify(data);
},
deserialize: function (responses) {
return JSON.parse(responses.text);
}
});
return RestDataSource;
});
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.html.DomElement",
["js.core.Component", "js.core.Content", "js.core.Binding"], function (Component, Content, Binding) {
var rspace = /\s+/;
var domEvents = ['click','dblclick','keyup', 'keydown' , 'change'];
var DomElementFunctions = {
defaults:{
selected:false,
selectable:false
},
$behavesAsDomElement:true,
ctor:function (attributes, descriptor, applicationDomain, parentScope, rootScope) {
this.$renderMap = {};
this.$childViews = [];
this.$contentChildren = [];
this.callBase();
if (descriptor) {
if (!this.$tagName) {
this.$tagName = descriptor.tagName;
}
if (!this.$namespace) {
this.$namespace = descriptor.namespaceURI;
}
}
},
_initializeAttributes:function (attributes) {
this.callBase();
if (attributes.tagName) {
this.$tagName = attributes.tagName;
delete(attributes.tagName);
}
},
addChild:function (child) {
this.callBase();
if (child instanceof DomElement || child.render) {
this.$childViews.push(child);
if(this.isRendered()){
this._renderChild(child);
}
}else if(child instanceof Content){
this.$contentChildren.push(child);
}
},
getPlaceHolder:function (name) {
for (var i = 0; i < this.$children.length; i++) {
if (this.$children[i].$.name === name) {
return this.$children[i];
}
}
var placeholder;
for (i = 0; i < this.$children.length; i++) {
if (this.$children[i].getPlaceHolder) {
placeholder = this.$children[i].getPlaceHolder(name);
if (placeholder) {
return placeholder;
}
}
}
return null;
},
render:function () {
if (!this.$initialized) {
this._initialize(this.$creationPolicy);
}
// check if it is already rendered
if (this.isRendered()) {
return this.$el;
}
this.$renderedChildren = [];
this.$el = document.createElement(this.$tagName);
this.$el.owner = this;
// TODO: read layout and create renderMAP
/**
* <js:Template name="layout"><placeholder cid="icon"/><placeholder cid="label"/></js:Template>
*/
this._renderChildren(this.$childViews);
this._renderContentChildren(this.$contentChildren);
this._renderAttributes(this.$);
this._bindDomEvents(this.$el);
return this.$el;
},
_bindDomEvents:function (el) {
var self = this, domEvent;
function bindDomEvent(eventName,scope,fncName){
self.bind(eventName,scope[fncName],scope);
domEvent = eventName.substr(2);
self.addEventListener(domEvent, function (e) {
self.trigger(eventName, e, self);
});
}
var eventDef;
for(var i = 0 ; i < this.$eventDefinitions.length; i++){
eventDef = this.$eventDefinitions[i];
if(!this._isComponentEvent(eventDef.name.substr(2))){
bindDomEvent(eventDef.name, eventDef.scope, eventDef.fncName);
}
}
},
_renderChildren:function (children) {
// for all children
var child;
for (var i = 0; i < children.length; i++) {
child = children[i];
this._renderChild(child);
}
},
_renderContentChildren: function(children){
var child;
for(var i = 0; i < children.length; i++){
child = children[i];
var ref = child.get('ref');
var placeHolder = this.getPlaceHolder(ref);
if (placeHolder) {
placeHolder.set({content:child});
}
}
},
_renderChild:function (child) {
if (rAppid._.isFunction(child.render)) {
var el = child.render();
this.$renderedChildren.push(child);
if (el) {
this.$el.appendChild(el);
}
}
},
_getIndexOfPlaceHolder:function (placeHolder) {
if (this.$layoutTpl) {
var child;
for (var i = 0; i < this.$layoutTpl.$children.length; i++) {
child = this.$layoutTpl.$children[i];
if (placeHolderId == child.$cid) {
return i;
}
}
}
return -1;
},
isRendered:function () {
return typeof (this.$el) !== "undefined";
},
_renderAttributes:function (attributes) {
var attr;
for (var key in attributes) {
if (attributes.hasOwnProperty(key) && key.indexOf("$") !== 0 && key.indexOf("data") !== 0) {
attr = attributes[key];
this._renderAttribute(key, attr);
}
}
},
_renderAttribute:function (key, attr) {
var method = this.$renderMap[key];
var prev = this.$previousAttributes[key];
if (rAppid._.isUndefined(method)) {
// generic call of render functions
var k = key[0].toUpperCase() + key.substr(1);
var methodName = "_render" + k;
method = this[methodName];
if (!rAppid._.isFunction(method)) {
method = false;
}
this.$renderMap[key] = method;
}
if (method !== false) {
method.call(this, attr, prev);
} else if (this.$behavesAsDomElement) {
this.$el.setAttribute(key, attr);
}
},
_renderVisible:function (visible) {
if (visible === true) {
this.removeClass('hidden');
} else if (visible === false) {
this.addClass('hidden');
}
},
_renderHidden:function (hidden) {
if (typeof(hidden) !== "undefined") {
this.set({visible:!hidden});
}
},
_renderSelected:function (selected) {
if (selected === true) {
this.addClass('active');
} else if (selected === false) {
this.removeClass('active');
}
},
_renderSelectable:function (selectable) {
if (selectable === true) {
var self = this;
this.addEventListener('click', function (e) {
// e.preventDefault();
self.set({selected:!self.$.selected});
});
} else {
this.set({selected:false});
}
},
_renderWidth:function (width) {
if (width) {
if (typeof(width) !== "string") {
width += "px";
}
this.$el.style.width = width;
}
},
_renderHeight:function (height) {
if (height) {
if (typeof(height) !== "string") {
height += "px";
}
this.$el.style.height = height;
}
},
_commitChangedAttributes:function (attributes) {
if (this.isRendered()) {
this._renderAttributes(attributes);
}
},
dom:function (element) {
return new DomManipulation(element || this);
}
};
var DomManipulationFunctions = {
hasClass:function (value) {
// var classes = this.$el.className.split(" "+value+" ");
},
addClass:function (value) {
var classNames = value.split(rspace);
if (!this.$el.className && classNames.length === 1) {
this.$el.className = value;
} else {
var setClasses = this.$el.className.split(rspace);
for (var i = 0; i < classNames.length; i++) {
if (setClasses.indexOf(classNames[i]) == -1) {
setClasses.push(classNames[i]);
}
}
this.$el.className = setClasses.join(" ");
}
},
removeClass:function (value) {
if (this.$el.className.length === 0) {
return;
}
var removeClasses = value.split(rspace);
var classes = this.$el.className.split(rspace);
for (var i = 0; i < removeClasses.length; i++) {
var index = classes.indexOf(removeClasses[i]);
if (index != -1) {
classes.splice(index, 1);
}
}
if (classes.length === 0) {
this.$el.removeAttribute('class');
} else {
this.$el.className = classes.join(" ");
}
},
addEventListener:function (type, eventHandle) {
if (this.$el.addEventListener) {
this.$el.addEventListener(type, eventHandle, false);
} else if (this.$el.attachEvent) {
this.$el.attachEvent("on" + type, eventHandle);
}
},
removeEvent:document.removeEventListener ?
function (type, handle) {
if (this.$el.removeEventListener) {
this.$el.removeEventListener(type, handle, false);
}
} :
function (type, handle) {
if (this.$el.detachEvent) {
this.$el.detachEvent("on" + type, handle);
}
}
};
var DomManipulation = inherit.Base.inherit(rAppid._.extend({
ctor:function (elm) {
this.$el = elm;
}
}, DomManipulationFunctions));
var DomElement = Component.inherit(rAppid._.extend(DomElementFunctions, DomManipulationFunctions));
return DomElement;
}
);
});
\ 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
(function () {
var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
var importRegEx = /((?:xaml!)?[a-z]+(\.[a-z]+[a-z0-9]*)*)/mgi;
define(function () {
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (obj) {
for (var i = 0; i < this.length; i++) {
if (this[i] == obj) {
return i;
}
}
return -1;
}
}
/**
* IE8 FIXES
* @param domNode
*/
var localNameFromDomNode = function(domNode){
if(domNode.localName) return domNode.localName;
var st = domNode.tagName.split(":");
return st[st.length-1];
};
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);
}
},
getDependency: function(namespace, localName, namespaceMap, xamlClasses, rewriteMap) {
var fqClassName = [namespaceMap[namespace] || namespace, localName].join(".");
for (var i = 0; i < rewriteMap.length; i++) {
var entry = rewriteMap[i];
if (entry.$from && entry.$to) {
if (entry.$from.test(fqClassName)) {
fqClassName = fqClassName.replace(entry.$from, entry.$to);
break;
}
}
}
// TODO fix
if (xamlClasses.indexOf(fqClassName) != -1) {
fqClassName = "xaml!" + fqClassName;
}
return fqClassName.replace(/\./g, "/");
},
findDependencies: function (xaml, namespaceMap, xamlClasses, rewriteMap, imports) {
var self = this;
var ret = [];
function findDependencies(domNode) {
var localName = localNameFromDomNode(domNode);
var dep = self.getDependency(domNode.namespaceURI, localName, namespaceMap, xamlClasses, rewriteMap);
// console.log(dep);
if (dep == "js/core/Imports") {
for (var t = 0; t < domNode.childNodes.length; t++) {
var importNode = domNode.childNodes[t];
if (importNode.nodeType == 3) {
// text node
var m;
var textContent = importNode.textContent ? importNode.textContent : importNode.text;
while ((m = importRegEx.exec(textContent+" ")) != null) {
var importClass = m[0].replace(/\./g, "/");
if(importClass !== "undefined"){
if (ret.indexOf(importClass) == -1) {
ret.push(importClass);
}
if (imports) {
imports.push(importClass);
}
}
}
}
}
}
if (ret.indexOf(dep) == -1) {
ret.push(dep);
}
for (var i = 0; i < domNode.childNodes.length; i++) {
var childNode = domNode.childNodes[i];
// element
if (childNode.nodeType == 1) {
findDependencies(childNode);
}
}
}
if (xaml) {
findDependencies(xaml);
}
return ret;
},
findScripts: function(xaml, namespaceMap, xamlClasses, rewriteMap) {
var ret = [];
for (var i = 0; i < xaml.childNodes.length; i++) {
var node = xaml.childNodes[i];
if (node.nodeType == 1) {
if ("js/core/Script" == this.getDependency(node.namespaceURI, localNameFromDomNode(node), namespaceMap, xamlClasses, rewriteMap)) {
ret.push(node);
}
}
}
return ret;
},
getDeclarationFromScripts: function(scripts) {
var ret = {};
if (scripts) {
for (var s = 0; s < scripts.length; s++) {
var script = scripts[s];
for (var fn in script) {
if (script.hasOwnProperty(fn)) {
ret[fn] = script[fn];
}
}
}
}
return ret;
},
load: function (name, req, onLoad, config) {
// if (config.isBuild && !config.inlineText) {
// onLoad();
// return;
// }
var self = this;
var url = req.toUrl(name.replace(/\./g, "/") + ".xml");
this.get(url, function (err, xhr) {
if (!err) {
if (xhr.responseXML) {
// require all dependencies
var imports = [];
var dependencies = self.findDependencies(xhr.responseXML.documentElement,
config.namespaceMap, config.xamlClasses, config.rewriteMap, imports);
for (var i = 0; i < imports.length; i++) {
// console.log(imports[i]);
}
var scripts = self.findScripts(xhr.responseXML.documentElement,
config.namespaceMap, config.xamlClasses, config.rewriteMap);
if (scripts.length > 0) {
// at least one script
dependencies.splice(1, 0, "js/core/Script");
}
if(imports.length > 0){
dependencies = dependencies.concat(imports);
}
for(i = 0 ; i < dependencies.length; i++){
// console.log("AFTER: "+dependencies[i]);
}
// first item should be the dependency of the document element
req(dependencies, function() {
// dependencies are loaded
var baseClass = arguments[0],
Script = arguments[1];
var args = [];
for(var i = 1; i < arguments.length; i++){
args.push(arguments[i]);
}
var scriptObjects = [];
var importedClasses = args.slice(args.length - imports.length);
if (scripts.length > 0) {
for (var s = 0; s < scripts.length; s++) {
try {
var scriptInstance = new Script(null, scripts[s]);
scriptObjects.push(scriptInstance.evaluate(importedClasses));
} catch (e) {
throw "Script cannot be loaded";
}
}
}
var xamlFactory = baseClass.inherit(
self.getDeclarationFromScripts(scriptObjects)
);
xamlFactory.prototype._$descriptor = xhr.responseXML.documentElement;
if (config.applicationDomain) {
config.applicationDomain.defineXamlClass(name, dependencies, xamlFactory);
onLoad(xamlFactory);
}
});
} else {
throw name + " wasn't a valid xml document";
}
} else {
throw err;
}
});
}
};
});
})();
\ 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: {
'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
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.ui.ItemsView",
["js.ui.View", "js.core.Template", "js.core.List"], function (View, Template, List) {
return View.inherit({
defaults: {
tagName: "div",
items: []
},
hasItems: function(){
return this.$.items.length > 0;
}.on('items'),
addItem: function (item) {
this.$.items.push(item);
if (this.isRendered()) {
this._renderItem(item);
}
},
render: function(){
this.$renderedItems = [];
return this.callBase();
},
removeItem: function(item){
var index = this.$.items.indexOf(item);
if(index > -1){
this.$.items.slice(index,1);
if (this.isRendered()) {
this._removeRenderedItem(item);
}
}
},
clear: function(){
},
_renderList: function(list, oldList){
if(oldList){
// TODO: unbind!
}
if(list instanceof List){
list.bind('sort', this._onSort, this);
list.bind('reset', this._onReset, this);
list.bind('add', this._onItemAdd,this);
list.bind('remove', this._onItemRemove,this);
this.set({items: list.$items});
}
},
_onSort: function(e){
if(this.isRendered()){
var item, c;
for (var i = 0; i < e.$.items.length; i++) {
item = e.$.items[i];
c = this.getComponentForItem(item);
this.$el.removeChild(c.$el);
this.$el.appendChild(c.$el);
}
}
},
_onReset: function(e){
this.set('items',e.$.items);
},
_onItemAdd: function(e){
this._renderItem(e.$.item,e.$.index);
},
_onItemRemove: function(e){
this._removeRenderedItem(e.$.item);
},
_renderItems: function (items) {
if (this.$renderedItems) {
var c;
for (var j = this.$renderedItems.length - 1; j >= 0; j--) {
c = this.$renderedItems[j];
this.$el.removeChild(c.component.$el);
}
}
this.$renderedItems = [];
for (var i = 0; i < items.length; i++) {
this._renderItem(items[i],i);
}
},
_renderItem: function (item,i) {
var comp = this.$templates['item'].createComponents({$item: item, $index: i})[0];
// add to rendered item map
this.$renderedItems.push({
item: item,
component: comp
});
this.addChild(comp);
},
_removeRenderedItem: function(item){
var ri;
for (var i = 0; i < this.$renderedItems.length; i++) {
ri = this.$renderedItems[i];
if (ri.item === item) {
this.$el.removeChild(ri.component.$el);
this.$renderedItems.slice(i,1);
return;
}
}
},
getComponentForItem: function (item) {
var ri;
for (var i = 0; i < this.$renderedItems.length; i++) {
ri = this.$renderedItems[i];
if (ri.item === item) {
return ri.component;
}
}
return null;
}
});
}
);
});
\ No newline at end of file
<?xml version="1.0"?>
<ui:View xmlns="http://www.w3.org/1999/xhtml" xmlns:js="js.core" xmlns:ui="js.ui">
<js:Script>
(function () {
return {
defaults:{
tagName:'a',
href:null,
label:' '
},
_renderIconClass:function (iconClass, oldIconClass) {
if (iconClass) {
this._renderTemplateToPlaceHolder('iconTemplate', 'icon', {$iconClass:iconClass});
} else {
this.getPlaceHolder("icon").clear();
}
},
_renderHref:function (href) {
if (this.$tagName == "a") {
this.$el.setAttribute("href", href || "#");
if (!href) {
this.$el.setAttribute('onclick', "return false;");
}
}
}
}
})
</js:Script>
<js:Template name="layout">
<ui:PlaceHolder name="icon"/>{label}
</js:Template>
<js:Template name="iconTemplate">
<i class="{$iconClass}"/>
</js:Template>
</ui:View>
\ No newline at end of file
<?xml version="1.0"?>
<ui:View xmlns="http://www.w3.org/1999/xhtml" xmlns:js="js.core" xmlns:ui="js.ui">
<js:Imports>
js.core.Content;
js.ui.Button;
</js:Imports>
<js:Script type="text/javascript">
<![CDATA[
(function (Content, Button) {
return {
defaults:{
tagName:'div',
'class':'btn-group',
'menuClassName':"dropdown-menu",
menuVisible:false
},
$instances:[],
addChild:function (child) {
if (child instanceof Button) {
this._collectButton(child);
}
this.callBase();
},
_collectButton:function (child) {
this.$button = child;
this.$toggleButton = child;
},
_renderType:function (type) {
this.$button.set({type:type});
},
_renderIconClass:function (iconClass) {
this.$button.set({iconClass:iconClass});
},
_renderLabel:function (label) {
this.$button.set({label:label});
},
_renderMenuVisible:function (visible) {
if (visible === true) {
for (var i = 0; i < this.$instances.length; i++) {
if (this.$instances[i] != this) {
this.$instances[i].set({menuVisible:false});
}
}
this.addClass('open');
} else {
this.removeClass('open');
}
},
_bindDomEvents:function (el) {
if (!rAppid._.contains(this.$instances, this)) {
this.$instances.push(this);
}
var self = this;
document.addEventListener('click', function (e) {
self.set({menuVisible:false});
});
this.$toggleButton.$el.addEventListener('click', function (e) {
e.stopPropagation();
e.preventDefault();
self.set({menuVisible:!self.$.menuVisible});
});
this.$button.addEventListener('click', function (e) {
self.trigger('onclick', e, self);
});
}
}
})
]]>
</js:Script>
<js:Template name="layout">
<ui:Button class="dropdown-toggle">
<js:Template name="layout">
<ui:PlaceHolder name="icon"/>{label}<span class="caret"/>
</js:Template>
</ui:Button>
<ui:ContentPlaceHolder tagName="div" name="menu" class="{menuClassName}"/>
</js:Template>
</ui:View>
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.ui.PlaceHolder",
["js.core.UIComponent", "js.core.Content"], function (UIComponent, Content) {
return UIComponent.inherit({
render: function () {
if (this.isRendered()) {
return this.$el;
}
this.$textNode = document.createTextNode("");
this.$el = this.$textNode;
return this.$el;
},
clear: function () {
this.set({content: this.$textNode});
},
_renderContent: function (content) {
var children;
if (content instanceof Content) {
children = content.$children;
} else if (rAppid._.isArray(content)) {
children = content;
} else {
children = [content];
}
var child, el;
for (var i = 0; i < children.length; i++) {
child = children[i];
if (child.render) {
el = child.render();
var parentNode = this.$el.parentNode;
parentNode.insertBefore(el, this.$el);
}
}
}
});
}
);
});
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.ui.ScrollableView",
["js.ui.View", "js.ui.ItemsView", "js.html.DomElement", "jQuery"], function (View, ItemsView, DomElement, $) {
var VERTICAL = "vertical";
var HORIZONTAL = "horizontal";
return View.inherit({
defaults:{
tagName:"div",
direction:HORIZONTAL,
selectedPage:0,
componentClass:'scrollable'
},
ctor:function () {
this.callBase();
this.$childViews = [];
},
addChild:function (child) {
this.callBase();
if (!this.$scrollView && child instanceof DomElement) {
this.$scrollView = child;
}
},
_renderDirection: function(direction,oldDirection){
if(oldDirection){
this.removeClass(oldDirection);
}
if(direction){
this.addClass(direction);
}
},
_renderSelectedPage:function (page, oldPage) {
if (this.$scrollView && this.$scrollView.isRendered()) {
this.$scrollView.addClass('scroller');
if(this.$.direction === HORIZONTAL){
$(this.$scrollView.$el).animate({
left:-parseInt(this.$el.style.width) * page,
specialEasing:{
width:'linear',
height:'easeInOutQuad'
}
}, 'slow');
}else if(this.$.direction === VERTICAL){
$(this.$scrollView.$el).animate({
top:-parseInt(this.$el.style.height) * page,
specialEasing:{
width:'linear',
height:'easeInOutQuad'
}
}, 'slow');
}
}
}
});
}
);
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.ui.SegmentedView",
["js.ui.ItemsView", "js.html.DomElement"], function (ItemsView, DomElement) {
return ItemsView.inherit({
defaults: {
tagName: "div",
visibleIndex: 0,
visibleView: null
},
ctor: function(){
this.$childViews = [];
this.callBase();
},
addChild: function (child) {
this.callBase();
if (child instanceof DomElement) {
this.$childViews.push(child);
}
},
_renderChild: function (child) {
if (this.$.visibleView == child) {
child.set({visible: true});
this.callBase();
}
},
_renderVisibleView: function (child, oldView) {
if (oldView) {
oldView.set({visible: false});
}
if (child) {
if (!child.isRendered()) {
child.set({visible: false});
this._renderChild(child);
}
child.set({visible: true});
}
},
_renderVisibleIndex: function (index) {
if (index > -1 && index < this.$childViews.length) {
this.set({visibleView: this.$childViews[index]});
} else if (this.$.visibleView) {
this.$.visibleView.set({visible: false});
}
}
});
}
);
});
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.ui.SelectionView",
["js.ui.ItemsView", "js.html.DomElement"], function (ItemsView, DomElement) {
return ItemsView.inherit({
defaults: {
tagName: "div",
needsSelection: false,
multiSelect: false,
selectedViews: [],
selectedItems: [],
selectedItem: null,
items: [],
forceSelectable: true
},
hasSelectedItems: function(){
return this.$.selectedItems.length > 0;
},
hasSelection: function () {
return this.$.selectedViews.length > 0;
}.onChange('selectedViews'),
_renderChild: function (child) {
if (child instanceof DomElement) {
var self = this;
if(this.$.forceSelectable === true){
child.set({selectable:true});
}
child.bind('change:selected', function (e, c) {
self._onChildSelected(c);
}, child);
}
this.callBase();
if (this.$.needsSelection === true && this.$.selectedItem === null && this.hasSelection() === false ) {
child.set({selected: true});
} else {
// get item for child, if item is in selectedItems, select child!
if (child.has("$item")) {
for (var i = 0; i < this.$.selectedItems.length; i++) {
if (child.$.$item === this.$.selectedItems[i] || child.$.$item === this.$.selectedItem) {
child.set({selected:true});
break;
}
}
}
}
},
_renderSelectedItem: function(item){
var comp = this.getComponentForItem(item);
if(comp){
comp.set({selected: true});
}
},
_renderSelectedItems: function (items) {
var item;
for (var i = 0; i < this.$renderedItems.length; i++) {
item = this.$renderedItems[i].item;
this.$renderedItems[i].component.set({selected:rAppid._.contains(items, item)});
}
},
_renderSelectedIndex: function (i) {
if (i != null && i > -1 && i < this.$renderedChildren.length) {
this.$renderedChildren[i].set({selected: true});
}
},
_onChildSelected: function (child) {
var c, i;
var checkMultiSelect = (child.$.selected === true && this.$.multiSelect === false);
var checkMinSelect = !checkMultiSelect && (child.$.selected === false && this.$.needsSelection === true);
var correctSelection = false;
var somethingSelected = false;
var selectedChildren = [];
var selectedItems = [];
var selectedIndex, selectedItem = null;
for (i = 0; i < this.$renderedChildren.length; i++) {
c = this.$children[i];
if (checkMultiSelect) {
if (c != child && c.$.selected === true) {
correctSelection = true;
c.set({selected: false});
}
} else if (checkMinSelect) {
if (c.$.selected === true) {
somethingSelected = true;
}
}
if (c.$.selected === true) {
selectedIndex = i;
selectedChildren.push(c);
if (c.has("$item")) {
selectedItems.push(c.$.$item);
selectedItem = c.$.$item;
}
}
}
if (this.$.needsSelection === true && somethingSelected === false && child.$.selected === false) {
child.set({selected: true});
correctSelection = true;
}
if (!correctSelection) {
this.set({selectedViews: selectedChildren, selectedItems: selectedItems, selectedIndex: selectedIndex, selectedItem: selectedItem});
}
}
});
}
);
});
\ No newline at end of file
<?xml version="1.0"?>
<ui:MenuButton xmlns="http://www.w3.org/1999/xhtml" xmlns:js="js.core" xmlns:ui="js.ui">
<js:Imports>
js.ui.Button
</js:Imports>
<js:Script type="text/javascript">
<![CDATA[
(function (Button) {
return {
defaults:{
'menuClassName':"dropdown-menu right"
},
_renderType:function (type) {
this.$toggleButton.set({type:type});
this.$button.set({type:type});
},
_collectButton:function (child) {
if (child.$['class'].indexOf("dropdown-toggle") > -1) {
this.$toggleButton = child;
} else {
this.$button = child;
}
}
}
})
]]>
</js:Script>
<js:Template name="layout">
<ui:Button class="btn"/>
<ui:Button class="btn dropdown-toggle">
<js:Template name="layout">
<span class="caret"/>
</js:Template>
</ui:Button>
<ui:ContentPlaceHolder tagName="div" name="menu" class="{menuClassName}"/>
</js:Template>
</ui:MenuButton>
\ No newline at end of file
<?xml version="1.0"?>
<ui:View xmlns="http://www.w3.org/1999/xhtml" xmlns:js="js.core" xmlns:ui="js.ui">
<js:Script>
(function () {
return {
defaults:{
tagName:'button',
'class':'btn'
},
_renderIconClass:function (iconClass) {
if (iconClass) {
if (!this.$iconComponent) {
// get Icon Template
var tpl = this.getTemplate('icon');
// TODO: remove this shop!
tpl._initialize();
// render icon template
this.$iconComponent = tpl.createComponent({$iconClass:iconClass});
this.$iconComponent.initialize();
this.getPlaceholderByCid('icon').set({content:this.$iconComponent});
} else {
this.$iconComponent.set({$iconClass:iconClass});
}
// append as child first child
} else {
this.$iconComponent.$el.remove();
delete this.$iconComponent;
}
},
_renderLabel:function (label) {
if (label) {
if (!this.$labelComponent) {
var tpl = this.getTemplate('label');
if (tpl) {
tpl._initialize();
this.$labelComponent = tpl.createComponent({$label:label});
this.$labelComponent.initialize();
this.getPlaceholderByCid('label').set({content:this.$labelComponent});
}
}
}
}
}
})();
</js:Script>
<js:Template name="layout">
<asdsad>
<js:Template ref="left"/>
</asdsad>
<js:Template ref="right"/>
</js:Template>
<js:Template name="layout">
<js:Template ref="left" />
<js:Template ref="right"/>
</js:Template>
<!-- DEFAULT ICON CLASS TEMPLATE-->
<js:Template name="left">
<div>
<js:PlaceHolder cid="innerleft"/>
</div>
</js:Template>
<js:Template name="left">
<div>
<span>splitterbar</span>
<js:PlaceHolder cid="innerright"/>
</div>
</js:Template>
</ui:View>
\ No newline at end of file
<?xml version="1.0"?>
<ui:ItemsView xmlns="http://www.w3.org/1999/xhtml" xmlns:js="js.core" xmlns:ui="js.ui">
<js:Imports>
js.ui.View;
js.ui.SelectionView;
js.ui.SegmentedView;
</js:Imports>
<js:Script>
<![CDATA[
(function (View, SelectionView, SegmentedView) {
return {
defaults:{
selectedIndex:0,
selectedView:null,
tabClassName: 'nav nav-tabs'
},
_initializeLayoutChildren:function (children) {
var child;
var self = this;
for (var i = 0; i < children.length; i++) {
child = children[i];
if (!this.$selectionView && child instanceof SelectionView) {
this.$selectionView = child;
this.$selectionView.set({items: []});
this.$selectionView.bind('change:selectedViews', this._onTabChange, this);
} else if (!this.$segmentedView && child instanceof SegmentedView) {
this.$segmentedView = child;
}
}
this.callBase();
},
_renderChild:function (child) {
if (child instanceof View && child != this.$selectionView && child != this.$segmentedView) {
this.$selectionView.addItem(child);
this.$segmentedView.addChild(child);
} else {
this.callBase();
}
},
_onTabChange:function (e) {
if (e.$.length > 0) {
this.$segmentedView.set({visibleView:e.$[0].$.$item});
}
},
_renderSelectedIndex:function (index) {
this.$selectionView.set({selectedIndex:index});
},
_renderSelectedView:function (view) {
this.$selectionView.set({selectedView:view});
}
}
})
]]>
</js:Script>
<js:Template name="layout">
<ui:SelectionView tagName="ul" class="{tabClassName}" needsSelection="true" forceSelectable="true">
<js:Template name="item">
<ui:View tagName="li"><ui:Link label="{$item.title}"/></ui:View>
</js:Template>
</ui:SelectionView>
<ui:SegmentedView/>
</js:Template>
</ui:ItemsView>
\ No newline at end of file
var requirejs = (typeof requirejs === "undefined" ? require("requirejs") : requirejs);
requirejs(["rAppid"], function (rAppid) {
rAppid.defineClass("js.ui.View",
["js.html.DomElement", "js.core.Template", "js.core.Content"], function (DomElement, Template, Content) {
return DomElement.inherit({
defaults: {
tagName: "div"
},
$behavesAsDomElement: false,
render: function () {
// look if the component has a layout defined
var layout = this.$templates['layout'];
// if layout template available...
if (layout) {
var children = layout.createComponents({},this,this);
this._initializeLayoutChildren(children);
}
return this.callBase();
},
_initializeLayoutChildren: function (children) {
for (var i = 0; i < children.length; i++) {
children[i].$rootScope = this;
this.addChild(children[i]);
}
},
_renderChild: function (child) {
this.callBase();
if (child instanceof Content) {
var ref = child.get('ref');
if (ref) {
var placeHolder = this.getPlaceHolder(ref);
if (placeHolder) {
placeHolder.set({content: child});
}
}
}
},
_renderLayoutClass: function(layoutClass, oldLayoutClass){
rAppid._.each(this.$renderedChildren,function(child){
if(oldLayoutClass){
child.removeClass(oldLayoutClass);
}
if(layoutClass){
child.addClass(layoutClass)
}
});
},
_renderComponentClass: function (cls, oldCls) {
if (oldCls) {
this.removeClass(oldCls);
}
if (cls) {
this.addClass(cls);
}
},
_renderClass: function (className) {
if (className) {
this.addClass(className);
}
},
_renderTemplateToPlaceHolder: function (templateName, placeholderName, attributes) {
this.$renderedPlaceholders = this.$renderedPlaceholders || {};
var renderedComponent = this.$renderedPlaceholders[placeholderName];
if (!renderedComponent) {
var template = this.getTemplate(templateName);
if (template) {
// TODO: maybe render all components returned
// or create special method createComponent
renderedComponent = template.createComponents(attributes)[0];
// renderedComponent._initialize();
var placeholder = this.getPlaceHolder(placeholderName);
if (placeholder) {
placeholder.set({content: renderedComponent});
this.$renderedPlaceholders[placeholderName] = renderedComponent;
} else {
// throw "No placeholder '"+placeholderName+"' found";
}
}
} else {
renderedComponent.set(attributes);
}
},
_renderId: function(id){
if(id){
this.$el.setAttribute("id",id);
}
}
});
}
);
});
\ No newline at end of file
/*!
* flow.js JavaScript Library v0.1.0
* https://github.com/it-ony/flow.js
*
* Copyright 2012, Tony Findeisen
* Licensed under the MIT license.
* https://raw.github.com/it-ony/flow.js/master/LICENSE
*
* Date: Mon Mar 12 2012 12:36:34 GMT+0100 (CET)
*/
(function (exports) {
"use strict";
var Flow = function(context) {
this.$context = context || {
error: null,
actions: [],
vars: {}
};
};
var flow = function () {
return new Flow();
};
/**
*
* @param {String} [name] variable name
* @param {Function} fn function to execute
* fn - function() {} // syncron
* fn - function(cb) {} // asyncron
*/
Flow.prototype.seq = function (name, fn) {
if (name instanceof Function) {
fn = name;
name = null;
}
if (!fn) {
throw "Sequence action not defined";
}
var self = this;
this.$context.actions.push(function (cb) {
var sync_end = false;
/**
* @param err
* @param data
* @param end
*/
var thisArg = function (err, data, end) {
if (!err && name) {
// save result to var
self.$context.vars[name] = data;
}
cb(err, end);
};
thisArg.vars = self.$context.vars;
if (fn.length) {
// end for async case
thisArg.end = function (err, data) {
// end
thisArg(err, data, true);
};
fn.call(thisArg, thisArg);
} else {
// sync
thisArg.end = function() {
sync_end = true;
};
try {
thisArg(null, fn.call(thisArg), sync_end);
} catch (e) {
thisArg(e, null, sync_end);
}
}
}
);
return this;
};
var ParallelAction = function (name, fn) {
if (!fn) {
throw "Parallel action not defined";
}
return function (parallelInstance, context, results, parallelFinishedCallback) {
var sync_end = false;
var thisArg = function (err, data, end) {
if (!err && name) {
// save result to tmp. var
results[name] = data;
}
parallelFinishedCallback(parallelInstance, err, end);
};
thisArg.vars = context.vars;
if (fn.length) {
// async
thisArg.end = function (err, data) {
// end
thisArg(err, data, true);
};
fn.call(thisArg, thisArg);
} else {
// sync
thisArg.end = function () {
sync_end = true;
};
try {
thisArg(null, fn.call(thisArg), sync_end);
} catch (e) {
thisArg(e, null, sync_end);
}
}
};
};
/**
* Executes the given functions parallel
*
* @param {Object, Array} fns
* {Object} fns - keys will be variable name for returned value
*/
Flow.prototype.par = function (fns) {
var self = this, i, key;
if (fns) {
var parallelActions = [];
if (fns instanceof Array) {
for (i = 0; i < fns.length; i++) {
var fn = fns[i];
parallelActions.push(new ParallelAction(null, fn));
}
} else {
for (key in fns) {
if (fns.hasOwnProperty(key)) {
parallelActions.push(new ParallelAction(key, fns[key]));
}
}
}
if (parallelActions.length > 0) {
// we got at least one function executing in parallel
// push new action
this.$context.actions.push(function (cb) {
(function (parallelActions, cb) {
var results = {}, p;
var parallelFinished = function (fn, err, end) {
var key;
if (!cb) {
// callback, already called, because end called multiple times
return;
}
if (err || end) {
// some error occurred
cb(err, end);
cb = null;
} else {
var index = parallelActions.indexOf(fn);
if (index >= 0 && index < parallelActions.length) {
// remove parallel executed function from actions
parallelActions.splice(index, 1);
} else {
cb("Parallel function returned which wasn't part of this parallel actions");
cb = null;
return;
}
if (parallelActions.length === 0) {
// copy results to var
for (key in results) {
if (results.hasOwnProperty(key)) {
self.$context.vars[key] = results[key];
}
}
cb(null, false);
cb = null;
}
}
};
// copy array of parallel actions, to avoid array is modified by returning of function
// before all functions are started
var copyParallelActions = parallelActions.slice();
// start all functions
for (p = 0; p < copyParallelActions.length; p++) {
// start parallel action
var parallelInstance = copyParallelActions[p];
parallelInstance(parallelInstance, self.$context, results, parallelFinished);
}
}(parallelActions, cb));
});
}
}
return this;
};
Flow.prototype.exec = function (cb) {
var self = this;
var callback = function(err, data) {
if (cb) {
cb(err, data);
}
};
function execNext(index) {
if (index < self.$context.actions.length) {
// execute action
self.$context.actions[index](function(err, end) {
if (err || end) {
callback(err, self.$context.vars);
} else {
execNext(index+1);
}
});
} else {
// finished
callback(null, self.$context.vars);
}
}
execNext(0);
};
// global on the server, window in the browser
var previous_flow = exports.flow;
flow.noConflict = function () {
exports.flow = previous_flow;
return flow;
};
exports.flow = flow;
}(typeof(exports) === "undefined" ? this : exports));
\ No newline at end of file
var inherit;
(function (global, exports) {
/**
*
* @param {Object} classDefinition The definition for the prototype methods
* @param {Function} [baseClass] The prototype to inherit from
*
* @return {Function} returns a constructor function describing the class
*/
inherit = function (classDefinition, baseClass) {
baseClass = baseClass || Object;
var newClass = function () {
if (this.ctor) {
return this.ctor.apply(this, arguments);
}
};
if (baseClass.constructor == Function) {
function Inheritance() {
}
Inheritance.prototype = baseClass.prototype;
newClass.prototype = new Inheritance();
newClass.prototype.constructor = classDefinition;
newClass.prototype.base = baseClass.prototype;
} else {
newClass.prototype = baseClass;
newClass.prototype.constructor = classDefinition;
newClass.prototype.base = baseClass;
}
for (var publicMethod in classDefinition) {
if (classDefinition.hasOwnProperty(publicMethod)) {
var baseFunction = newClass.prototype[publicMethod];
newClass.prototype[publicMethod] = classDefinition[publicMethod];
if (baseFunction instanceof Function) {
newClass.prototype[publicMethod].baseImplementation = baseFunction;
}
}
}
newClass.prototype.callBase = inherit.callBase;
return newClass;
};
inherit.callBase = function () {
// get arguments
var args = Array.prototype.slice.call(arguments);
if (args.length == 0) {
// use arguments from call
args = Array.prototype.slice.call(arguments.callee.caller.arguments);
}
return arguments.callee.caller.baseImplementation.apply(this, args);
};
/**
*
* @param classDefinition The definition for the prototype methods
*
* @return {Function} returns a constructor function describing the class
*/
Function.prototype.inherit = function (classDefinition) {
return inherit(classDefinition, this);
};
Function.prototype.callBase = function () {
var args = Array.prototype.slice.call(arguments);
var that = args.shift();
if (that && that.base) {
var caller = arguments.callee.caller;
if (this == caller) {
return this.baseImplementation.apply(that, args);
} else {
return this.apply(that, args);
}
} else {
throw "base not definied";
}
};
/**
* @property {Function} base class
*/
inherit.Base = inherit({
ctor: function () {
}
});
exports.inherit = inherit;
})(this, typeof exports === "undefined" ? this : exports);
var rAppid;
/** ECMA SCRIPT COMPLIANT**/
if(!String.prototype.trim){
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/g, '');
};
}
(function (exports, inherit, require, define, underscore, XMLHttpRequest, flow) {
if (!require) {
throw "require.js is needed";
}
if (!define) {
throw "define is needed";
}
if (!underscore) {
// TODO include own implementation
throw "underscore is needed"
}
if (!flow) {
throw "flow.js is needed";
}
define("flowjs", function() {
return flow;
});
require.config({
paths: {
"xaml": "js/plugins/xaml",
"json": "js/plugins/json"
}
});
var Base = inherit.Base.inherit({
ctor: function () {
if (!this.className) {
this.className = this.constructor.name;
}
}
});
// define js.core.Base
define("js/core/Base", [], function() {
return Base;
});
define("rAppid", function() {
return _rAppid;
});
function SystemManager(applicationDomain, application) {
this.applicationDomain = applicationDomain;
this.application = application;
}
var xamlApplication = /^(xaml!)?(.+?)(\.xml)?$/;
var defaultNamespaceMap = {
"http://www.w3.org/1999/xhtml": "js.html"
};
var currentApplicationDomain = null;
var _rAppid = {
defineClass: function(fqName, dependencies, generateFactory){
if (currentApplicationDomain) {
currentApplicationDomain.defineClass(fqName, dependencies, generateFactory);
} else {
throw "CurrentApplicationDomain not available! Application not bootstrapped?";
}
},
defineXamlClass: function(fqClassName, dependencies, factory) {
if (currentApplicationDomain) {
currentApplicationDomain.defineXamlClass(fqClassName, dependencies, factory);
} else {
throw "CurrentApplicationDomain not available! Application not bootstrapped?";
}
},
getDefinition: function(fqClassName) {
if (currentApplicationDomain) {
currentApplicationDomain.getDefinition(fqClassName);
} else {
throw "CurrentApplicationDomain not available! Application not bootstrapped?";
}
},
bootStrap: function (mainClass, config, callback) {
config = config || {};
var internalBootstrap = function(config) {
var xamlClasses = config.xamlClasses || [];
var namespaceMap = config.namespaceMap || defaultNamespaceMap;
var rewriteMap = config.rewriteMap;
var applicationDomain = currentApplicationDomain = new ApplicationDomain(namespaceMap, rewriteMap);
require.config({
xamlClasses: xamlClasses,
namespaceMap: namespaceMap,
rewriteMap: applicationDomain.$rewriteMap,
applicationDomain: applicationDomain
});
if (mainClass) {
var parts = xamlApplication.exec(mainClass);
if (parts) {
// mainClass is xaml
mainClass = "xaml!" + parts[2];
} else {
// mainClass is javascript factory
mainClass = mainClass.replace(/\./g, "/");
}
require(["./js/core/Imports"], function () {
require(["./js/core/Application", mainClass], function (Application, mainClassFactory) {
// create instance
var application = new mainClassFactory(null, false, applicationDomain, null, null);
if (application instanceof Application) {
var systemManager = new SystemManager(applicationDomain, application);
rAppid.systemManager = systemManager;
application.$config = config;
application._initialize("auto");
// return system manager
if (callback) {
callback(null, systemManager, application);
}
} else {
var errMessage = "mainClass isn't an instance of js.core.Application";
if (callback) {
callback(errMessage);
} else {
throw(errMessage);
}
}
});
});
}
};
if (Object.prototype.toString.call(config) == '[object String]') {
require(["json!" + config], function(config) {
internalBootstrap(config);
});
} else {
internalBootstrap(config);
}
},
createQueryString: function(parameter) {
var ret = [];
for (var key in parameter) {
if (parameter.hasOwnProperty(key)) {
ret.push(encodeURIComponent(key) + "=" + encodeURIComponent(parameter[key]));
}
}
return ret.join("&");
},
ajax: function(url, options, callback) {
var s = {
url: url
};
rAppid._.extend(s, options, _rAppid.ajaxSettings);
if (s.data && !rAppid._.isString(s.data)) {
throw "data must be a string";
}
s.hasContent = !/^(?:GET|HEAD)$/.test(s.type);
if (s.queryParameter) {
// append query parameter to url
s.url += /\?/.test(s.url) ? "&" : "?" + this.createQueryString(s.queryParameter);
}
if (s.data && s.hasContent && s.contentType !== false) {
xhr.setRequestHeader("Content-Type", s.contentType);
}
// create new xhr
var xhr = s.xhr();
xhr.open(s.type, s.url, s.async);
try {
for (var header in s.headers) {
xhr.setRequestHeader(header, s.headers[header]);
}
} catch (e) {} // FF3
xhr.send();
var xhrCallback = function(_, isAbort) {
var wrappedXhr;
if (xhrCallback && (isAbort || xhr.readyState === 4)) {
xhrCallback = undefined;
if (isAbort) {
// Abort it manually if needed
if (xhr.readyState !== 4) {
xhr.abort();
}
} else {
wrappedXhr = new rAppidXhr(xhr);
}
if (callback) {
callback(isAbort, wrappedXhr)
}
}
};
if (!s.async || xhr.readyState === 4) {
xhrCallback();
} else {
xhr.onreadystatechange = xhrCallback
}
return xhr;
},
// export underscore
_: underscore,
// export inherit
inherit: inherit,
require: require
};
var rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg; // IE leaves an \r character at EOL
var rAppidXhr = Base.inherit({
ctor: function(xhr) {
this.xhr = xhr;
this.status = xhr.status;
this.$nativeResponseHeaders = xhr.getAllResponseHeaders();
this.responses = {};
var xml = xhr.responseXML;
// Construct response list
if (xml && xml.documentElement) {
this.responses.xml = xml;
}
this.responses.text = xhr.responseText;
try {
this.statusText = xhr.statusText;
} catch (e) {
this.statusText = "";
}
},
getResponseHeader: function(key) {
var match;
if (!this.$responseHeaders) {
this.$responseHeaders = {};
while (( match = rheaders.exec(this.$nativeResponseHeaders) )) {
this.$responseHeaders[match[1].toLowerCase()] = match[2];
}
}
return this.$responseHeaders[key.toLowerCase()];
}
});
_rAppid.ajaxSettings = {
type: "GET",
contentType: "application/x-www-form-urlencoded",
async: true,
// TODO: add ie7 support for local file requests via ActiveX
xhr: function() {
return new XMLHttpRequest();
},
headers: {
}
};
var Rewrite = _rAppid.rewriteMapEntry = function (from, to) {
this.$from = from;
this.$to = to;
};
_rAppid.defaultRewriteMap = [
new Rewrite(/^js.html.(input)$/, "js.html.Input"),
new Rewrite(/^js.html.(select)$/, "js.html.Select"),
new Rewrite(/^js.html.(textarea)$/, "js.html.TextArea"),
new Rewrite(/^js.html.(option)$/, "js.html.Option"),
new Rewrite(/^js.html.(.+)$/, "js.html.DomElement"),
new Rewrite(/^js.conf.(.+)$/, "js.core.Component")
];
var ApplicationDomain = inherit.Base.inherit({
ctor: function(namespaceMap, rewriteMap) {
this.$namespaceMap = namespaceMap || {};
this.$rewriteMap = rewriteMap || rAppid.defaultRewriteMap;
this.$ns = {};
},
/**
*
* loads all dependencies and defines a class under the given fqClassname
*
* @param fqClassName full qualified classname (e.g. js.ui.myComponent)
* @param dependencies as hash or array
* @param generateFactor a function that return the factory function invoked after all dependencies are loaded
*/
defineClass: function (fqClassName, dependencies, generateFactor) {
// create the namespace and install the class
if (!fqClassName || fqClassName == "") {
throw "Full qualified class name '" + fqClassName + "' in wrong format. Use dot notation.";
}
var self = this;
var realDependencies = [];
if (dependencies) {
for (var i = 0; i < dependencies.length; i++) {
realDependencies.push(dependencies[i].replace(/\./g, "/"));
}
}
define(fqClassName.replace(/\./g, "/"), realDependencies, function () {
var factory = generateFactor.apply(this, arguments);
factory.prototype.constructor.name = fqClassName;
if (!self.installClass(self.$ns, fqClassName.split("."), factory)) {
throw "Class '" + fqClassName + "' could not be installed";
}
return factory;
});
},
/**
* registers an XAML component
*
* differs from normal class registration because, dependencies are loaded
* and class has to be installed immedently
*
* @param fqClassName
* @param dependencies
* @param factory
*/
defineXamlClass: function (fqClassName, dependencies, factory) {
// create the namespace and install the class
if (!fqClassName || fqClassName == "") {
throw "Full qualified class name '" + fqClassName + "' in wrong format. Use dot notation.";
}
var normalizeRegex = /\//g;
fqClassName = fqClassName.replace(normalizeRegex, ".");
factory.prototype.constructor.name = fqClassName;
if (!this.installClass(this.$ns, fqClassName.split("."), factory)) {
throw "Class '" + fqClassName + "' could not be installed";
}
define(fqClassName.replace(/\./g, "/"), dependencies, function () {
return factory;
});
},
getDefinition: function (fqClassName) {
function getDefinition (currentNamespace, classPath) {
if (classPath.length > 0) {
var part = classPath.shift();
if (currentNamespace.hasOwnProperty(part)) {
var value = currentNamespace[part];
if (value instanceof Function) {
if (classPath.length == 0) {
return value;
} else {
throw "unterminated classpath";
}
} else {
return getDefinition.call(this, currentNamespace[part], classPath);
}
}
}
return null;
}
return getDefinition.call(this, this.$ns, fqClassName.split("."));
},
hasDefinition: function (fqClassName) {
return this.getDefinition(fqClassName) ? true : false;
},
createInstance: function (fqClassName, args, className) {
className = className || fqClassName;
args = args || [];
var classDefinition = this.getDefinition(fqClassName);
function construct(constructor, args) {
function F() {
return constructor.apply(this, args);
}
F.prototype = constructor.prototype;
return new F();
}
var ret = construct(classDefinition, args);
ret.className = className;
return ret;
},
getFqClassName: function (namespace, className, useRewriteMap) {
if (useRewriteMap == undefined || useRewriteMap == null) {
useRewriteMap = true;
}
var fqClassName = [this.$namespaceMap[namespace] || namespace, className].join(".");
if (useRewriteMap) {
for (var i = 0; i < this.$rewriteMap.length; i++) {
var entry = this.$rewriteMap[i];
if (entry instanceof rAppid.rewriteMapEntry) {
if (entry.$from.test(fqClassName)) {
return fqClassName.replace(entry.$from, entry.$to);
}
}
}
}
return fqClassName;
},
installClass: function (currentNamespace, path, value) {
if (path.length == 0) {
return false;
}
var part = path.shift();
if (!currentNamespace.hasOwnProperty(part)) {
if (path.length == 0) {
// create class
currentNamespace[part] = value;
return true;
} else {
// create namespace
currentNamespace[part] = {};
}
}
// step into namespace
return this.installClass(currentNamespace[part], path, value);
}
});
rAppid = exports.rAppid = _rAppid;
})(typeof exports === "undefined" ? this : exports,
typeof inherit === "undefined" ? global.inherit : inherit,
requirejs,
requirejs.define ? requirejs.define : define,
typeof this._ === "undefined" ? global.underscore : this._,
typeof window !== "undefined" ? window.XMLHttpRequest : global.XMLHttpRequest,
typeof flow === "undefined" ? global.flow : flow);
/** vim: et:ts=4:sw=4:sts=4
* @license RequireJS 1.0.7 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
/*jslint strict: false, plusplus: false, sub: true */
/*global window, navigator, document, importScripts, jQuery, setTimeout, opera */
var requirejs, require, define;
(function () {
//Change this version number for each release.
var version = "1.0.7",
commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
cjsRequireRegExp = /require\(\s*["']([^'"\s]+)["']\s*\)/g,
currDirRegExp = /^\.\//,
jsSuffixRegExp = /\.js$/,
ostring = Object.prototype.toString,
ap = Array.prototype,
aps = ap.slice,
apsp = ap.splice,
isBrowser = !!(typeof window !== "undefined" && navigator && document),
isWebWorker = !isBrowser && typeof importScripts !== "undefined",
//PS3 indicates loaded and complete, but need to wait for complete
//specifically. Sequence is "loading", "loaded", execution,
// then "complete". The UA check is unfortunate, but not sure how
//to feature test w/o causing perf issues.
readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?
/^complete$/ : /^(complete|loaded)$/,
defContextName = "_",
//Oh the tragedy, detecting opera. See the usage of isOpera for reason.
isOpera = typeof opera !== "undefined" && opera.toString() === "[object Opera]",
empty = {},
contexts = {},
globalDefQueue = [],
interactiveScript = null,
checkLoadedDepth = 0,
useInteractive = false,
reservedDependencies = {
require: true,
module: true,
exports: true
},
req, cfg = {}, currentlyAddingScript, s, head, baseElement, scripts, script,
src, subPath, mainScript, dataMain, globalI, ctx, jQueryCheck, checkLoadedTimeoutId;
function isFunction(it) {
return ostring.call(it) === "[object Function]";
}
function isArray(it) {
return ostring.call(it) === "[object Array]";
}
/**
* Simple function to mix in properties from source into target,
* but only if target does not already have a property of the same name.
* This is not robust in IE for transferring methods that match
* Object.prototype names, but the uses of mixin here seem unlikely to
* trigger a problem related to that.
*/
function mixin(target, source, force) {
for (var prop in source) {
if (!(prop in empty) && (!(prop in target) || force)) {
target[prop] = source[prop];
}
}
return req;
}
/**
* Constructs an error with a pointer to an URL with more information.
* @param {String} id the error ID that maps to an ID on a web page.
* @param {String} message human readable error.
* @param {Error} [err] the original error, if there is one.
*
* @returns {Error}
*/
function makeError(id, msg, err) {
var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id);
if (err) {
e.originalError = err;
}
return e;
}
/**
* Used to set up package paths from a packagePaths or packages config object.
* @param {Object} pkgs the object to store the new package config
* @param {Array} currentPackages an array of packages to configure
* @param {String} [dir] a prefix dir to use.
*/
function configurePackageDir(pkgs, currentPackages, dir) {
var i, location, pkgObj;
for (i = 0; (pkgObj = currentPackages[i]); i++) {
pkgObj = typeof pkgObj === "string" ? { name: pkgObj } : pkgObj;
location = pkgObj.location;
//Add dir to the path, but avoid paths that start with a slash
//or have a colon (indicates a protocol)
if (dir && (!location || (location.indexOf("/") !== 0 && location.indexOf(":") === -1))) {
location = dir + "/" + (location || pkgObj.name);
}
//Create a brand new object on pkgs, since currentPackages can
//be passed in again, and config.pkgs is the internal transformed
//state for all package configs.
pkgs[pkgObj.name] = {
name: pkgObj.name,
location: location || pkgObj.name,
//Remove leading dot in main, so main paths are normalized,
//and remove any trailing .js, since different package
//envs have different conventions: some use a module name,
//some use a file name.
main: (pkgObj.main || "main")
.replace(currDirRegExp, '')
.replace(jsSuffixRegExp, '')
};
}
}
/**
* jQuery 1.4.3-1.5.x use a readyWait/ready() pairing to hold DOM
* ready callbacks, but jQuery 1.6 supports a holdReady() API instead.
* At some point remove the readyWait/ready() support and just stick
* with using holdReady.
*/
function jQueryHoldReady($, shouldHold) {
if ($.holdReady) {
$.holdReady(shouldHold);
} else if (shouldHold) {
$.readyWait += 1;
} else {
$.ready(true);
}
}
if (typeof define !== "undefined") {
//If a define is already in play via another AMD loader,
//do not overwrite.
return;
}
if (typeof requirejs !== "undefined") {
if (isFunction(requirejs)) {
//Do not overwrite and existing requirejs instance.
return;
} else {
cfg = requirejs;
requirejs = undefined;
}
}
//Allow for a require config object
if (typeof require !== "undefined" && !isFunction(require)) {
//assume it is a config object.
cfg = require;
require = undefined;
}
/**
* Creates a new context for use in require and define calls.
* Handle most of the heavy lifting. Do not want to use an object
* with prototype here to avoid using "this" in require, in case it
* needs to be used in more super secure envs that do not want this.
* Also there should not be that many contexts in the page. Usually just
* one for the default context, but could be extra for multiversion cases
* or if a package needs a special context for a dependency that conflicts
* with the standard context.
*/
function newContext(contextName) {
var context, resume,
config = {
waitSeconds: 7,
baseUrl: "./",
paths: {},
pkgs: {},
catchError: {}
},
defQueue = [],
specified = {
"require": true,
"exports": true,
"module": true
},
urlMap = {},
defined = {},
loaded = {},
waiting = {},
waitAry = [],
urlFetched = {},
managerCounter = 0,
managerCallbacks = {},
plugins = {},
//Used to indicate which modules in a build scenario
//need to be full executed.
needFullExec = {},
fullExec = {},
resumeDepth = 0;
/**
* Trims the . and .. from an array of path segments.
* It will keep a leading path segment if a .. will become
* the first path segment, to help with module name lookups,
* which act like paths, but can be remapped. But the end result,
* all paths that use this function should look normalized.
* NOTE: this method MODIFIES the input array.
* @param {Array} ary the array of path segments.
*/
function trimDots(ary) {
var i, part;
for (i = 0; (part = ary[i]); i++) {
if (part === ".") {
ary.splice(i, 1);
i -= 1;
} else if (part === "..") {
if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {
//End of the line. Keep at least one non-dot
//path segment at the front so it can be mapped
//correctly to disk. Otherwise, there is likely
//no path mapping for a path starting with '..'.
//This can still fail, but catches the most reasonable
//uses of ..
break;
} else if (i > 0) {
ary.splice(i - 1, 2);
i -= 2;
}
}
}
}
/**
* Given a relative module name, like ./something, normalize it to
* a real name that can be mapped to a path.
* @param {String} name the relative name
* @param {String} baseName a real name that the name arg is relative
* to.
* @returns {String} normalized name
*/
function normalize(name, baseName) {
var pkgName, pkgConfig;
//Adjust any relative paths.
if (name && name.charAt(0) === ".") {
//If have a base name, try to normalize against it,
//otherwise, assume it is a top-level require that will
//be relative to baseUrl in the end.
if (baseName) {
if (config.pkgs[baseName]) {
//If the baseName is a package name, then just treat it as one
//name to concat the name with.
baseName = [baseName];
} else {
//Convert baseName to array, and lop off the last part,
//so that . matches that "directory" and not name of the baseName's
//module. For instance, baseName of "one/two/three", maps to
//"one/two/three.js", but we want the directory, "one/two" for
//this normalization.
baseName = baseName.split("/");
baseName = baseName.slice(0, baseName.length - 1);
}
name = baseName.concat(name.split("/"));
trimDots(name);
//Some use of packages may use a . path to reference the
//"main" module name, so normalize for that.
pkgConfig = config.pkgs[(pkgName = name[0])];
name = name.join("/");
if (pkgConfig && name === pkgName + '/' + pkgConfig.main) {
name = pkgName;
}
} else if (name.indexOf("./") === 0) {
// No baseName, so this is ID is resolved relative
// to baseUrl, pull off the leading dot.
name = name.substring(2);
}
}
return name;
}
/**
* Creates a module mapping that includes plugin prefix, module
* name, and path. If parentModuleMap is provided it will
* also normalize the name via require.normalize()
*
* @param {String} name the module name
* @param {String} [parentModuleMap] parent module map
* for the module name, used to resolve relative names.
*
* @returns {Object}
*/
function makeModuleMap(name, parentModuleMap) {
var index = name ? name.indexOf("!") : -1,
prefix = null,
parentName = parentModuleMap ? parentModuleMap.name : null,
originalName = name,
normalizedName, url, pluginModule;
if (index !== -1) {
prefix = name.substring(0, index);
name = name.substring(index + 1, name.length);
}
if (prefix) {
prefix = normalize(prefix, parentName);
}
//Account for relative paths if there is a base name.
if (name) {
if (prefix) {
pluginModule = defined[prefix];
if (pluginModule && pluginModule.normalize) {
//Plugin is loaded, use its normalize method.
normalizedName = pluginModule.normalize(name, function (name) {
return normalize(name, parentName);
});
} else {
normalizedName = normalize(name, parentName);
}
} else {
//A regular module.
normalizedName = normalize(name, parentName);
url = urlMap[normalizedName];
if (!url) {
//Calculate url for the module, if it has a name.
//Use name here since nameToUrl also calls normalize,
//and for relative names that are outside the baseUrl
//this causes havoc. Was thinking of just removing
//parentModuleMap to avoid extra normalization, but
//normalize() still does a dot removal because of
//issue #142, so just pass in name here and redo
//the normalization. Paths outside baseUrl are just
//messy to support.
url = context.nameToUrl(name, null, parentModuleMap);
//Store the URL mapping for later.
urlMap[normalizedName] = url;
}
}
}
return {
prefix: prefix,
name: normalizedName,
parentMap: parentModuleMap,
url: url,
originalName: originalName,
fullName: prefix ? prefix + "!" + (normalizedName || '') : normalizedName
};
}
/**
* Determine if priority loading is done. If so clear the priorityWait
*/
function isPriorityDone() {
var priorityDone = true,
priorityWait = config.priorityWait,
priorityName, i;
if (priorityWait) {
for (i = 0; (priorityName = priorityWait[i]); i++) {
if (!loaded[priorityName]) {
priorityDone = false;
break;
}
}
if (priorityDone) {
delete config.priorityWait;
}
}
return priorityDone;
}
function makeContextModuleFunc(func, relModuleMap, enableBuildCallback) {
return function () {
//A version of a require function that passes a moduleName
//value for items that may need to
//look up paths relative to the moduleName
var args = aps.call(arguments, 0), lastArg;
if (enableBuildCallback &&
isFunction((lastArg = args[args.length - 1]))) {
lastArg.__requireJsBuild = true;
}
args.push(relModuleMap);
return func.apply(null, args);
};
}
/**
* Helper function that creates a require function object to give to
* modules that ask for it as a dependency. It needs to be specific
* per module because of the implication of path mappings that may
* need to be relative to the module name.
*/
function makeRequire(relModuleMap, enableBuildCallback, altRequire) {
var modRequire = makeContextModuleFunc(altRequire || context.require, relModuleMap, enableBuildCallback);
mixin(modRequire, {
nameToUrl: makeContextModuleFunc(context.nameToUrl, relModuleMap),
toUrl: makeContextModuleFunc(context.toUrl, relModuleMap),
defined: makeContextModuleFunc(context.requireDefined, relModuleMap),
specified: makeContextModuleFunc(context.requireSpecified, relModuleMap),
isBrowser: req.isBrowser
});
return modRequire;
}
/*
* Queues a dependency for checking after the loader is out of a
* "paused" state, for example while a script file is being loaded
* in the browser, where it may have many modules defined in it.
*/
function queueDependency(manager) {
context.paused.push(manager);
}
function execManager(manager) {
var i, ret, err, errFile, errModuleTree,
cb = manager.callback,
map = manager.map,
fullName = map.fullName,
args = manager.deps,
listeners = manager.listeners,
cjsModule;
//Call the callback to define the module, if necessary.
if (cb && isFunction(cb)) {
if (config.catchError.define) {
try {
ret = req.execCb(fullName, manager.callback, args, defined[fullName]);
} catch (e) {
err = e;
}
} else {
ret = req.execCb(fullName, manager.callback, args, defined[fullName]);
}
if (fullName) {
//If setting exports via "module" is in play,
//favor that over return value and exports. After that,
//favor a non-undefined return value over exports use.
cjsModule = manager.cjsModule;
if (cjsModule &&
cjsModule.exports !== undefined &&
//Make sure it is not already the exports value
cjsModule.exports !== defined[fullName]) {
ret = defined[fullName] = manager.cjsModule.exports;
} else if (ret === undefined && manager.usingExports) {
//exports already set the defined value.
ret = defined[fullName];
} else {
//Use the return value from the function.
defined[fullName] = ret;
//If this module needed full execution in a build
//environment, mark that now.
if (needFullExec[fullName]) {
fullExec[fullName] = true;
}
}
}
} else if (fullName) {
//May just be an object definition for the module. Only
//worry about defining if have a module name.
ret = defined[fullName] = cb;
//If this module needed full execution in a build
//environment, mark that now.
if (needFullExec[fullName]) {
fullExec[fullName] = true;
}
}
//Clean up waiting. Do this before error calls, and before
//calling back listeners, so that bookkeeping is correct
//in the event of an error and error is reported in correct order,
//since the listeners will likely have errors if the
//onError function does not throw.
if (waiting[manager.id]) {
delete waiting[manager.id];
manager.isDone = true;
context.waitCount -= 1;
if (context.waitCount === 0) {
//Clear the wait array used for cycles.
waitAry = [];
}
}
//Do not need to track manager callback now that it is defined.
delete managerCallbacks[fullName];
//Allow instrumentation like the optimizer to know the order
//of modules executed and their dependencies.
if (req.onResourceLoad && !manager.placeholder) {
req.onResourceLoad(context, map, manager.depArray);
}
if (err) {
errFile = (fullName ? makeModuleMap(fullName).url : '') ||
err.fileName || err.sourceURL;
errModuleTree = err.moduleTree;
err = makeError('defineerror', 'Error evaluating ' +
'module "' + fullName + '" at location "' +
errFile + '":\n' +
err + '\nfileName:' + errFile +
'\nlineNumber: ' + (err.lineNumber || err.line), err);
err.moduleName = fullName;
err.moduleTree = errModuleTree;
return req.onError(err);
}
//Let listeners know of this manager's value.
for (i = 0; (cb = listeners[i]); i++) {
cb(ret);
}
return undefined;
}
/**
* Helper that creates a callack function that is called when a dependency
* is ready, and sets the i-th dependency for the manager as the
* value passed to the callback generated by this function.
*/
function makeArgCallback(manager, i) {
return function (value) {
//Only do the work if it has not been done
//already for a dependency. Cycle breaking
//logic in forceExec could mean this function
//is called more than once for a given dependency.
if (!manager.depDone[i]) {
manager.depDone[i] = true;
manager.deps[i] = value;
manager.depCount -= 1;
if (!manager.depCount) {
//All done, execute!
execManager(manager);
}
}
};
}
function callPlugin(pluginName, depManager) {
var map = depManager.map,
fullName = map.fullName,
name = map.name,
plugin = plugins[pluginName] ||
(plugins[pluginName] = defined[pluginName]),
load;
//No need to continue if the manager is already
//in the process of loading.
if (depManager.loading) {
return;
}
depManager.loading = true;
load = function (ret) {
depManager.callback = function () {
return ret;
};
execManager(depManager);
loaded[depManager.id] = true;
//The loading of this plugin
//might have placed other things
//in the paused queue. In particular,
//a loader plugin that depends on
//a different plugin loaded resource.
resume();
};
//Allow plugins to load other code without having to know the
//context or how to "complete" the load.
load.fromText = function (moduleName, text) {
/*jslint evil: true */
var hasInteractive = useInteractive;
//Indicate a the module is in process of loading.
loaded[moduleName] = false;
context.scriptCount += 1;
//Indicate this is not a "real" module, so do not track it
//for builds, it does not map to a real file.
context.fake[moduleName] = true;
//Turn off interactive script matching for IE for any define
//calls in the text, then turn it back on at the end.
if (hasInteractive) {
useInteractive = false;
}
req.exec(text);
if (hasInteractive) {
useInteractive = true;
}
//Support anonymous modules.
context.completeLoad(moduleName);
};
//No need to continue if the plugin value has already been
//defined by a build.
if (fullName in defined) {
load(defined[fullName]);
} else {
//Use parentName here since the plugin's name is not reliable,
//could be some weird string with no path that actually wants to
//reference the parentName's path.
plugin.load(name, makeRequire(map.parentMap, true, function (deps, cb) {
var moduleDeps = [],
i, dep, depMap;
//Convert deps to full names and hold on to them
//for reference later, when figuring out if they
//are blocked by a circular dependency.
for (i = 0; (dep = deps[i]); i++) {
depMap = makeModuleMap(dep, map.parentMap);
deps[i] = depMap.fullName;
if (!depMap.prefix) {
moduleDeps.push(deps[i]);
}
}
depManager.moduleDeps = (depManager.moduleDeps || []).concat(moduleDeps);
return context.require(deps, cb);
}), load, config);
}
}
/**
* Adds the manager to the waiting queue. Only fully
* resolved items should be in the waiting queue.
*/
function addWait(manager) {
if (!waiting[manager.id]) {
waiting[manager.id] = manager;
waitAry.push(manager);
context.waitCount += 1;
}
}
/**
* Function added to every manager object. Created out here
* to avoid new function creation for each manager instance.
*/
function managerAdd(cb) {
this.listeners.push(cb);
}
function getManager(map, shouldQueue) {
var fullName = map.fullName,
prefix = map.prefix,
plugin = prefix ? plugins[prefix] ||
(plugins[prefix] = defined[prefix]) : null,
manager, created, pluginManager, prefixMap;
if (fullName) {
manager = managerCallbacks[fullName];
}
if (!manager) {
created = true;
manager = {
//ID is just the full name, but if it is a plugin resource
//for a plugin that has not been loaded,
//then add an ID counter to it.
id: (prefix && !plugin ?
(managerCounter++) + '__p@:' : '') +
(fullName || '__r@' + (managerCounter++)),
map: map,
depCount: 0,
depDone: [],
depCallbacks: [],
deps: [],
listeners: [],
add: managerAdd
};
specified[manager.id] = true;
//Only track the manager/reuse it if this is a non-plugin
//resource. Also only track plugin resources once
//the plugin has been loaded, and so the fullName is the
//true normalized value.
if (fullName && (!prefix || plugins[prefix])) {
managerCallbacks[fullName] = manager;
}
}
//If there is a plugin needed, but it is not loaded,
//first load the plugin, then continue on.
if (prefix && !plugin) {
prefixMap = makeModuleMap(prefix);
//Clear out defined and urlFetched if the plugin was previously
//loaded/defined, but not as full module (as in a build
//situation). However, only do this work if the plugin is in
//defined but does not have a module export value.
if (prefix in defined && !defined[prefix]) {
delete defined[prefix];
delete urlFetched[prefixMap.url];
}
pluginManager = getManager(prefixMap, true);
pluginManager.add(function (plugin) {
//Create a new manager for the normalized
//resource ID and have it call this manager when
//done.
var newMap = makeModuleMap(map.originalName, map.parentMap),
normalizedManager = getManager(newMap, true);
//Indicate this manager is a placeholder for the real,
//normalized thing. Important for when trying to map
//modules and dependencies, for instance, in a build.
manager.placeholder = true;
normalizedManager.add(function (resource) {
manager.callback = function () {
return resource;
};
execManager(manager);
});
});
} else if (created && shouldQueue) {
//Indicate the resource is not loaded yet if it is to be
//queued.
loaded[manager.id] = false;
queueDependency(manager);
addWait(manager);
}
return manager;
}
function main(inName, depArray, callback, relModuleMap) {
var moduleMap = makeModuleMap(inName, relModuleMap),
name = moduleMap.name,
fullName = moduleMap.fullName,
manager = getManager(moduleMap),
id = manager.id,
deps = manager.deps,
i, depArg, depName, depPrefix, cjsMod;
if (fullName) {
//If module already defined for context, or already loaded,
//then leave. Also leave if jQuery is registering but it does
//not match the desired version number in the config.
if (fullName in defined || loaded[id] === true ||
(fullName === "jquery" && config.jQuery &&
config.jQuery !== callback().fn.jquery)) {
return;
}
//Set specified/loaded here for modules that are also loaded
//as part of a layer, where onScriptLoad is not fired
//for those cases. Do this after the inline define and
//dependency tracing is done.
specified[id] = true;
loaded[id] = true;
//If module is jQuery set up delaying its dom ready listeners.
if (fullName === "jquery" && callback) {
jQueryCheck(callback());
}
}
//Attach real depArray and callback to the manager. Do this
//only if the module has not been defined already, so do this after
//the fullName checks above. IE can call main() more than once
//for a module.
manager.depArray = depArray;
manager.callback = callback;
//Add the dependencies to the deps field, and register for callbacks
//on the dependencies.
for (i = 0; i < depArray.length; i++) {
depArg = depArray[i];
//There could be cases like in IE, where a trailing comma will
//introduce a null dependency, so only treat a real dependency
//value as a dependency.
if (depArg) {
//Split the dependency name into plugin and name parts
depArg = makeModuleMap(depArg, (name ? moduleMap : relModuleMap));
depName = depArg.fullName;
depPrefix = depArg.prefix;
//Fix the name in depArray to be just the name, since
//that is how it will be called back later.
depArray[i] = depName;
//Fast path CommonJS standard dependencies.
if (depName === "require") {
deps[i] = makeRequire(moduleMap);
} else if (depName === "exports") {
//CommonJS module spec 1.1
deps[i] = defined[fullName] = {};
manager.usingExports = true;
} else if (depName === "module") {
//CommonJS module spec 1.1
manager.cjsModule = cjsMod = deps[i] = {
id: name,
uri: name ? context.nameToUrl(name, null, relModuleMap) : undefined,
exports: defined[fullName]
};
} else if (depName in defined && !(depName in waiting) &&
(!(fullName in needFullExec) ||
(fullName in needFullExec && fullExec[depName]))) {
//Module already defined, and not in a build situation
//where the module is a something that needs full
//execution and this dependency has not been fully
//executed. See r.js's requirePatch.js for more info
//on fullExec.
deps[i] = defined[depName];
} else {
//Mark this dependency as needing full exec if
//the current module needs full exec.
if (fullName in needFullExec) {
needFullExec[depName] = true;
//Reset state so fully executed code will get
//picked up correctly.
delete defined[depName];
urlFetched[depArg.url] = false;
}
//Either a resource that is not loaded yet, or a plugin
//resource for either a plugin that has not
//loaded yet.
manager.depCount += 1;
manager.depCallbacks[i] = makeArgCallback(manager, i);
getManager(depArg, true).add(manager.depCallbacks[i]);
}
}
}
//Do not bother tracking the manager if it is all done.
if (!manager.depCount) {
//All done, execute!
execManager(manager);
} else {
addWait(manager);
}
}
/**
* Convenience method to call main for a define call that was put on
* hold in the defQueue.
*/
function callDefMain(args) {
main.apply(null, args);
}
/**
* jQuery 1.4.3+ supports ways to hold off calling
* calling jQuery ready callbacks until all scripts are loaded. Be sure
* to track it if the capability exists.. Also, since jQuery 1.4.3 does
* not register as a module, need to do some global inference checking.
* Even if it does register as a module, not guaranteed to be the precise
* name of the global. If a jQuery is tracked for this context, then go
* ahead and register it as a module too, if not already in process.
*/
jQueryCheck = function (jqCandidate) {
if (!context.jQuery) {
var $ = jqCandidate || (typeof jQuery !== "undefined" ? jQuery : null);
if ($) {
//If a specific version of jQuery is wanted, make sure to only
//use this jQuery if it matches.
if (config.jQuery && $.fn.jquery !== config.jQuery) {
return;
}
if ("holdReady" in $ || "readyWait" in $) {
context.jQuery = $;
//Manually create a "jquery" module entry if not one already
//or in process. Note this could trigger an attempt at
//a second jQuery registration, but does no harm since
//the first one wins, and it is the same value anyway.
callDefMain(["jquery", [], function () {
return jQuery;
}]);
//Ask jQuery to hold DOM ready callbacks.
if (context.scriptCount) {
jQueryHoldReady($, true);
context.jQueryIncremented = true;
}
}
}
}
};
function findCycle(manager, traced) {
var fullName = manager.map.fullName,
depArray = manager.depArray,
fullyLoaded = true,
i, depName, depManager, result;
if (manager.isDone || !fullName || !loaded[fullName]) {
return result;
}
//Found the cycle.
if (traced[fullName]) {
return manager;
}
traced[fullName] = true;
//Trace through the dependencies.
if (depArray) {
for (i = 0; i < depArray.length; i++) {
//Some array members may be null, like if a trailing comma
//IE, so do the explicit [i] access and check if it has a value.
depName = depArray[i];
if (!loaded[depName] && !reservedDependencies[depName]) {
fullyLoaded = false;
break;
}
depManager = waiting[depName];
if (depManager && !depManager.isDone && loaded[depName]) {
result = findCycle(depManager, traced);
if (result) {
break;
}
}
}
if (!fullyLoaded) {
//Discard the cycle that was found, since it cannot
//be forced yet. Also clear this module from traced.
result = undefined;
delete traced[fullName];
}
}
return result;
}
function forceExec(manager, traced) {
var fullName = manager.map.fullName,
depArray = manager.depArray,
i, depName, depManager, prefix, prefixManager, value;
if (manager.isDone || !fullName || !loaded[fullName]) {
return undefined;
}
if (fullName) {
if (traced[fullName]) {
return defined[fullName];
}
traced[fullName] = true;
}
//Trace through the dependencies.
if (depArray) {
for (i = 0; i < depArray.length; i++) {
//Some array members may be null, like if a trailing comma
//IE, so do the explicit [i] access and check if it has a value.
depName = depArray[i];
if (depName) {
//First, make sure if it is a plugin resource that the
//plugin is not blocked.
prefix = makeModuleMap(depName).prefix;
if (prefix && (prefixManager = waiting[prefix])) {
forceExec(prefixManager, traced);
}
depManager = waiting[depName];
if (depManager && !depManager.isDone && loaded[depName]) {
value = forceExec(depManager, traced);
manager.depCallbacks[i](value);
}
}
}
}
return defined[fullName];
}
/**
* Checks if all modules for a context are loaded, and if so, evaluates the
* new ones in right dependency order.
*
* @private
*/
function checkLoaded() {
var waitInterval = config.waitSeconds * 1000,
//It is possible to disable the wait interval by using waitSeconds of 0.
expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
noLoads = "", hasLoadedProp = false, stillLoading = false,
cycleDeps = [],
i, prop, err, manager, cycleManager, moduleDeps;
//If there are items still in the paused queue processing wait.
//This is particularly important in the sync case where each paused
//item is processed right away but there may be more waiting.
if (context.pausedCount > 0) {
return undefined;
}
//Determine if priority loading is done. If so clear the priority. If
//not, then do not check
if (config.priorityWait) {
if (isPriorityDone()) {
//Call resume, since it could have
//some waiting dependencies to trace.
resume();
} else {
return undefined;
}
}
//See if anything is still in flight.
for (prop in loaded) {
if (!(prop in empty)) {
hasLoadedProp = true;
if (!loaded[prop]) {
if (expired) {
noLoads += prop + " ";
} else {
stillLoading = true;
if (prop.indexOf('!') === -1) {
//No reason to keep looking for unfinished
//loading. If the only stillLoading is a
//plugin resource though, keep going,
//because it may be that a plugin resource
//is waiting on a non-plugin cycle.
cycleDeps = [];
break;
} else {
moduleDeps = managerCallbacks[prop] && managerCallbacks[prop].moduleDeps;
if (moduleDeps) {
cycleDeps.push.apply(cycleDeps, moduleDeps);
}
}
}
}
}
}
//Check for exit conditions.
if (!hasLoadedProp && !context.waitCount) {
//If the loaded object had no items, then the rest of
//the work below does not need to be done.
return undefined;
}
if (expired && noLoads) {
//If wait time expired, throw error of unloaded modules.
err = makeError("timeout", "Load timeout for modules: " + noLoads);
err.requireType = "timeout";
err.requireModules = noLoads;
err.contextName = context.contextName;
return req.onError(err);
}
//If still loading but a plugin is waiting on a regular module cycle
//break the cycle.
if (stillLoading && cycleDeps.length) {
for (i = 0; (manager = waiting[cycleDeps[i]]); i++) {
if ((cycleManager = findCycle(manager, {}))) {
forceExec(cycleManager, {});
break;
}
}
}
//If still waiting on loads, and the waiting load is something
//other than a plugin resource, or there are still outstanding
//scripts, then just try back later.
if (!expired && (stillLoading || context.scriptCount)) {
//Something is still waiting to load. Wait for it, but only
//if a timeout is not already in effect.
if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {
checkLoadedTimeoutId = setTimeout(function () {
checkLoadedTimeoutId = 0;
checkLoaded();
}, 50);
}
return undefined;
}
//If still have items in the waiting cue, but all modules have
//been loaded, then it means there are some circular dependencies
//that need to be broken.
//However, as a waiting thing is fired, then it can add items to
//the waiting cue, and those items should not be fired yet, so
//make sure to redo the checkLoaded call after breaking a single
//cycle, if nothing else loaded then this logic will pick it up
//again.
if (context.waitCount) {
//Cycle through the waitAry, and call items in sequence.
for (i = 0; (manager = waitAry[i]); i++) {
forceExec(manager, {});
}
//If anything got placed in the paused queue, run it down.
if (context.paused.length) {
resume();
}
//Only allow this recursion to a certain depth. Only
//triggered by errors in calling a module in which its
//modules waiting on it cannot finish loading, or some circular
//dependencies that then may add more dependencies.
//The value of 5 is a bit arbitrary. Hopefully just one extra
//pass, or two for the case of circular dependencies generating
//more work that gets resolved in the sync node case.
if (checkLoadedDepth < 5) {
checkLoadedDepth += 1;
checkLoaded();
}
}
checkLoadedDepth = 0;
//Check for DOM ready, and nothing is waiting across contexts.
req.checkReadyState();
return undefined;
}
/**
* Resumes tracing of dependencies and then checks if everything is loaded.
*/
resume = function () {
var manager, map, url, i, p, args, fullName;
//Any defined modules in the global queue, intake them now.
context.takeGlobalQueue();
resumeDepth += 1;
if (context.scriptCount <= 0) {
//Synchronous envs will push the number below zero with the
//decrement above, be sure to set it back to zero for good measure.
//require() calls that also do not end up loading scripts could
//push the number negative too.
context.scriptCount = 0;
}
//Make sure any remaining defQueue items get properly processed.
while (defQueue.length) {
args = defQueue.shift();
if (args[0] === null) {
return req.onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));
} else {
callDefMain(args);
}
}
//Skip the resume of paused dependencies
//if current context is in priority wait.
if (!config.priorityWait || isPriorityDone()) {
while (context.paused.length) {
p = context.paused;
context.pausedCount += p.length;
//Reset paused list
context.paused = [];
for (i = 0; (manager = p[i]); i++) {
map = manager.map;
url = map.url;
fullName = map.fullName;
//If the manager is for a plugin managed resource,
//ask the plugin to load it now.
if (map.prefix) {
callPlugin(map.prefix, manager);
} else {
//Regular dependency.
if (!urlFetched[url] && !loaded[fullName]) {
req.load(context, fullName, url);
//Mark the URL as fetched, but only if it is
//not an empty: URL, used by the optimizer.
//In that case we need to be sure to call
//load() for each module that is mapped to
//empty: so that dependencies are satisfied
//correctly.
if (url.indexOf('empty:') !== 0) {
urlFetched[url] = true;
}
}
}
}
//Move the start time for timeout forward.
context.startTime = (new Date()).getTime();
context.pausedCount -= p.length;
}
}
//Only check if loaded when resume depth is 1. It is likely that
//it is only greater than 1 in sync environments where a factory
//function also then calls the callback-style require. In those
//cases, the checkLoaded should not occur until the resume
//depth is back at the top level.
if (resumeDepth === 1) {
checkLoaded();
}
resumeDepth -= 1;
return undefined;
};
//Define the context object. Many of these fields are on here
//just to make debugging easier.
context = {
contextName: contextName,
config: config,
defQueue: defQueue,
waiting: waiting,
waitCount: 0,
specified: specified,
loaded: loaded,
urlMap: urlMap,
urlFetched: urlFetched,
scriptCount: 0,
defined: defined,
paused: [],
pausedCount: 0,
plugins: plugins,
needFullExec: needFullExec,
fake: {},
fullExec: fullExec,
managerCallbacks: managerCallbacks,
makeModuleMap: makeModuleMap,
normalize: normalize,
/**
* Set a configuration for the context.
* @param {Object} cfg config object to integrate.
*/
configure: function (cfg) {
var paths, prop, packages, pkgs, packagePaths, requireWait;
//Make sure the baseUrl ends in a slash.
if (cfg.baseUrl) {
if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== "/") {
cfg.baseUrl += "/";
}
}
//Save off the paths and packages since they require special processing,
//they are additive.
paths = config.paths;
packages = config.packages;
pkgs = config.pkgs;
//Mix in the config values, favoring the new values over
//existing ones in context.config.
mixin(config, cfg, true);
//Adjust paths if necessary.
if (cfg.paths) {
for (prop in cfg.paths) {
if (!(prop in empty)) {
paths[prop] = cfg.paths[prop];
}
}
config.paths = paths;
}
packagePaths = cfg.packagePaths;
if (packagePaths || cfg.packages) {
//Convert packagePaths into a packages config.
if (packagePaths) {
for (prop in packagePaths) {
if (!(prop in empty)) {
configurePackageDir(pkgs, packagePaths[prop], prop);
}
}
}
//Adjust packages if necessary.
if (cfg.packages) {
configurePackageDir(pkgs, cfg.packages);
}
//Done with modifications, assing packages back to context config
config.pkgs = pkgs;
}
//If priority loading is in effect, trigger the loads now
if (cfg.priority) {
//Hold on to requireWait value, and reset it after done
requireWait = context.requireWait;
//Allow tracing some require calls to allow the fetching
//of the priority config.
context.requireWait = false;
//But first, call resume to register any defined modules that may
//be in a data-main built file before the priority config
//call.
resume();
context.require(cfg.priority);
//Trigger a resume right away, for the case when
//the script with the priority load is done as part
//of a data-main call. In that case the normal resume
//call will not happen because the scriptCount will be
//at 1, since the script for data-main is being processed.
resume();
//Restore previous state.
context.requireWait = requireWait;
config.priorityWait = cfg.priority;
}
//If a deps array or a config callback is specified, then call
//require with those args. This is useful when require is defined as a
//config object before require.js is loaded.
if (cfg.deps || cfg.callback) {
context.require(cfg.deps || [], cfg.callback);
}
},
requireDefined: function (moduleName, relModuleMap) {
return makeModuleMap(moduleName, relModuleMap).fullName in defined;
},
requireSpecified: function (moduleName, relModuleMap) {
return makeModuleMap(moduleName, relModuleMap).fullName in specified;
},
require: function (deps, callback, relModuleMap) {
var moduleName, fullName, moduleMap;
if (typeof deps === "string") {
if (isFunction(callback)) {
//Invalid call
return req.onError(makeError("requireargs", "Invalid require call"));
}
//Synchronous access to one module. If require.get is
//available (as in the Node adapter), prefer that.
//In this case deps is the moduleName and callback is
//the relModuleMap
if (req.get) {
return req.get(context, deps, callback);
}
//Just return the module wanted. In this scenario, the
//second arg (if passed) is just the relModuleMap.
moduleName = deps;
relModuleMap = callback;
//Normalize module name, if it contains . or ..
moduleMap = makeModuleMap(moduleName, relModuleMap);
fullName = moduleMap.fullName;
if (!(fullName in defined)) {
return req.onError(makeError("notloaded", "Module name '" +
moduleMap.fullName +
"' has not been loaded yet for context: " +
contextName));
}
return defined[fullName];
}
//Call main but only if there are dependencies or
//a callback to call.
if (deps && deps.length || callback) {
main(null, deps, callback, relModuleMap);
}
//If the require call does not trigger anything new to load,
//then resume the dependency processing.
if (!context.requireWait) {
while (!context.scriptCount && context.paused.length) {
resume();
}
}
return context.require;
},
/**
* Internal method to transfer globalQueue items to this context's
* defQueue.
*/
takeGlobalQueue: function () {
//Push all the globalDefQueue items into the context's defQueue
if (globalDefQueue.length) {
//Array splice in the values since the context code has a
//local var ref to defQueue, so cannot just reassign the one
//on context.
apsp.apply(context.defQueue,
[context.defQueue.length - 1, 0].concat(globalDefQueue));
globalDefQueue = [];
}
},
/**
* Internal method used by environment adapters to complete a load event.
* A load event could be a script load or just a load pass from a synchronous
* load call.
* @param {String} moduleName the name of the module to potentially complete.
*/
completeLoad: function (moduleName) {
var args;
context.takeGlobalQueue();
while (defQueue.length) {
args = defQueue.shift();
if (args[0] === null) {
args[0] = moduleName;
break;
} else if (args[0] === moduleName) {
//Found matching define call for this script!
break;
} else {
//Some other named define call, most likely the result
//of a build layer that included many define calls.
callDefMain(args);
args = null;
}
}
if (args) {
callDefMain(args);
} else {
//A script that does not call define(), so just simulate
//the call for it. Special exception for jQuery dynamic load.
callDefMain([moduleName, [],
moduleName === "jquery" && typeof jQuery !== "undefined" ?
function () {
return jQuery;
} : null]);
}
//Doing this scriptCount decrement branching because sync envs
//need to decrement after resume, otherwise it looks like
//loading is complete after the first dependency is fetched.
//For browsers, it works fine to decrement after, but it means
//the checkLoaded setTimeout 50 ms cost is taken. To avoid
//that cost, decrement beforehand.
if (req.isAsync) {
context.scriptCount -= 1;
}
resume();
if (!req.isAsync) {
context.scriptCount -= 1;
}
},
/**
* Converts a module name + .extension into an URL path.
* *Requires* the use of a module name. It does not support using
* plain URLs like nameToUrl.
*/
toUrl: function (moduleNamePlusExt, relModuleMap) {
var index = moduleNamePlusExt.lastIndexOf("."),
ext = null;
if (index !== -1) {
ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
}
return context.nameToUrl(moduleNamePlusExt, ext, relModuleMap);
},
/**
* Converts a module name to a file path. Supports cases where
* moduleName may actually be just an URL.
*/
nameToUrl: function (moduleName, ext, relModuleMap) {
var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,
config = context.config;
//Normalize module name if have a base relative module name to work from.
moduleName = normalize(moduleName, relModuleMap && relModuleMap.fullName);
//If a colon is in the URL, it indicates a protocol is used and it is just
//an URL to a file, or if it starts with a slash or ends with .js, it is just a plain file.
//The slash is important for protocol-less URLs as well as full paths.
if (req.jsExtRegExp.test(moduleName)) {
//Just a plain path, not module name lookup, so just return it.
//Add extension if it is included. This is a bit wonky, only non-.js things pass
//an extension, this method probably needs to be reworked.
url = moduleName + (ext ? ext : "");
} else {
//A module that needs to be converted to a path.
paths = config.paths;
pkgs = config.pkgs;
syms = moduleName.split("/");
//For each module name segment, see if there is a path
//registered for it. Start with most specific name
//and work up from it.
for (i = syms.length; i > 0; i--) {
parentModule = syms.slice(0, i).join("/");
if (paths[parentModule]) {
syms.splice(0, i, paths[parentModule]);
break;
} else if ((pkg = pkgs[parentModule])) {
//If module name is just the package name, then looking
//for the main module.
if (moduleName === pkg.name) {
pkgPath = pkg.location + '/' + pkg.main;
} else {
pkgPath = pkg.location;
}
syms.splice(0, i, pkgPath);
break;
}
}
//Join the path parts together, then figure out if baseUrl is needed.
url = syms.join("/") + (ext || ".js");
url = (url.charAt(0) === '/' || url.match(/^\w+:/) ? "" : config.baseUrl) + url;
}
return config.urlArgs ? url +
((url.indexOf('?') === -1 ? '?' : '&') +
config.urlArgs) : url;
}
};
//Make these visible on the context so can be called at the very
//end of the file to bootstrap
context.jQueryCheck = jQueryCheck;
context.resume = resume;
return context;
}
/**
* Main entry point.
*
* If the only argument to require is a string, then the module that
* is represented by that string is fetched for the appropriate context.
*
* If the first argument is an array, then it will be treated as an array
* of dependency string names to fetch. An optional function callback can
* be specified to execute when all of those dependencies are available.
*
* Make a local req variable to help Caja compliance (it assumes things
* on a require that are not standardized), and to give a short
* name for minification/local scope use.
*/
req = requirejs = function (deps, callback) {
//Find the right context, use default
var contextName = defContextName,
context, config;
// Determine if have config object in the call.
if (!isArray(deps) && typeof deps !== "string") {
// deps is a config object
config = deps;
if (isArray(callback)) {
// Adjust args if there are dependencies
deps = callback;
callback = arguments[2];
} else {
deps = [];
}
}
if (config && config.context) {
contextName = config.context;
}
context = contexts[contextName] ||
(contexts[contextName] = newContext(contextName));
if (config) {
context.configure(config);
}
return context.require(deps, callback);
};
/**
* Support require.config() to make it easier to cooperate with other
* AMD loaders on globally agreed names.
*/
req.config = function (config) {
return req(config);
};
/**
* Export require as a global, but only if it does not already exist.
*/
if (!require) {
require = req;
}
/**
* Global require.toUrl(), to match global require, mostly useful
* for debugging/work in the global space.
*/
req.toUrl = function (moduleNamePlusExt) {
return contexts[defContextName].toUrl(moduleNamePlusExt);
};
req.version = version;
//Used to filter out dependencies that are already paths.
req.jsExtRegExp = /^\/|:|\?|\.js$/;
s = req.s = {
contexts: contexts,
//Stores a list of URLs that should not get async script tag treatment.
skipAsync: {}
};
req.isAsync = req.isBrowser = isBrowser;
if (isBrowser) {
head = s.head = document.getElementsByTagName("head")[0];
//If BASE tag is in play, using appendChild is a problem for IE6.
//When that browser dies, this can be removed. Details in this jQuery bug:
//http://dev.jquery.com/ticket/2709
baseElement = document.getElementsByTagName("base")[0];
if (baseElement) {
head = s.head = baseElement.parentNode;
}
}
/**
* Any errors that require explicitly generates will be passed to this
* function. Intercept/override it if you want custom error handling.
* @param {Error} err the error object.
*/
req.onError = function (err) {
throw err;
};
/**
* Does the request to load a module for the browser case.
* Make this a separate function to allow other environments
* to override it.
*
* @param {Object} context the require context to find state.
* @param {String} moduleName the name of the module.
* @param {Object} url the URL to the module.
*/
req.load = function (context, moduleName, url) {
req.resourcesReady(false);
context.scriptCount += 1;
req.attach(url, context, moduleName);
//If tracking a jQuery, then make sure its ready callbacks
//are put on hold to prevent its ready callbacks from
//triggering too soon.
if (context.jQuery && !context.jQueryIncremented) {
jQueryHoldReady(context.jQuery, true);
context.jQueryIncremented = true;
}
};
function getInteractiveScript() {
var scripts, i, script;
if (interactiveScript && interactiveScript.readyState === 'interactive') {
return interactiveScript;
}
scripts = document.getElementsByTagName('script');
for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) {
if (script.readyState === 'interactive') {
return (interactiveScript = script);
}
}
return null;
}
/**
* The function that handles definitions of modules. Differs from
* require() in that a string for the module should be the first argument,
* and the function to execute after dependencies are loaded should
* return a value to define the module corresponding to the first argument's
* name.
*/
define = function (name, deps, callback) {
var node, context;
//Allow for anonymous functions
if (typeof name !== 'string') {
//Adjust args appropriately
callback = deps;
deps = name;
name = null;
}
//This module may not have dependencies
if (!isArray(deps)) {
callback = deps;
deps = [];
}
//If no name, and callback is a function, then figure out if it a
//CommonJS thing with dependencies.
if (!deps.length && isFunction(callback)) {
//Remove comments from the callback string,
//look for require calls, and pull them into the dependencies,
//but only if there are function args.
if (callback.length) {
callback
.toString()
.replace(commentRegExp, "")
.replace(cjsRequireRegExp, function (match, dep) {
deps.push(dep);
});
//May be a CommonJS thing even without require calls, but still
//could use exports, and module. Avoid doing exports and module
//work though if it just needs require.
//REQUIRES the function to expect the CommonJS variables in the
//order listed below.
deps = (callback.length === 1 ? ["require"] : ["require", "exports", "module"]).concat(deps);
}
}
//If in IE 6-8 and hit an anonymous define() call, do the interactive
//work.
if (useInteractive) {
node = currentlyAddingScript || getInteractiveScript();
if (node) {
if (!name) {
name = node.getAttribute("data-requiremodule");
}
context = contexts[node.getAttribute("data-requirecontext")];
}
}
//Always save off evaluating the def call until the script onload handler.
//This allows multiple modules to be in a file without prematurely
//tracing dependencies, and allows for anonymous module support,
//where the module name is not known until the script onload event
//occurs. If no context, use the global queue, and get it processed
//in the onscript load callback.
(context ? context.defQueue : globalDefQueue).push([name, deps, callback]);
return undefined;
};
define.amd = {
multiversion: true,
plugins: true,
jQuery: true
};
/**
* Executes the text. Normally just uses eval, but can be modified
* to use a more environment specific call.
* @param {String} text the text to execute/evaluate.
*/
req.exec = function (text) {
return eval(text);
};
/**
* Executes a module callack function. Broken out as a separate function
* solely to allow the build system to sequence the files in the built
* layer in the right sequence.
*
* @private
*/
req.execCb = function (name, callback, args, exports) {
return callback.apply(exports, args);
};
/**
* Adds a node to the DOM. Public function since used by the order plugin.
* This method should not normally be called by outside code.
*/
req.addScriptToDom = function (node) {
//For some cache cases in IE 6-8, the script executes before the end
//of the appendChild execution, so to tie an anonymous define
//call to the module name (which is stored on the node), hold on
//to a reference to this node, but clear after the DOM insertion.
currentlyAddingScript = node;
if (baseElement) {
head.insertBefore(node, baseElement);
} else {
head.appendChild(node);
}
currentlyAddingScript = null;
};
/**
* callback for script loads, used to check status of loading.
*
* @param {Event} evt the event from the browser for the script
* that was loaded.
*
* @private
*/
req.onScriptLoad = function (evt) {
//Using currentTarget instead of target for Firefox 2.0's sake. Not
//all old browsers will be supported, but this one was easy enough
//to support and still makes sense.
var node = evt.currentTarget || evt.srcElement, contextName, moduleName,
context;
if (evt.type === "load" || (node && readyRegExp.test(node.readyState))) {
//Reset interactive script so a script node is not held onto for
//to long.
interactiveScript = null;
//Pull out the name of the module and the context.
contextName = node.getAttribute("data-requirecontext");
moduleName = node.getAttribute("data-requiremodule");
context = contexts[contextName];
contexts[contextName].completeLoad(moduleName);
//Clean up script binding. Favor detachEvent because of IE9
//issue, see attachEvent/addEventListener comment elsewhere
//in this file.
if (node.detachEvent && !isOpera) {
//Probably IE. If not it will throw an error, which will be
//useful to know.
node.detachEvent("onreadystatechange", req.onScriptLoad);
} else {
node.removeEventListener("load", req.onScriptLoad, false);
}
}
};
/**
* Attaches the script represented by the URL to the current
* environment. Right now only supports browser loading,
* but can be redefined in other environments to do the right thing.
* @param {String} url the url of the script to attach.
* @param {Object} context the context that wants the script.
* @param {moduleName} the name of the module that is associated with the script.
* @param {Function} [callback] optional callback, defaults to require.onScriptLoad
* @param {String} [type] optional type, defaults to text/javascript
* @param {Function} [fetchOnlyFunction] optional function to indicate the script node
* should be set up to fetch the script but do not attach it to the DOM
* so that it can later be attached to execute it. This is a way for the
* order plugin to support ordered loading in IE. Once the script is fetched,
* but not executed, the fetchOnlyFunction will be called.
*/
req.attach = function (url, context, moduleName, callback, type, fetchOnlyFunction) {
var node;
if (isBrowser) {
//In the browser so use a script tag
callback = callback || req.onScriptLoad;
node = context && context.config && context.config.xhtml ?
document.createElementNS("http://www.w3.org/1999/xhtml", "html:script") :
document.createElement("script");
node.type = type || (context && context.config.scriptType) ||
"text/javascript";
node.charset = "utf-8";
//Use async so Gecko does not block on executing the script if something
//like a long-polling comet tag is being run first. Gecko likes
//to evaluate scripts in DOM order, even for dynamic scripts.
//It will fetch them async, but only evaluate the contents in DOM
//order, so a long-polling script tag can delay execution of scripts
//after it. But telling Gecko we expect async gets us the behavior
//we want -- execute it whenever it is finished downloading. Only
//Helps Firefox 3.6+
//Allow some URLs to not be fetched async. Mostly helps the order!
//plugin
node.async = !s.skipAsync[url];
if (context) {
node.setAttribute("data-requirecontext", context.contextName);
}
node.setAttribute("data-requiremodule", moduleName);
//Set up load listener. Test attachEvent first because IE9 has
//a subtle issue in its addEventListener and script onload firings
//that do not match the behavior of all other browsers with
//addEventListener support, which fire the onload event for a
//script right after the script execution. See:
//https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution
//UNFORTUNATELY Opera implements attachEvent but does not follow the script
//script execution mode.
if (node.attachEvent && !isOpera) {
//Probably IE. IE (at least 6-8) do not fire
//script onload right after executing the script, so
//we cannot tie the anonymous define call to a name.
//However, IE reports the script as being in "interactive"
//readyState at the time of the define call.
useInteractive = true;
if (fetchOnlyFunction) {
//Need to use old school onreadystate here since
//when the event fires and the node is not attached
//to the DOM, the evt.srcElement is null, so use
//a closure to remember the node.
node.onreadystatechange = function (evt) {
//Script loaded but not executed.
//Clear loaded handler, set the real one that
//waits for script execution.
if (node.readyState === 'loaded') {
node.onreadystatechange = null;
node.attachEvent("onreadystatechange", callback);
fetchOnlyFunction(node);
}
};
} else {
node.attachEvent("onreadystatechange", callback);
}
} else {
node.addEventListener("load", callback, false);
}
node.src = url;
//Fetch only means waiting to attach to DOM after loaded.
if (!fetchOnlyFunction) {
req.addScriptToDom(node);
}
return node;
} else if (isWebWorker) {
//In a web worker, use importScripts. This is not a very
//efficient use of importScripts, importScripts will block until
//its script is downloaded and evaluated. However, if web workers
//are in play, the expectation that a build has been done so that
//only one script needs to be loaded anyway. This may need to be
//reevaluated if other use cases become common.
importScripts(url);
//Account for anonymous modules
context.completeLoad(moduleName);
}
return null;
};
//Look for a data-main script attribute, which could also adjust the baseUrl.
if (isBrowser) {
//Figure out baseUrl. Get it from the script tag with require.js in it.
scripts = document.getElementsByTagName("script");
for (globalI = scripts.length - 1; globalI > -1 && (script = scripts[globalI]); globalI--) {
//Set the "head" where we can append children by
//using the script's parent.
if (!head) {
head = script.parentNode;
}
//Look for a data-main attribute to set main script for the page
//to load. If it is there, the path to data main becomes the
//baseUrl, if it is not already set.
if ((dataMain = script.getAttribute('data-main'))) {
if (!cfg.baseUrl) {
//Pull off the directory of data-main for use as the
//baseUrl.
src = dataMain.split('/');
mainScript = src.pop();
subPath = src.length ? src.join('/') + '/' : './';
//Set final config.
cfg.baseUrl = subPath;
//Strip off any trailing .js since dataMain is now
//like a module name.
dataMain = mainScript.replace(jsSuffixRegExp, '');
}
//Put the data-main script in the files to load.
cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain];
break;
}
}
}
//See if there is nothing waiting across contexts, and if not, trigger
//resourcesReady.
req.checkReadyState = function () {
var contexts = s.contexts, prop;
for (prop in contexts) {
if (!(prop in empty)) {
if (contexts[prop].waitCount) {
return;
}
}
}
req.resourcesReady(true);
};
/**
* Internal function that is triggered whenever all scripts/resources
* have been loaded by the loader. Can be overridden by other, for
* instance the domReady plugin, which wants to know when all resources
* are loaded.
*/
req.resourcesReady = function (isReady) {
var contexts, context, prop;
//First, set the public variable indicating that resources are loading.
req.resourcesDone = isReady;
if (req.resourcesDone) {
//If jQuery with DOM ready delayed, release it now.
contexts = s.contexts;
for (prop in contexts) {
if (!(prop in empty)) {
context = contexts[prop];
if (context.jQueryIncremented) {
jQueryHoldReady(context.jQuery, false);
context.jQueryIncremented = false;
}
}
}
}
};
//FF < 3.6 readyState fix. Needed so that domReady plugin
//works well in that environment, since require.js is normally
//loaded via an HTML script tag so it will be there before window load,
//where the domReady plugin is more likely to be loaded after window load.
req.pageLoaded = function () {
if (document.readyState !== "complete") {
document.readyState = "complete";
}
};
if (isBrowser) {
if (document.addEventListener) {
if (!document.readyState) {
document.readyState = "loading";
window.addEventListener("load", req.pageLoaded, false);
}
}
}
//Set up default context. If require was a configuration object, use that as base config.
req(cfg);
//If modules are built into require.js, then need to make sure dependencies are
//traced. Use a setTimeout in the browser world, to allow all the modules to register
//themselves. In a non-browser env, assume that modules are not built into require.js,
//which seems odd to do on the server.
if (req.isAsync && typeof setTimeout !== "undefined") {
ctx = s.contexts[(cfg.context || defContextName)];
//Indicate that the script that includes require() is still loading,
//so that require()'d dependencies are not traced until the end of the
//file is parsed (approximated via the setTimeout call).
ctx.requireWait = true;
setTimeout(function () {
ctx.requireWait = false;
if (!ctx.scriptCount) {
ctx.resume();
}
req.checkReadyState();
}, 0);
}
}());
// Underscore.js 1.3.1
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore is freely distributable under the MIT license.
// Portions of Underscore are inspired or borrowed from Prototype,
// Oliver Steele's Functional, and John Resig's Micro-Templating.
// For all details and documentation:
// http://documentcloud.github.com/underscore
(function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,
h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each=
b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(e in a&&c.call(d,a[e],e,a)===n)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===n)break};b.map=b.collect=function(a,c,b){var e=[];if(a==null)return e;if(x&&a.map===x)return a.map(c,b);j(a,function(a,g,h){e[e.length]=c.call(b,a,g,h)});if(a.length===+a.length)e.length=a.length;return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a==
null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=
function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e=
e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=
function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&&(e={value:a,computed:b})});
return e.value};b.shuffle=function(a){var b=[],d;j(a,function(a,f){f==0?b[0]=a:(d=Math.floor(Math.random()*(f+1)),b[f]=b[d],b[d]=a)});return b};b.sortBy=function(a,c,d){return b.pluck(b.map(a,function(a,b,g){return{value:a,criteria:c.call(d,a,b,g)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c<d?-1:c>d?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,
c,d){d||(d=b.identity);for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:a.toArray?a.toArray():b.isArray(a)?i.call(a):b.isArguments(a)?i.call(a):b.values(a)};b.size=function(a){return b.toArray(a).length};b.first=b.head=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};b.initial=function(a,b,d){return i.call(a,0,a.length-(b==null||d?1:b))};b.last=function(a,b,d){return b!=null&&!d?i.call(a,Math.max(a.length-b,0)):a[a.length-1]};b.rest=
b.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};b.compact=function(a){return b.filter(a,function(a){return!!a})};b.flatten=function(a,c){return b.reduce(a,function(a,e){if(b.isArray(e))return a.concat(c?e:b.flatten(e));a[a.length]=e;return a},[])};b.without=function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,e=[];b.reduce(d,function(d,g,h){if(0==h||(c===true?b.last(d)!=g:!b.include(d,g)))d[d.length]=g,e[e.length]=a[h];return d},[]);
return e};b.union=function(){return b.uniq(b.flatten(arguments,true))};b.intersection=b.intersect=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,c,
d){if(a==null)return-1;var e;if(d)return d=b.sortedIndex(a,c),a[d]===c?d:-1;if(p&&a.indexOf===p)return a.indexOf(c);for(d=0,e=a.length;d<e;d++)if(d in a&&a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(D&&a.lastIndexOf===D)return a.lastIndexOf(b);for(var d=a.length;d--;)if(d in a&&a[d]===b)return d;return-1};b.range=function(a,b,d){arguments.length<=1&&(b=a||0,a=0);for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;)g[f++]=a,a+=d;return g};
var F=function(){};b.bind=function(a,c){var d,e;if(a.bind===s&&s)return s.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));F.prototype=a.prototype;var b=new F,g=a.apply(b,e.concat(i.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,
c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(a,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,h,i=b.debounce(function(){h=g=false},c);return function(){d=this;e=arguments;var b;f||(f=setTimeout(function(){f=null;h&&a.apply(d,e);i()},c));g?h=true:
a.apply(d,e);i();g=true}};b.debounce=function(a,b){var d;return function(){var e=this,f=arguments;clearTimeout(d);d=setTimeout(function(){d=null;a.apply(e,f)},b)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments,0));return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};
b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments,
1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};
b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};
b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.escape=function(a){return(""+a).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;")};b.mixin=function(a){j(b.functions(a),
function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+
u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]=
function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=
true;return this};m.prototype.value=function(){return this._wrapped}}).call(this);
This source diff could not be displayed because it is too large. You can view the blob instead.
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