-
Notifications
You must be signed in to change notification settings - Fork 1
/
Plugins.js
153 lines (131 loc) · 3.82 KB
/
Plugins.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/**
* Olives
* Copyright(c) 2012 Olivier Scherrer <pode.fr@gmail.com> - Olivier Wietrich <olivier.wietrich@gmail.com>
* MIT Licensed
*/
define("Olives/Plugins", ["Tools", "Olives/DomUtils"],
/**
* @class
* Plugins is the link between the UI and your plugins.
* You can design your own plugin, declare them in your UI, and call them
* from the template, like :
* <tag data-yourPlugin="method: param"></tag>
* @see Model-Plugin for instance
* @requires Tools
*/
function Plugins(Tools, DomUtils) {
return function PluginsConstructor() {
/**
* The list of plugins
* @private
*/
var _plugins = {},
/**
* Just a "functionalification" of trim
* for code readability
* @private
*/
trim = function trim(string) {
return string.trim();
},
/**
* Call the plugins methods, passing them the dom node
* A phrase can be :
* <tag data-plugin='method: param, param; method:param...'/>
* the function has to call every method of the plugin
* passing it the node, and the given params
* @private
*/
applyPlugin = function applyPlugin(node, phrase, plugin) {
// Split the methods
phrase.split(";")
.forEach(function (couple) {
// Split the result between method and params
var split = couple.split(":"),
// Trim the name
method = split[0].trim(),
// And the params, if any
params = split[1] ? split[1].split(",").map(trim) : [];
// The first param must be the dom node
params.unshift(node);
if (_plugins[plugin] && _plugins[plugin][method]) {
// Call the method with the following params for instance :
// [node, "param1", "param2" .. ]
_plugins[plugin][method].apply(_plugins[plugin], params);
}
});
};
/**
* Add a plugin
*
* Note that once added, the function adds a "plugins" property to the plugin.
* It's an object that holds a name property, with the registered name of the plugin
* and an apply function, to use on new nodes that the plugin would generate
*
* @param {String} name the name of the data that the plugin should look for
* @param {Object} plugin the plugin that has the functions to execute
* @returns true if plugin successfully added.
*/
this.add = function add(name, plugin) {
var that = this,
propertyName = "plugins";
if (typeof name == "string" && typeof plugin == "object" && plugin) {
_plugins[name] = plugin;
plugin[propertyName] = {
name: name,
apply: function apply() {
return that.apply.apply(that, arguments);
}
};
return true;
} else {
return false;
}
};
/**
* Add multiple plugins at once
* @param {Object} list key is the plugin name and value is the plugin
* @returns true if correct param
*/
this.addAll = function addAll(list) {
return Tools.loop(list, function (plugin, name) {
this.add(name, plugin);
}, this);
};
/**
* Get a previously added plugin
* @param {String} name the name of the plugin
* @returns {Object} the plugin
*/
this.get = function get(name) {
return _plugins[name];
};
/**
* Delete a plugin from the list
* @param {String} name the name of the plugin
* @returns {Boolean} true if success
*/
this.del = function del(name) {
return delete _plugins[name];
};
/**
* Apply the plugins to a NodeList
* @param {HTMLElement} dom the dom nodes on which to apply the plugins
* @returns {Boolean} true if the param is a dom node
*/
this.apply = function apply(dom) {
var nodes;
if (dom instanceof HTMLElement) {
nodes = DomUtils.getNodes(dom);
Tools.loop(Tools.toArray(nodes), function (node) {
Tools.loop(node.dataset, function (phrase, plugin) {
applyPlugin(node, phrase, plugin);
});
});
return dom;
} else {
return false;
}
};
};
});