This repository has been archived by the owner on Feb 21, 2024. It is now read-only.
/
lb.core.Sandbox.js
228 lines (213 loc) · 8.86 KB
/
lb.core.Sandbox.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/*
* Namespace: lb.core.Sandbox
* Sandbox for Modules of Legal Box Scalable JavaScript Application
*
* A new instance of Sandbox gets attributed to each instance of Module. It
* acts both as a proxy and a facade to the application core, restricting
* modifications to the box assigned to the module, an HTML element which
* encloses the module.
*
* The methods related to the module itself are defined on the Sandbox. Other
* methods are defined by separate plugin modules.
*
* Module (sandbox):
* - <sandbox.getId([localId]):string>
* - <sandbox.getBox(createIfMissing): DOM Element>
* - <sandbox.isInBox(element): boolean>
*
* Cascading Style Sheets (sandbox.css, defined by <lb.core.plugins.css>):
* - <lb.core.plugins.css.sandbox.css.getClasses(element): object>
* - <lb.core.plugins.css.sandbox.css.addClass(element,name)>
* - <lb.core.plugins.css.sandbox.css.removeClass(element,name)>
*
* Document Object Model (sandbox.dom, defined by <lb.core.plugins.dom>):
* - <lb.core.plugins.dom.sandbox.dom.$(localId): DOM Element>
* - <lb.core.plugins.dom.sandbox.dom.element(name[,attributes[,childNodes]]): DOM Element>
* - <lb.core.plugins.dom.sandbox.dom.fireEvent(element,type[,properties]): DOM Event>
* - <lb.core.plugins.dom.sandbox.dom.cancelEvent(event)>
* - <lb.core.plugins.dom.sandbox.dom.getListeners(): array>
* - <lb.core.plugins.dom.sandbox.dom.addListener(element,type,callback): Listener>
* - <lb.core.plugins.dom.sandbox.dom.removeListener(listener)>
* - <lb.core.plugins.dom.sandbox.dom.removeAllListeners()>
*
* Events for loose coupling with other modules (sandbox.events, defined by <lb.core.plugins.events>):
* - <lb.core.plugins.events.sandbox.events.subscribe(filter,callback)>
* - <lb.core.plugins.events.sandbox.events.unsubscribe(filter)>
* - <lb.core.plugins.events.sandbox.events.publish(event)>
*
* Internationalization through language properties (sandbox.i18n, defined by <lb.core.plugins.i18n>):
* - <lb.core.plugins.i18n.sandbox.i18n.getLanguageList(): array of strings>
* - <lb.core.plugins.i18n.sandbox.i18n.getSelectedLanguage(): string>
* - <lb.core.plugins.i18n.sandbox.i18n.selectLanguage(languageCode)>
* - <lb.core.plugins.i18n.sandbox.i18n.addLanguageProperties(languageCode,languageProperties)>
* - <lb.core.plugins.i18n.sandbox.i18n.get(key[,languageCode]): any>
* - <lb.core.plugins.i18n.sandbox.i18n.getString(key[,data[,languageCode]]): string>
* - <lb.core.plugins.i18n.sandbox.i18n.filterHtml(htmlNode[,data[,languageCode]])>
*
* Asynchronous communication with a remote server (sandbox.server, defined by <lb.core.plugins.server>):
* - <lb.core.plugins.server.sandbox.server.send(url,data,receive)>
*
* Uniform Resource Locator, local navigation (sandbox.url, defined by <lb.core.plugins.url>):
* - <lb.core.plugins.url.sandbox.url.getLocation(): object>
* - <lb.core.plugins.url.sandbox.url.setHash(hash)>
* - <lb.core.plugins.url.sandbox.url.onHashChange(callback)>
*
* General utilities (sandbox.utils):
* - <lb.core.plugins.utils.sandbox.utils.no(value): boolean>
* - <lb.core.plugins.utils.sandbox.utils.or(a,b): any>
* - <lb.core.plugins.utils.sandbox.utils.has(object,property[,...]): boolean>
* - <lb.core.plugins.utils.sandbox.utils.is([...,]value[,type]): boolean>
* - <lb.core.plugins.utils.sandbox.utils.getTimestamp(): number>
* - <lb.core.plugins.utils.sandbox.utils.setTimeout(callback,delay): number>
* - <lb.core.plugins.utils.sandbox.utils.clearTimeout(timeoutId)>
* - <lb.core.plugins.utils.sandbox.utils.trim(string): string>
* - <lb.core.plugins.utils.sandbox.utils.log(message)>
* - <lb.core.plugins.utils.sandbox.utils.confirm(message): boolean>
*
* The plugins are loaded by the Sandbox Builder. The sandbox API can be
* customized by configuring a different sandbox builder to load additional or
* alternative plugins. See <lb.core.plugins.builder> for details.
*
* Authors:
* o Eric Bréchemier <github@eric.brechemier.name>
* o Marc Delhommeau <marc.delhommeau@legalbox.com>
*
* Copyright:
* Eric Bréchemier (c) 2011-2013, Some Rights Reserved
* Legal-Box SAS (c) 2010-2011, All Rights Reserved
*
* License:
* BSD License
* http://creativecommons.org/licenses/BSD/
*
* Version:
* 2013-09-10
*/
/*global define, document, window */
define(
[
"./lb.core",
"./lb.base.object",
"./lb.base.config",
"./lb.base.dom.factory",
"./lb.base.dom",
"./lb.base.log"
],
function(
lbCore,
object,
config,
defaultFactory,
dom,
logModule
) {
// Assign to lb.core.Sandbox
// for backward-compatibility in browser environment
lbCore.Sandbox = function (id){
// Function: new Sandbox(id): Sandbox
// Constructor of a new Sandbox.
//
// Parameters:
// id - string, the identifier of the module, which is also the id of the
// root HTML element for this module. If the element does not exist in
// the document, it will get created on the first call to getBox().
//
// Returns:
// object, the new instance of Sandbox
// Define aliases
var has = object.has,
log = logModule.print,
// Private fields
// DOM element, the root of the box, carrying the module identifier.
// Used only in getBox(), to avoid multiple lookups of the same element.
// Initialized on first call to getBox().
box = null;
function getId(localId){
// Function: sandbox.getId([localId]): string
// Get the identifier of the module, when optional parameter is omitted.
// With optional parameter, get the full identifier corresponding to the
// given local identifier.
//
// Parameter:
// localId - string, optional local identifier
//
// Returns:
// string, the identifier of the module, as provided in constructor,
// or the full identifier corresponding to given local identifier.
//
// Note:
// The full identifier is made of the module identifier, followed by the
// separator '.', followed by the local identifier.
if ( has(localId) ) {
return id+'.'+localId;
} else {
return id;
}
}
function getBox(createIfMissing){
// Function: sandbox.getBox(createIfMissing): DOM Element
// Get the root HTML element for this module.
//
// Parameter:
// createIfMissing - boolean, optional, defaults to true,
// Whether to create the box element if it is not found
// in the document.
// Note:
// In case createIfMissing is true (by default) and no HTML element is
// found in the document with the module id, a new div element is created
// with this id and inserted last in the document body.
//
// Returns:
// * DOM Element, the HTML element corresponding to the module id,
// * or null, in case createIfMissing is false and the element is missing
createIfMissing = has(createIfMissing)? createIfMissing : true;
var factory;
if ( has(box) ) {
return box;
}
box = dom.$(id);
if ( !has(box) && createIfMissing){
log('Warning: no element "'+id+
'" found in box. Will be created at end of body.');
factory = config.getOption('lbFactory', defaultFactory);
box = factory.createElement('div',{'id': id});
document.body.appendChild(box);
}
return box;
}
function isInBox(element){
// Function: sandbox.isInBox(element): boolean
// Check whether the given element is in the box.
//
// Parameter:
// element - DOM Element, an element
//
// Returns:
// * true if the element is a descendant of or the root of the box itself
// * false otherwise
// Note:
// if optimization or reuse is needed, isInBox() could rely on a new method
// to add to base DOM API: contains(ancestorElement,descendantElement)
// (available as goog.dom.contains(parent,descendant) in Closure library)
var ancestor = element;
while ( has(ancestor) ) {
// TODO: return false when a document node is reached without passing by
// the root of the box
// TODO: allow document-fragment or null as last ancestor
// for nodes not/no longer part of the DOM
// box must be found in ancestors or self
if ( ancestor === getBox(false) ) {
return true;
}
ancestor = ancestor.parentNode;
}
return false;
}
// Public methods
this.getId = getId;
this.getBox = getBox;
this.isInBox = isInBox;
};
return lbCore.Sandbox;
}
);