bee_api 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/bin/bee_api +84 -0
  2. data/lib/mdpreview.rb +80 -0
  3. data/lib/mdpreview/translator.rb +60 -0
  4. data/lib/mdpreview/version.rb +3 -0
  5. data/test/mdptest.rb +100 -0
  6. data/vendor/HISTORY.md +237 -0
  7. data/vendor/Jakefile.js +316 -0
  8. data/vendor/LICENSE +176 -0
  9. data/vendor/NOTICE +17 -0
  10. data/vendor/README.md +102 -0
  11. data/vendor/app/chrome/documentation.txt +12 -0
  12. data/vendor/app/chrome/manifest.json +24 -0
  13. data/vendor/app/web/ajax.js +43 -0
  14. data/vendor/app/web/app.css +292 -0
  15. data/vendor/app/web/app.js +377 -0
  16. data/vendor/app/web/beta/index.html +17 -0
  17. data/vendor/app/web/datapolicy.txt +48 -0
  18. data/vendor/app/web/doc/doc.css +60 -0
  19. data/vendor/app/web/doc/img/actions_menu.png +0 -0
  20. data/vendor/app/web/doc/img/button_actions_menu.png +0 -0
  21. data/vendor/app/web/doc/img/button_dragarea.png +0 -0
  22. data/vendor/app/web/doc/img/jsoneditor.png +0 -0
  23. data/vendor/app/web/doc/img/jsonformatter.png +0 -0
  24. data/vendor/app/web/doc/img/main_menu.png +0 -0
  25. data/vendor/app/web/doc/img/splitter.png +0 -0
  26. data/vendor/app/web/doc/index.html +201 -0
  27. data/vendor/app/web/favicon.ico +0 -0
  28. data/vendor/app/web/fileretriever.css +54 -0
  29. data/vendor/app/web/fileretriever.js +567 -0
  30. data/vendor/app/web/fileretriever.php +120 -0
  31. data/vendor/app/web/googlea47c4a0b36d11021.html +1 -0
  32. data/vendor/app/web/hash.js +133 -0
  33. data/vendor/app/web/img/description.txt +20 -0
  34. data/vendor/app/web/img/header_background.png +0 -0
  35. data/vendor/app/web/img/icon_128.png +0 -0
  36. data/vendor/app/web/img/icon_16.png +0 -0
  37. data/vendor/app/web/img/icon_gray.svg +151 -0
  38. data/vendor/app/web/img/icon_gray_16.svg +150 -0
  39. data/vendor/app/web/img/icon_orange.svg +151 -0
  40. data/vendor/app/web/img/logo.png +0 -0
  41. data/vendor/app/web/img/logo.xcf +0 -0
  42. data/vendor/app/web/img/logo_app.png +0 -0
  43. data/vendor/app/web/img/logo_app.xcf +0 -0
  44. data/vendor/app/web/index.html +191 -0
  45. data/vendor/app/web/notify.js +150 -0
  46. data/vendor/app/web/queryparams.js +71 -0
  47. data/vendor/app/web/robots.txt +0 -0
  48. data/vendor/app/web/splitter.js +179 -0
  49. data/vendor/app/web/test.html +224 -0
  50. data/vendor/component.json +33 -0
  51. data/vendor/docs/api.md +188 -0
  52. data/vendor/docs/usage.md +137 -0
  53. data/vendor/examples/01_basic_usage.html +45 -0
  54. data/vendor/examples/02_viewer.html +38 -0
  55. data/vendor/examples/03_switch_mode.html +98 -0
  56. data/vendor/examples/cur.file +1 -0
  57. data/vendor/examples/jquery.js +2 -0
  58. data/vendor/examples/meta.js +1 -0
  59. data/vendor/examples/requirejs_demo/requirejs_demo.html +19 -0
  60. data/vendor/examples/requirejs_demo/scripts/main.js +25 -0
  61. data/vendor/examples/requirejs_demo/scripts/require.js +35 -0
  62. data/vendor/img/jsoneditor-icons.png +0 -0
  63. data/vendor/jsoneditor-min.css +1 -0
  64. data/vendor/jsoneditor-min.js +34 -0
  65. data/vendor/jsoneditor.css +597 -0
  66. data/vendor/jsoneditor.js +6069 -0
  67. data/vendor/jsoneditor/css/contextmenu.css +219 -0
  68. data/vendor/jsoneditor/css/img/description.txt +13 -0
  69. data/vendor/jsoneditor/css/img/export.sh +16 -0
  70. data/vendor/jsoneditor/css/img/jsoneditor-icons.png +0 -0
  71. data/vendor/jsoneditor/css/img/jsoneditor-icons.svg +861 -0
  72. data/vendor/jsoneditor/css/jsoneditor.css +220 -0
  73. data/vendor/jsoneditor/css/menu.css +81 -0
  74. data/vendor/jsoneditor/css/searchbox.css +73 -0
  75. data/vendor/jsoneditor/js/appendnode.js +211 -0
  76. data/vendor/jsoneditor/js/contextmenu.js +440 -0
  77. data/vendor/jsoneditor/js/header.js +32 -0
  78. data/vendor/jsoneditor/js/highlighter.js +82 -0
  79. data/vendor/jsoneditor/js/history.js +218 -0
  80. data/vendor/jsoneditor/js/jsoneditor.js +206 -0
  81. data/vendor/jsoneditor/js/module.js +50 -0
  82. data/vendor/jsoneditor/js/node.js +2864 -0
  83. data/vendor/jsoneditor/js/searchbox.js +288 -0
  84. data/vendor/jsoneditor/js/texteditor.js +311 -0
  85. data/vendor/jsoneditor/js/treeeditor.js +770 -0
  86. data/vendor/jsoneditor/js/util.js +582 -0
  87. data/vendor/lib/ace/ace.js +11 -0
  88. data/vendor/lib/ace/mode-json.js +1 -0
  89. data/vendor/lib/ace/theme-jsoneditor.js +144 -0
  90. data/vendor/lib/ace/theme-textmate.js +163 -0
  91. data/vendor/lib/ace/worker-json.js +1 -0
  92. data/vendor/lib/jsonlint/README.md +62 -0
  93. data/vendor/lib/jsonlint/jsonlint.js +432 -0
  94. data/vendor/misc/screenshots/actionsmenu_640x400.png +0 -0
  95. data/vendor/misc/screenshots/codeeditor_640x400.png +0 -0
  96. data/vendor/misc/screenshots/description.json +17 -0
  97. data/vendor/misc/screenshots/jsoneditoronline.png +0 -0
  98. data/vendor/misc/screenshots/jsoneditoronline_640x400.png +0 -0
  99. data/vendor/misc/screenshots/search_640x400.png +0 -0
  100. data/vendor/misc/screenshots/small_tile.xcf +0 -0
  101. data/vendor/misc/screenshots/small_tile_440x280.png +0 -0
  102. data/vendor/misc/todo.txt +101 -0
  103. data/vendor/package.json +28 -0
  104. data/vendor/test/couchdbeditor.html +100 -0
  105. data/vendor/test/largefile.json +12605 -0
  106. data/vendor/test/test_ace.html +60 -0
  107. data/vendor/test/test_editable_div.html +449 -0
  108. 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
+ };