bee_api 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/bee_api +84 -0
- data/lib/mdpreview.rb +80 -0
- data/lib/mdpreview/translator.rb +60 -0
- data/lib/mdpreview/version.rb +3 -0
- data/test/mdptest.rb +100 -0
- data/vendor/HISTORY.md +237 -0
- data/vendor/Jakefile.js +316 -0
- data/vendor/LICENSE +176 -0
- data/vendor/NOTICE +17 -0
- data/vendor/README.md +102 -0
- data/vendor/app/chrome/documentation.txt +12 -0
- data/vendor/app/chrome/manifest.json +24 -0
- data/vendor/app/web/ajax.js +43 -0
- data/vendor/app/web/app.css +292 -0
- data/vendor/app/web/app.js +377 -0
- data/vendor/app/web/beta/index.html +17 -0
- data/vendor/app/web/datapolicy.txt +48 -0
- data/vendor/app/web/doc/doc.css +60 -0
- data/vendor/app/web/doc/img/actions_menu.png +0 -0
- data/vendor/app/web/doc/img/button_actions_menu.png +0 -0
- data/vendor/app/web/doc/img/button_dragarea.png +0 -0
- data/vendor/app/web/doc/img/jsoneditor.png +0 -0
- data/vendor/app/web/doc/img/jsonformatter.png +0 -0
- data/vendor/app/web/doc/img/main_menu.png +0 -0
- data/vendor/app/web/doc/img/splitter.png +0 -0
- data/vendor/app/web/doc/index.html +201 -0
- data/vendor/app/web/favicon.ico +0 -0
- data/vendor/app/web/fileretriever.css +54 -0
- data/vendor/app/web/fileretriever.js +567 -0
- data/vendor/app/web/fileretriever.php +120 -0
- data/vendor/app/web/googlea47c4a0b36d11021.html +1 -0
- data/vendor/app/web/hash.js +133 -0
- data/vendor/app/web/img/description.txt +20 -0
- data/vendor/app/web/img/header_background.png +0 -0
- data/vendor/app/web/img/icon_128.png +0 -0
- data/vendor/app/web/img/icon_16.png +0 -0
- data/vendor/app/web/img/icon_gray.svg +151 -0
- data/vendor/app/web/img/icon_gray_16.svg +150 -0
- data/vendor/app/web/img/icon_orange.svg +151 -0
- data/vendor/app/web/img/logo.png +0 -0
- data/vendor/app/web/img/logo.xcf +0 -0
- data/vendor/app/web/img/logo_app.png +0 -0
- data/vendor/app/web/img/logo_app.xcf +0 -0
- data/vendor/app/web/index.html +191 -0
- data/vendor/app/web/notify.js +150 -0
- data/vendor/app/web/queryparams.js +71 -0
- data/vendor/app/web/robots.txt +0 -0
- data/vendor/app/web/splitter.js +179 -0
- data/vendor/app/web/test.html +224 -0
- data/vendor/component.json +33 -0
- data/vendor/docs/api.md +188 -0
- data/vendor/docs/usage.md +137 -0
- data/vendor/examples/01_basic_usage.html +45 -0
- data/vendor/examples/02_viewer.html +38 -0
- data/vendor/examples/03_switch_mode.html +98 -0
- data/vendor/examples/cur.file +1 -0
- data/vendor/examples/jquery.js +2 -0
- data/vendor/examples/meta.js +1 -0
- data/vendor/examples/requirejs_demo/requirejs_demo.html +19 -0
- data/vendor/examples/requirejs_demo/scripts/main.js +25 -0
- data/vendor/examples/requirejs_demo/scripts/require.js +35 -0
- data/vendor/img/jsoneditor-icons.png +0 -0
- data/vendor/jsoneditor-min.css +1 -0
- data/vendor/jsoneditor-min.js +34 -0
- data/vendor/jsoneditor.css +597 -0
- data/vendor/jsoneditor.js +6069 -0
- data/vendor/jsoneditor/css/contextmenu.css +219 -0
- data/vendor/jsoneditor/css/img/description.txt +13 -0
- data/vendor/jsoneditor/css/img/export.sh +16 -0
- data/vendor/jsoneditor/css/img/jsoneditor-icons.png +0 -0
- data/vendor/jsoneditor/css/img/jsoneditor-icons.svg +861 -0
- data/vendor/jsoneditor/css/jsoneditor.css +220 -0
- data/vendor/jsoneditor/css/menu.css +81 -0
- data/vendor/jsoneditor/css/searchbox.css +73 -0
- data/vendor/jsoneditor/js/appendnode.js +211 -0
- data/vendor/jsoneditor/js/contextmenu.js +440 -0
- data/vendor/jsoneditor/js/header.js +32 -0
- data/vendor/jsoneditor/js/highlighter.js +82 -0
- data/vendor/jsoneditor/js/history.js +218 -0
- data/vendor/jsoneditor/js/jsoneditor.js +206 -0
- data/vendor/jsoneditor/js/module.js +50 -0
- data/vendor/jsoneditor/js/node.js +2864 -0
- data/vendor/jsoneditor/js/searchbox.js +288 -0
- data/vendor/jsoneditor/js/texteditor.js +311 -0
- data/vendor/jsoneditor/js/treeeditor.js +770 -0
- data/vendor/jsoneditor/js/util.js +582 -0
- data/vendor/lib/ace/ace.js +11 -0
- data/vendor/lib/ace/mode-json.js +1 -0
- data/vendor/lib/ace/theme-jsoneditor.js +144 -0
- data/vendor/lib/ace/theme-textmate.js +163 -0
- data/vendor/lib/ace/worker-json.js +1 -0
- data/vendor/lib/jsonlint/README.md +62 -0
- data/vendor/lib/jsonlint/jsonlint.js +432 -0
- data/vendor/misc/screenshots/actionsmenu_640x400.png +0 -0
- data/vendor/misc/screenshots/codeeditor_640x400.png +0 -0
- data/vendor/misc/screenshots/description.json +17 -0
- data/vendor/misc/screenshots/jsoneditoronline.png +0 -0
- data/vendor/misc/screenshots/jsoneditoronline_640x400.png +0 -0
- data/vendor/misc/screenshots/search_640x400.png +0 -0
- data/vendor/misc/screenshots/small_tile.xcf +0 -0
- data/vendor/misc/screenshots/small_tile_440x280.png +0 -0
- data/vendor/misc/todo.txt +101 -0
- data/vendor/package.json +28 -0
- data/vendor/test/couchdbeditor.html +100 -0
- data/vendor/test/largefile.json +12605 -0
- data/vendor/test/test_ace.html +60 -0
- data/vendor/test/test_editable_div.html +449 -0
- metadata +154 -0
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
// create namespace
|
|
2
|
+
util = {};
|
|
3
|
+
|
|
4
|
+
// Internet Explorer 8 and older does not support Array.indexOf,
|
|
5
|
+
// so we define it here in that case
|
|
6
|
+
// http://soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorer/
|
|
7
|
+
if(!Array.prototype.indexOf) {
|
|
8
|
+
Array.prototype.indexOf = function(obj){
|
|
9
|
+
for(var i = 0; i < this.length; i++){
|
|
10
|
+
if(this[i] == obj){
|
|
11
|
+
return i;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return -1;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Internet Explorer 8 and older does not support Array.forEach,
|
|
19
|
+
// so we define it here in that case
|
|
20
|
+
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach
|
|
21
|
+
if (!Array.prototype.forEach) {
|
|
22
|
+
Array.prototype.forEach = function(fn, scope) {
|
|
23
|
+
for(var i = 0, len = this.length; i < len; ++i) {
|
|
24
|
+
fn.call(scope || this, this[i], i, this);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Parse JSON using the parser built-in in the browser.
|
|
31
|
+
* On exception, the jsonString is validated and a detailed error is thrown.
|
|
32
|
+
* @param {String} jsonString
|
|
33
|
+
*/
|
|
34
|
+
util.parse = function (jsonString) {
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(jsonString);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
// try to throw a more detailed error message using validate
|
|
40
|
+
util.validate(jsonString);
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Validate a string containing a JSON object
|
|
47
|
+
* This method uses JSONLint to validate the String. If JSONLint is not
|
|
48
|
+
* available, the built-in JSON parser of the browser is used.
|
|
49
|
+
* @param {String} jsonString String with an (invalid) JSON object
|
|
50
|
+
* @throws Error
|
|
51
|
+
*/
|
|
52
|
+
util.validate = function (jsonString) {
|
|
53
|
+
if (typeof(jsonlint) != 'undefined') {
|
|
54
|
+
jsonlint.parse(jsonString);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
JSON.parse(jsonString);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Extend object a with the properties of object b
|
|
63
|
+
* @param {Object} a
|
|
64
|
+
* @param {Object} b
|
|
65
|
+
* @return {Object} a
|
|
66
|
+
*/
|
|
67
|
+
util.extend = function (a, b) {
|
|
68
|
+
for (var prop in b) {
|
|
69
|
+
if (b.hasOwnProperty(prop)) {
|
|
70
|
+
a[prop] = b[prop];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return a;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Remove all properties from object a
|
|
78
|
+
* @param {Object} a
|
|
79
|
+
* @return {Object} a
|
|
80
|
+
*/
|
|
81
|
+
util.clear = function (a) {
|
|
82
|
+
for (var prop in a) {
|
|
83
|
+
if (a.hasOwnProperty(prop)) {
|
|
84
|
+
delete a[prop];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return a;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Output text to the console, if console is available
|
|
92
|
+
* @param {...*} args
|
|
93
|
+
*/
|
|
94
|
+
util.log = function(args) {
|
|
95
|
+
if (console && typeof console.log === 'function') {
|
|
96
|
+
console.log.apply(console, arguments);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Test whether a text contains a url (matches when a string starts
|
|
102
|
+
* with 'http://*' or 'https://*' and has no whitespace characters)
|
|
103
|
+
* @param {String} text
|
|
104
|
+
*/
|
|
105
|
+
var isUrlRegex = /^https?:\/\/\S+$/;
|
|
106
|
+
util.isUrl = function (text) {
|
|
107
|
+
return (typeof text == 'string' || text instanceof String) &&
|
|
108
|
+
isUrlRegex.test(text);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Retrieve the absolute left value of a DOM element
|
|
113
|
+
* @param {Element} elem A dom element, for example a div
|
|
114
|
+
* @return {Number} left The absolute left position of this element
|
|
115
|
+
* in the browser page.
|
|
116
|
+
*/
|
|
117
|
+
util.getAbsoluteLeft = function (elem) {
|
|
118
|
+
var left = elem.offsetLeft;
|
|
119
|
+
var body = document.body;
|
|
120
|
+
var e = elem.offsetParent;
|
|
121
|
+
while (e != null && elem != body) {
|
|
122
|
+
left += e.offsetLeft;
|
|
123
|
+
left -= e.scrollLeft;
|
|
124
|
+
e = e.offsetParent;
|
|
125
|
+
}
|
|
126
|
+
return left;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Retrieve the absolute top value of a DOM element
|
|
131
|
+
* @param {Element} elem A dom element, for example a div
|
|
132
|
+
* @return {Number} top The absolute top position of this element
|
|
133
|
+
* in the browser page.
|
|
134
|
+
*/
|
|
135
|
+
util.getAbsoluteTop = function (elem) {
|
|
136
|
+
var top = elem.offsetTop;
|
|
137
|
+
var body = document.body;
|
|
138
|
+
var e = elem.offsetParent;
|
|
139
|
+
while (e != null && e != body) {
|
|
140
|
+
top += e.offsetTop;
|
|
141
|
+
top -= e.scrollTop;
|
|
142
|
+
e = e.offsetParent;
|
|
143
|
+
}
|
|
144
|
+
return top;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Get the absolute, vertical mouse position from an event.
|
|
149
|
+
* @param {Event} event
|
|
150
|
+
* @return {Number} mouseY
|
|
151
|
+
*/
|
|
152
|
+
util.getMouseY = function (event) {
|
|
153
|
+
var mouseY;
|
|
154
|
+
if ('pageY' in event) {
|
|
155
|
+
mouseY = event.pageY;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
// for IE8 and older
|
|
159
|
+
mouseY = (event.clientY + document.documentElement.scrollTop);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return mouseY;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get the absolute, horizontal mouse position from an event.
|
|
167
|
+
* @param {Event} event
|
|
168
|
+
* @return {Number} mouseX
|
|
169
|
+
*/
|
|
170
|
+
util.getMouseX = function (event) {
|
|
171
|
+
var mouseX;
|
|
172
|
+
if ('pageX' in event) {
|
|
173
|
+
mouseX = event.pageX;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// for IE8 and older
|
|
177
|
+
mouseX = (event.clientX + document.documentElement.scrollLeft);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return mouseX;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Get the window height
|
|
185
|
+
* @return {Number} windowHeight
|
|
186
|
+
*/
|
|
187
|
+
util.getWindowHeight = function () {
|
|
188
|
+
if ('innerHeight' in window) {
|
|
189
|
+
return window.innerHeight;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// for IE8 and older
|
|
193
|
+
return Math.max(document.body.clientHeight,
|
|
194
|
+
document.documentElement.clientHeight);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* add a className to the given elements style
|
|
200
|
+
* @param {Element} elem
|
|
201
|
+
* @param {String} className
|
|
202
|
+
*/
|
|
203
|
+
util.addClassName = function(elem, className) {
|
|
204
|
+
var classes = elem.className.split(' ');
|
|
205
|
+
if (classes.indexOf(className) == -1) {
|
|
206
|
+
classes.push(className); // add the class to the array
|
|
207
|
+
elem.className = classes.join(' ');
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* add a className to the given elements style
|
|
213
|
+
* @param {Element} elem
|
|
214
|
+
* @param {String} className
|
|
215
|
+
*/
|
|
216
|
+
util.removeClassName = function(elem, className) {
|
|
217
|
+
var classes = elem.className.split(' ');
|
|
218
|
+
var index = classes.indexOf(className);
|
|
219
|
+
if (index != -1) {
|
|
220
|
+
classes.splice(index, 1); // remove the class from the array
|
|
221
|
+
elem.className = classes.join(' ');
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Strip the formatting from the contents of a div
|
|
227
|
+
* the formatting from the div itself is not stripped, only from its childs.
|
|
228
|
+
* @param {Element} divElement
|
|
229
|
+
*/
|
|
230
|
+
util.stripFormatting = function (divElement) {
|
|
231
|
+
var childs = divElement.childNodes;
|
|
232
|
+
for (var i = 0, iMax = childs.length; i < iMax; i++) {
|
|
233
|
+
var child = childs[i];
|
|
234
|
+
|
|
235
|
+
// remove the style
|
|
236
|
+
if (child.style) {
|
|
237
|
+
// TODO: test if child.attributes does contain style
|
|
238
|
+
child.removeAttribute('style');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// remove all attributes
|
|
242
|
+
var attributes = child.attributes;
|
|
243
|
+
if (attributes) {
|
|
244
|
+
for (var j = attributes.length - 1; j >= 0; j--) {
|
|
245
|
+
var attribute = attributes[j];
|
|
246
|
+
if (attribute.specified == true) {
|
|
247
|
+
child.removeAttribute(attribute.name);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// recursively strip childs
|
|
253
|
+
util.stripFormatting(child);
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Set focus to the end of an editable div
|
|
259
|
+
* code from Nico Burns
|
|
260
|
+
* http://stackoverflow.com/users/140293/nico-burns
|
|
261
|
+
* http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity
|
|
262
|
+
* @param {Element} contentEditableElement A content editable div
|
|
263
|
+
*/
|
|
264
|
+
util.setEndOfContentEditable = function (contentEditableElement) {
|
|
265
|
+
var range, selection;
|
|
266
|
+
if(document.createRange) {//Firefox, Chrome, Opera, Safari, IE 9+
|
|
267
|
+
range = document.createRange();//Create a range (a range is a like the selection but invisible)
|
|
268
|
+
range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range
|
|
269
|
+
range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
|
|
270
|
+
selection = window.getSelection();//get the selection object (allows you to change selection)
|
|
271
|
+
selection.removeAllRanges();//remove any selections already made
|
|
272
|
+
selection.addRange(range);//make the range you have just created the visible selection
|
|
273
|
+
}
|
|
274
|
+
else if(document.selection) {//IE 8 and lower
|
|
275
|
+
range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible)
|
|
276
|
+
range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range
|
|
277
|
+
range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
|
|
278
|
+
range.select();//Select the range (make it the visible selection
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Select all text of a content editable div.
|
|
284
|
+
* http://stackoverflow.com/a/3806004/1262753
|
|
285
|
+
* @param {Element} contentEditableElement A content editable div
|
|
286
|
+
*/
|
|
287
|
+
util.selectContentEditable = function (contentEditableElement) {
|
|
288
|
+
if (!contentEditableElement || contentEditableElement.nodeName != 'DIV') {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
var sel, range;
|
|
293
|
+
if (window.getSelection && document.createRange) {
|
|
294
|
+
range = document.createRange();
|
|
295
|
+
range.selectNodeContents(contentEditableElement);
|
|
296
|
+
sel = window.getSelection();
|
|
297
|
+
sel.removeAllRanges();
|
|
298
|
+
sel.addRange(range);
|
|
299
|
+
} else if (document.body.createTextRange) {
|
|
300
|
+
range = document.body.createTextRange();
|
|
301
|
+
range.moveToElementText(contentEditableElement);
|
|
302
|
+
range.select();
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Get text selection
|
|
308
|
+
* http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore
|
|
309
|
+
* @return {Range | TextRange | null} range
|
|
310
|
+
*/
|
|
311
|
+
util.getSelection = function () {
|
|
312
|
+
if (window.getSelection) {
|
|
313
|
+
var sel = window.getSelection();
|
|
314
|
+
if (sel.getRangeAt && sel.rangeCount) {
|
|
315
|
+
return sel.getRangeAt(0);
|
|
316
|
+
}
|
|
317
|
+
} else if (document.selection && document.selection.createRange) {
|
|
318
|
+
return document.selection.createRange();
|
|
319
|
+
}
|
|
320
|
+
return null;
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Set text selection
|
|
325
|
+
* http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore
|
|
326
|
+
* @param {Range | TextRange | null} range
|
|
327
|
+
*/
|
|
328
|
+
util.setSelection = function (range) {
|
|
329
|
+
if (range) {
|
|
330
|
+
if (window.getSelection) {
|
|
331
|
+
var sel = window.getSelection();
|
|
332
|
+
sel.removeAllRanges();
|
|
333
|
+
sel.addRange(range);
|
|
334
|
+
} else if (document.selection && range.select) {
|
|
335
|
+
range.select();
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Get selected text range
|
|
342
|
+
* @return {Object} params object containing parameters:
|
|
343
|
+
* {Number} startOffset
|
|
344
|
+
* {Number} endOffset
|
|
345
|
+
* {Element} container HTML element holding the
|
|
346
|
+
* selected text element
|
|
347
|
+
* Returns null if no text selection is found
|
|
348
|
+
*/
|
|
349
|
+
util.getSelectionOffset = function () {
|
|
350
|
+
var range = util.getSelection();
|
|
351
|
+
|
|
352
|
+
if (range && 'startOffset' in range && 'endOffset' in range &&
|
|
353
|
+
range.startContainer && (range.startContainer == range.endContainer)) {
|
|
354
|
+
return {
|
|
355
|
+
startOffset: range.startOffset,
|
|
356
|
+
endOffset: range.endOffset,
|
|
357
|
+
container: range.startContainer.parentNode
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
// TODO: implement getSelectionOffset for IE8
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return null;
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Set selected text range in given element
|
|
369
|
+
* @param {Object} params An object containing:
|
|
370
|
+
* {Element} container
|
|
371
|
+
* {Number} startOffset
|
|
372
|
+
* {Number} endOffset
|
|
373
|
+
*/
|
|
374
|
+
util.setSelectionOffset = function (params) {
|
|
375
|
+
if (document.createRange && window.getSelection) {
|
|
376
|
+
var selection = window.getSelection();
|
|
377
|
+
if(selection) {
|
|
378
|
+
var range = document.createRange();
|
|
379
|
+
// TODO: do not suppose that the first child of the container is a textnode,
|
|
380
|
+
// but recursively find the textnodes
|
|
381
|
+
range.setStart(params.container.firstChild, params.startOffset);
|
|
382
|
+
range.setEnd(params.container.firstChild, params.endOffset);
|
|
383
|
+
|
|
384
|
+
util.setSelection(range);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
// TODO: implement setSelectionOffset for IE8
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Get the inner text of an HTML element (for example a div element)
|
|
394
|
+
* @param {Element} element
|
|
395
|
+
* @param {Object} [buffer]
|
|
396
|
+
* @return {String} innerText
|
|
397
|
+
*/
|
|
398
|
+
util.getInnerText = function (element, buffer) {
|
|
399
|
+
var first = (buffer == undefined);
|
|
400
|
+
if (first) {
|
|
401
|
+
buffer = {
|
|
402
|
+
'text': '',
|
|
403
|
+
'flush': function () {
|
|
404
|
+
var text = this.text;
|
|
405
|
+
this.text = '';
|
|
406
|
+
return text;
|
|
407
|
+
},
|
|
408
|
+
'set': function (text) {
|
|
409
|
+
this.text = text;
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// text node
|
|
415
|
+
if (element.nodeValue) {
|
|
416
|
+
return buffer.flush() + element.nodeValue;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// divs or other HTML elements
|
|
420
|
+
if (element.hasChildNodes()) {
|
|
421
|
+
var childNodes = element.childNodes;
|
|
422
|
+
var innerText = '';
|
|
423
|
+
|
|
424
|
+
for (var i = 0, iMax = childNodes.length; i < iMax; i++) {
|
|
425
|
+
var child = childNodes[i];
|
|
426
|
+
|
|
427
|
+
if (child.nodeName == 'DIV' || child.nodeName == 'P') {
|
|
428
|
+
var prevChild = childNodes[i - 1];
|
|
429
|
+
var prevName = prevChild ? prevChild.nodeName : undefined;
|
|
430
|
+
if (prevName && prevName != 'DIV' && prevName != 'P' && prevName != 'BR') {
|
|
431
|
+
innerText += '\n';
|
|
432
|
+
buffer.flush();
|
|
433
|
+
}
|
|
434
|
+
innerText += util.getInnerText(child, buffer);
|
|
435
|
+
buffer.set('\n');
|
|
436
|
+
}
|
|
437
|
+
else if (child.nodeName == 'BR') {
|
|
438
|
+
innerText += buffer.flush();
|
|
439
|
+
buffer.set('\n');
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
innerText += util.getInnerText(child, buffer);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return innerText;
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
if (element.nodeName == 'P' && util.getInternetExplorerVersion() != -1) {
|
|
450
|
+
// On Internet Explorer, a <p> with hasChildNodes()==false is
|
|
451
|
+
// rendered with a new line. Note that a <p> with
|
|
452
|
+
// hasChildNodes()==true is rendered without a new line
|
|
453
|
+
// Other browsers always ensure there is a <br> inside the <p>,
|
|
454
|
+
// and if not, the <p> does not render a new line
|
|
455
|
+
return buffer.flush();
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// br or unknown
|
|
460
|
+
return '';
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Returns the version of Internet Explorer or a -1
|
|
465
|
+
* (indicating the use of another browser).
|
|
466
|
+
* Source: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx
|
|
467
|
+
* @return {Number} Internet Explorer version, or -1 in case of an other browser
|
|
468
|
+
*/
|
|
469
|
+
util.getInternetExplorerVersion = function() {
|
|
470
|
+
if (_ieVersion == -1) {
|
|
471
|
+
var rv = -1; // Return value assumes failure.
|
|
472
|
+
if (navigator.appName == 'Microsoft Internet Explorer')
|
|
473
|
+
{
|
|
474
|
+
var ua = navigator.userAgent;
|
|
475
|
+
var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
|
|
476
|
+
if (re.exec(ua) != null) {
|
|
477
|
+
rv = parseFloat( RegExp.$1 );
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
_ieVersion = rv;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
return _ieVersion;
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* cached internet explorer version
|
|
489
|
+
* @type {Number}
|
|
490
|
+
* @private
|
|
491
|
+
*/
|
|
492
|
+
var _ieVersion = -1;
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Add and event listener. Works for all browsers
|
|
496
|
+
* @param {Element} element An html element
|
|
497
|
+
* @param {string} action The action, for example "click",
|
|
498
|
+
* without the prefix "on"
|
|
499
|
+
* @param {function} listener The callback function to be executed
|
|
500
|
+
* @param {boolean} [useCapture] false by default
|
|
501
|
+
* @return {function} the created event listener
|
|
502
|
+
*/
|
|
503
|
+
util.addEventListener = function (element, action, listener, useCapture) {
|
|
504
|
+
if (element.addEventListener) {
|
|
505
|
+
if (useCapture === undefined)
|
|
506
|
+
useCapture = false;
|
|
507
|
+
|
|
508
|
+
if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) {
|
|
509
|
+
action = "DOMMouseScroll"; // For Firefox
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
element.addEventListener(action, listener, useCapture);
|
|
513
|
+
return listener;
|
|
514
|
+
} else {
|
|
515
|
+
// IE browsers
|
|
516
|
+
var f = function () {
|
|
517
|
+
return listener.call(element, window.event);
|
|
518
|
+
};
|
|
519
|
+
element.attachEvent("on" + action, f);
|
|
520
|
+
return f;
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Remove an event listener from an element
|
|
526
|
+
* @param {Element} element An html dom element
|
|
527
|
+
* @param {string} action The name of the event, for example "mousedown"
|
|
528
|
+
* @param {function} listener The listener function
|
|
529
|
+
* @param {boolean} [useCapture] false by default
|
|
530
|
+
*/
|
|
531
|
+
util.removeEventListener = function(element, action, listener, useCapture) {
|
|
532
|
+
if (element.removeEventListener) {
|
|
533
|
+
// non-IE browsers
|
|
534
|
+
if (useCapture === undefined)
|
|
535
|
+
useCapture = false;
|
|
536
|
+
|
|
537
|
+
if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) {
|
|
538
|
+
action = "DOMMouseScroll"; // For Firefox
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
element.removeEventListener(action, listener, useCapture);
|
|
542
|
+
} else {
|
|
543
|
+
// IE browsers
|
|
544
|
+
element.detachEvent("on" + action, listener);
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Stop event propagation
|
|
551
|
+
* @param {Event} event
|
|
552
|
+
*/
|
|
553
|
+
util.stopPropagation = function (event) {
|
|
554
|
+
if (!event) {
|
|
555
|
+
event = window.event;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
if (event.stopPropagation) {
|
|
559
|
+
event.stopPropagation(); // non-IE browsers
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
event.cancelBubble = true; // IE browsers
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Cancels the event if it is cancelable, without stopping further propagation of the event.
|
|
569
|
+
* @param {Event} event
|
|
570
|
+
*/
|
|
571
|
+
util.preventDefault = function (event) {
|
|
572
|
+
if (!event) {
|
|
573
|
+
event = window.event;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
if (event.preventDefault) {
|
|
577
|
+
event.preventDefault(); // non-IE browsers
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
event.returnValue = false; // IE browsers
|
|
581
|
+
}
|
|
582
|
+
};
|