forked from riot/riot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
riot.js
133 lines (95 loc) · 2.76 KB
/
riot.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
Riot.js 0.9.4 | moot.it/riotjs | @license MIT
(c) 2013 Tero Piirainen, Moot Inc and other contributors.
*/
(function(top) { "use strict";
var $ = top.$ = top.$ || {};
// avoid multiple execution. popstate should be fired only once etc.
if ($.riot) return;
$.riot = "0.9.4";
function isFunction(el) {
return Object.prototype.toString.call(el) == '[object Function]';
}
$.observable = function(el) {
var callbacks = {},
slice = [].slice;
el.on = function(events, fn) {
if (isFunction(fn)) {
events = events.split(/\s+/);
for (var i = 0, len = events.length, type; i < len; i++) {
type = events[i];
(callbacks[type] = callbacks[type] || []).push(fn);
if (len > 1) fn.typed = true;
}
}
return el;
};
el.off = function(events, fn) {
events = events.split(/\s+/);
for (var j = 0, type; j < events.length; j++) {
type = events[j];
// remove single type
if (!fn) { callbacks[type] = []; continue; }
var fns = callbacks[type] || [],
pos = -1;
for (var i = 0, len = fns.length; i < len; i++) {
if (fns[i] === fn || fns[i].listener === fn) { pos = i; break; }
}
if (pos >= 0) fns.splice(pos, 1);
}
return el;
};
// only single event supported
el.one = function(type, fn) {
function on() {
el.off(type, fn);
fn.apply(el, arguments);
}
if (isFunction(fn)) {
on.listener = fn;
el.on(type, on);
}
return el;
};
el.trigger = function(type) {
var args = slice.call(arguments, 1),
fns = callbacks[type] || [];
for (var i = 0, len = fns.length, fn, added; i < len; ++i) {
fn = fns[i];
// possibly removed
if (!fn) continue;
// add event argument when multiple listeners
fn.apply(el, fn.typed ? [type].concat(args) : args);
}
return el;
};
return el;
};
// emit window.popstate event consistently on page load, on every browser
var page_popped,
fn = $.observable({});
function pop(hash) {
fn.trigger("pop", hash || top.location.hash);
}
function on(event, fn) {
top.addEventListener(event, fn, false);
}
on("load", function() {
top.setTimeout(function() { page_popped || pop(); }, 1);
});
on("popstate", function(e) {
if (!page_popped) page_popped = true;
pop();
});
// Change the browser URL or listen to changes on the URL
$.route = function(to) {
// listen
if (isFunction(to)) {
fn.on("pop", to);
// fire
} else if (to != top.location.hash) {
if (top.history.pushState) top.history.pushState("", "", to);
pop(to);
}
};
})(window);