locomotive-aloha-rails 0.20.1.2 → 0.20.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/Rakefile +1 -1
  2. data/lib/aloha/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/aloha/css/aloha.css +3 -0
  4. data/vendor/assets/javascripts/aloha/css/ext-aloha.css +3 -0
  5. data/vendor/assets/javascripts/aloha/lib/aloha-bootstrap.js +4565 -3934
  6. data/vendor/assets/javascripts/aloha/lib/aloha.js +1357 -702
  7. data/vendor/assets/javascripts/aloha/lib/aloha/command.js +16 -13
  8. data/vendor/assets/javascripts/aloha/lib/aloha/core.js +23 -3
  9. data/vendor/assets/javascripts/aloha/lib/aloha/ecma5shims.js +23 -7
  10. data/vendor/assets/javascripts/aloha/lib/aloha/editable.js +57 -14
  11. data/vendor/assets/javascripts/aloha/lib/aloha/engine.js +9 -5
  12. data/vendor/assets/javascripts/aloha/lib/aloha/floatingmenu.js +288 -96
  13. data/vendor/assets/javascripts/aloha/lib/aloha/jquery.js +11 -1
  14. data/vendor/assets/javascripts/aloha/lib/aloha/markup.js +318 -40
  15. data/vendor/assets/javascripts/aloha/lib/aloha/repositorymanager.js +11 -10
  16. data/vendor/assets/javascripts/aloha/lib/aloha/selection.js +20 -1
  17. data/vendor/assets/javascripts/aloha/lib/aloha/sidebar.js +11 -1
  18. data/vendor/assets/javascripts/aloha/lib/jquery-plugin.js +10 -7
  19. data/vendor/assets/javascripts/aloha/lib/util/dom.js +18 -6
  20. data/vendor/assets/javascripts/aloha/lib/util/range.js +6 -6
  21. data/vendor/assets/javascripts/aloha/lib/vendor/ext-3.2.1/ext-all-debug.js +26 -2
  22. data/vendor/assets/javascripts/aloha/lib/vendor/jquery.store.js +39 -15
  23. data/vendor/assets/javascripts/aloha/plugins/common/abbr/lib/abbr-plugin.js +1 -0
  24. data/vendor/assets/javascripts/aloha/plugins/common/align/lib/align-plugin.js +344 -334
  25. data/vendor/assets/javascripts/aloha/plugins/common/block/css/block.css +65 -12
  26. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/block-plugin.js +12 -15
  27. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/block.js +796 -180
  28. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/blockcontenthandler.js +54 -13
  29. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/blockmanager.js +315 -78
  30. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/editor.js +111 -8
  31. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/editormanager.js +2 -0
  32. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/jquery-ui-1.8.16.custom.min.js +198 -0
  33. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/sidebarattributeeditor.js +7 -20
  34. data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/lib/characterpicker-plugin.js +15 -3
  35. data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/lib/sanitizecontenthandler.js +3 -2
  36. data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/lib/wordcontenthandler.js +111 -5
  37. data/vendor/assets/javascripts/aloha/plugins/common/dom-to-xhtml/lib/dom-to-xhtml-plugin.js +29 -0
  38. data/vendor/assets/javascripts/aloha/plugins/common/dom-to-xhtml/lib/dom-to-xhtml.js +306 -0
  39. data/vendor/assets/javascripts/aloha/plugins/common/format/lib/format-plugin.js +59 -5
  40. data/vendor/assets/javascripts/aloha/plugins/common/format/nls/i18n.js +1 -1
  41. data/vendor/assets/javascripts/aloha/plugins/common/horizontalruler/lib/horizontalruler-plugin.js +18 -3
  42. data/vendor/assets/javascripts/aloha/plugins/common/image/img/crop-buttons.gif +0 -0
  43. data/vendor/assets/javascripts/aloha/plugins/common/image/lib/image-plugin.js +1629 -1601
  44. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/jcrop/jquery.jcrop.css +11 -0
  45. data/vendor/assets/javascripts/aloha/plugins/common/link/extra/linklist.js +8 -6
  46. data/vendor/assets/javascripts/aloha/plugins/common/link/lib/link-plugin.js +26 -10
  47. data/vendor/assets/javascripts/aloha/plugins/common/list/nls/de/i18n.js +5 -1
  48. data/vendor/assets/javascripts/aloha/plugins/common/paste/lib/paste-plugin.js +3 -4
  49. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table-cell.js +13 -12
  50. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table-plugin.js +108 -61
  51. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table-selection.js +61 -1
  52. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table.js +1 -0
  53. data/vendor/assets/javascripts/aloha/plugins/common/table/nls/de/i18n.js +28 -1
  54. data/vendor/assets/javascripts/aloha/plugins/common/table/nls/i18n.js +36 -10
  55. data/vendor/assets/javascripts/aloha/plugins/extra/browser/css/browser.jqgrid.css +292 -292
  56. data/vendor/assets/javascripts/aloha/plugins/extra/browser/lib/browser.js +28 -5
  57. data/vendor/assets/javascripts/aloha/plugins/extra/browser/lib/locale.js +2 -2
  58. data/vendor/assets/javascripts/aloha/plugins/extra/browser/vendor/grid.locale.de.js +6 -1
  59. data/vendor/assets/javascripts/aloha/plugins/extra/browser/vendor/grid.locale.en.js +5 -0
  60. data/vendor/assets/javascripts/aloha/plugins/extra/browser/vendor/jquery.jqGrid.js +5 -0
  61. data/vendor/assets/javascripts/aloha/plugins/extra/browser/vendor/jquery.jstree.js +6 -1
  62. data/vendor/assets/javascripts/aloha/plugins/extra/browser/vendor/jquery.ui.js +6 -1
  63. data/vendor/assets/javascripts/aloha/plugins/extra/browser/vendor/ui-layout.js +6 -1
  64. data/vendor/assets/javascripts/aloha/plugins/extra/cite/lib/cite-plugin.js +18 -4
  65. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/lib/formatlesspaste-plugin.js +1 -1
  66. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/lib/linkbrowser-plugin.js +14 -2
  67. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/demo/js/aloha-config.js +2 -2
  68. data/vendor/assets/javascripts/aloha/plugins/extra/toc/lib/toc-plugin.js +382 -0
  69. data/vendor/assets/javascripts/aloha/plugins/extra/toc/nls/de/i18n.js +3 -0
  70. data/vendor/assets/javascripts/aloha/plugins/extra/toc/nls/i18n.js +4 -0
  71. metadata +15 -11
  72. data/vendor/assets/javascripts/aloha/plugins/extra/toc/i18n/de.json +0 -1
  73. data/vendor/assets/javascripts/aloha/plugins/extra/toc/i18n/en.json +0 -1
  74. data/vendor/assets/javascripts/aloha/plugins/extra/toc/src/toc.js +0 -350
@@ -5,8 +5,14 @@
5
5
  * Licensed unter the terms of http://www.aloha-editor.com/license.html
6
6
  */
7
7
  define(
8
- ['aloha', 'aloha/jquery', 'aloha/plugin', 'aloha/floatingmenu', 'i18n!characterpicker/nls/i18n', 'i18n!aloha/nls/i18n', 'css!characterpicker/css/characterpicker.css'],
9
- function(Aloha, jQuery, Plugin, FloatingMenu, i18n, i18nCore) {
8
+ ['aloha',
9
+ 'aloha/jquery',
10
+ 'aloha/plugin',
11
+ 'aloha/floatingmenu',
12
+ 'i18n!characterpicker/nls/i18n',
13
+ 'i18n!aloha/nls/i18n',
14
+ 'css!characterpicker/css/characterpicker.css'],
15
+ function( Aloha, jQuery, Plugin, FloatingMenu, i18n, i18nCore ) {
10
16
 
11
17
 
12
18
  var
@@ -207,10 +213,14 @@ function(Aloha, jQuery, Plugin, FloatingMenu, i18n, i18nCore) {
207
213
  );
208
214
  self.characterOverlay = new CharacterOverlay(self.settings.characters, self.onCharacterSelect);
209
215
  },
216
+ /**
217
+ * insert a character after selecting it from the list
218
+ */
210
219
  onCharacterSelect: function(character) {
211
220
  var self = this;
212
221
  var range = Aloha.Selection.getRangeObject();
213
- if(Aloha.activeEditable) {
222
+
223
+ if( Aloha.activeEditable ) {
214
224
  var charNode = jQuery(document.createTextNode(character));
215
225
  GENTICS.Utils.Dom.insertIntoDOM(
216
226
  charNode,
@@ -218,6 +228,8 @@ function(Aloha, jQuery, Plugin, FloatingMenu, i18n, i18nCore) {
218
228
  jQuery(Aloha.activeEditable.obj),
219
229
  true
220
230
  );
231
+ range.startContainer = range.endContainer = charNode.get( 0 );
232
+ range.startOffset = range.endOffset = charNode.length;
221
233
  range.select();
222
234
  }
223
235
  }
@@ -62,7 +62,7 @@ function( Aloha, jQuery, ContentHandlerManager, console ) {
62
62
  ],
63
63
 
64
64
  attributes: {
65
- 'a': ['href', 'title', 'id', 'data-gentics-aloha-repository', 'data-gentics-aloha-object-id'],
65
+ 'a': ['href', 'title', 'id', 'class', 'data-gentics-aloha-repository', 'data-gentics-aloha-object-id'],
66
66
  'div': [ 'id', 'class'],
67
67
  'abbr': ['title'],
68
68
  'blockquote': ['cite'],
@@ -75,7 +75,8 @@ function( Aloha, jQuery, ContentHandlerManager, console ) {
75
75
  'table': ['summary', 'width'],
76
76
  'td': ['abbr', 'axis', 'colspan', 'rowspan', 'width'],
77
77
  'th': ['abbr', 'axis', 'colspan', 'rowspan', 'scope', 'width'],
78
- 'ul': ['type']
78
+ 'ul': ['type'],
79
+ 'span': ['class']
79
80
  },
80
81
 
81
82
  protocols: {
@@ -15,6 +15,7 @@ function( Aloha, jQuery, ContentHandlerManager ) {
15
15
  * @param content
16
16
  */
17
17
  handleContent: function( content ) {
18
+
18
19
  if ( typeof content === 'string' ){
19
20
  content = jQuery( '<div>' + content + '</div>' );
20
21
  } else if ( content instanceof jQuery ) {
@@ -120,7 +121,7 @@ function( Aloha, jQuery, ContentHandlerManager ) {
120
121
  var jqElem = jQuery(this),
121
122
  innerText = jqElem.text().trim().replace(/&nbsp;/g, ''),
122
123
  outerText;
123
-
124
+
124
125
  if (innerText.length === 0) {
125
126
  // check whether the outermost of the three spans contains nothing more than numbering
126
127
  outerText = jqElem.parent().parent().text().trim().replace(/&nbsp;/g, '');
@@ -257,21 +258,126 @@ function( Aloha, jQuery, ContentHandlerManager ) {
257
258
  Aloha.Markup.transformDomObject(jQuery(this), 'h1');
258
259
  });
259
260
  content.find('p.MsoSubtitle').each(function() {
260
- // titles will be transformed to h1
261
+ // sub titles will be transformed to h2
261
262
  Aloha.Markup.transformDomObject(jQuery(this), 'h2');
262
263
  });
263
264
  },
265
+
266
+ /**
267
+ * Cleanup MS Word HTML
268
+ * @param content
269
+ */
270
+ cleanHtml: function ( content ) {
271
+
272
+ // unwrap empty tags
273
+ // do not remove them here because of eg. spaces wrapped in spans which are needed
274
+ content.find('*').filter( function() {
275
+ return jQuery.trim(jQuery(this).text()) == '';
276
+ }).contents().unwrap();
277
+
278
+ // unwrap all spans
279
+ content.find('span').contents().unwrap();
280
+
281
+ // when href starts with #, it's the link to an anchor. remove it.
282
+ content.find('a').each(function() {
283
+ if ( jQuery(this).attr('href') && jQuery(this).attr('href').trim().match(/^#(.*)$/) ) {
284
+ jQuery(this).contents().unwrap();
285
+ }
286
+ });
287
+
288
+ // eg. footnotes are wrapped in divs. unwrap them.
289
+ content.find('div').contents().unwrap();
290
+
291
+ // remove empty tags
292
+ content.find('*').filter( function() {
293
+ return jQuery.trim(jQuery(this).text()) == '';
294
+ }).remove();
295
+
296
+ },
297
+
298
+ /**
299
+ * Remove paragraph numbering from TOC feature
300
+ * @param content
301
+ */
302
+ removeParagraphNumbering: function( content ) {
303
+ var detectionFilter = 'h1,h2,h3,h4,h5,h6',
304
+ paragraphs = content.find(detectionFilter);
305
+
306
+ if (paragraphs.length > 0) {
307
+ paragraphs.each(function() {
308
+ var jqElem = jQuery(this),
309
+ spans = jqElem.find('span'),
310
+ links = jqElem.find('a');
311
+
312
+ // remove TOC numbering
313
+ spans.each(function() {
314
+ if ( jQuery(this).text().trim().match(/^([\.\(]?[\d\D][\.\(]?){1,4}$/) ) {
315
+ jQuery(this).remove();
316
+ }
317
+ })
318
+
319
+ // remove TOC anchor links
320
+ links.each(function() {
321
+ // no href, so it's an anchor
322
+ if ( typeof jQuery(this).attr('href') === 'undefined' ) {
323
+ jQuery(this).contents().unwrap();
324
+ }
325
+ });
326
+
327
+ });
328
+ }
329
+ },
330
+
331
+
332
+ /**
333
+ * Transform TOC
334
+ * @param content
335
+ */
336
+ transformToc: function( content ) {
337
+ var detectionFilter = '[class*=MsoToc]',
338
+ paragraphs = content.find(detectionFilter);
339
+
340
+ paragraphs.each(function() {
341
+ var jqElem = jQuery(this),
342
+ spans = jqElem.find('span'),
343
+ links = jqElem.find('a');
344
+
345
+ // a table of contents entry looks like
346
+ // 1. Title text ... 5
347
+ // we get rid of the "... 5" part which repesents the page number
348
+ spans.each(function() {
349
+ if ( jQuery(this).attr('style') && jQuery(this).attr('style').search('mso-hide') > -1 ) {
350
+ jQuery(this).remove();
351
+ }
352
+ jQuery(this).contents().unwrap();
353
+ });
354
+
355
+ // remove the anchor link of the toc item
356
+ links.each(function() {
357
+ jQuery(this).contents().unwrap();
358
+ });
359
+ });
360
+ },
264
361
 
265
362
  /**
266
363
  * This is the main transformation method
267
364
  * @param content
268
365
  */
269
- transformWordContent: function (content) {
366
+ transformWordContent: function( content ) {
367
+ // transform table of contents
368
+ this.transformToc( content );
369
+
370
+ // remove paragraph numbering
371
+ this.removeParagraphNumbering( content );
372
+
270
373
  // transform lists
271
- this.transformListsFromWord(content);
374
+ this.transformListsFromWord( content );
272
375
 
273
376
  // transform titles
274
- this.transformTitles(content);
377
+ this.transformTitles( content );
378
+
379
+ // clean html
380
+ this.cleanHtml( content );
275
381
  }
276
382
  });
277
383
 
@@ -0,0 +1,29 @@
1
+ /*!
2
+ * Aloha Editor
3
+ * Author & Copyright (c) 2010 Gentics Software GmbH
4
+ * aloha-sales@gentics.com
5
+ * Licensed unter the terms of http://www.aloha-editor.com/license.html
6
+ */
7
+ /**
8
+ * The dom-to-xhtml plugin extends the serialization method of the
9
+ * Aloha.Editable.getContent() instance method to generate valid XHTML
10
+ * (in so far as the DOM of the editables itself is valid).
11
+ */
12
+ define(
13
+ ['aloha', 'aloha/jquery', 'aloha/plugin', 'dom-to-xhtml/dom-to-xhtml'],
14
+ function( Aloha, $, Plugin, domToXhtml) {
15
+
16
+
17
+ return Plugin.create('dom-to-xhtml', {
18
+ /**
19
+ * Called by the plugin-manager on intialization.
20
+ *
21
+ * @Override
22
+ */
23
+ init: function () {
24
+ Aloha.Editable.setContentSerializer(function(editableElement){
25
+ return domToXhtml.contentsToXhtml(editableElement);
26
+ });
27
+ }
28
+ });
29
+ });
@@ -0,0 +1,306 @@
1
+ /*!
2
+ * Aloha Editor
3
+ * Author & Copyright (c) 2010 Gentics Software GmbH
4
+ * aloha-sales@gentics.com
5
+ * Licensed unter the terms of http://www.aloha-editor.com/license.html
6
+ */
7
+ /**
8
+ * Provides public utility methods to convert DOM nodes to XHTML.
9
+ */
10
+ define(
11
+ ['aloha', 'aloha/jquery', 'aloha/console'],
12
+ function( Aloha, $, console) {
13
+
14
+
15
+ /**
16
+ * Gets the attributes of the given element.
17
+ *
18
+ * @param element
19
+ * An element to get the attributes for.
20
+ * @return
21
+ * An array of consisting of [name, value] tuples for each attribute.
22
+ * Attribute values may be strings, booleans or undefined.
23
+ */
24
+ function getAttrs(element) {
25
+ var attrs = element.attributes;
26
+ var cleanAttrs = [];
27
+ for ( var i = 0; i < attrs.length; i++ ) {
28
+ var attr = attrs[ i ];
29
+ if ( typeof attr.specified === "undefined" || attr.specified ) {
30
+ var name = attr.nodeName;
31
+ // Use jQuery to get a corrected style attribute on IE.
32
+ // Otherwise prefer getAttribute() over attr.nodeValue as the
33
+ // latter stringifies the attribute value.
34
+ // There seems to be a jQuery bug that returns undefined
35
+ // for the "checked" attribute on IE7, otherwise we
36
+ // could always use jquery.
37
+ var value = ( "style" === name ? $.attr(element, name) : element.getAttribute(name) );
38
+ cleanAttrs.push( [ name, value ] );
39
+ }
40
+ }
41
+ return cleanAttrs;
42
+ }
43
+
44
+ /**
45
+ * Elements that are to be serialized like <img /> and not like <img></img>
46
+ */
47
+ var emptyElements = [
48
+ "area", "base", "basefont", "br", "col", "frame", "hr",
49
+ "img", "input", "isindex", "link", "meta", "param", "embed" ];
50
+
51
+ /**
52
+ * Attributes that are to be serialized like checked="checked" for any true attribute value.
53
+ */
54
+ var booleanAttrs = [
55
+ "checked", "compact", "declare", "defer", "disabled", "ismap", "multiple",
56
+ "nohref", "noresize", "noshade", "nowrap", "readonly", "selected" ];
57
+
58
+ /**
59
+ * Encodes a string meant to be used wherever parsable character data occurs in XML.
60
+ * @param str
61
+ * An unencoded piece of character data
62
+ * @return
63
+ * The given string with & and < characters replaced with the corresponding HTML entity references.
64
+ */
65
+ function encodePcdata(str) {
66
+ return str.replace(/&/g, '&amp;').replace(/</g, '&lt;');
67
+ }
68
+
69
+ /**
70
+ * Encodes a string meant to be used between double-quoted attribute values.
71
+ *
72
+ * @param str
73
+ * An unencoded attribute value
74
+ * @return
75
+ * The given string with & < and " characters replaced with the corresponding HTML entity references.
76
+ */
77
+ function encodeDqAttrValue(str) {
78
+ return encodePcdata(str).replace(/"/g, '&quot;');
79
+ }
80
+
81
+ /**
82
+ * Serializes the attributes of the given element.
83
+ *
84
+ * Attributes that have the empty string as value will not appear in the string at all.
85
+ *
86
+ * @param element
87
+ * An element to serialize the attributes of
88
+ * @return
89
+ * A string made up of name="value" for each attribute of the
90
+ * given element, separated by space. The string will have a leading space.
91
+ */
92
+ function makeAttrString(element) {
93
+ var attrs = getAttrs(element);
94
+ var str = "";
95
+ for (var i = 0; i < attrs.length; i++) {
96
+ var name = attrs[i][0];
97
+ var value = attrs[i][1];
98
+ if ( "" === value || null == value ) {
99
+ // I don't think it is ever an error to make an
100
+ // attribute not appear if its string value is empty.
101
+ continue;
102
+ }
103
+ // The XHTML spec says attributes are lowercase
104
+ name = name.toLowerCase();
105
+ //TODO it's only a boolean attribute if the element is in an HTML namespace
106
+ var isBool = (-1 !== $.inArray(name, booleanAttrs));
107
+ if ( ! isBool || (isBool && value) ) {
108
+ str += " " + name + '="' + encodeDqAttrValue( "" + (isBool ? name : value) ) + '"';
109
+ }
110
+ }
111
+ return str;
112
+ }
113
+
114
+ /**
115
+ * IE8 turns the following
116
+ * <book id="x">{content}</book>
117
+ * into
118
+ * <book id="x"></book>{content}</book><//book>
119
+ * This seems to occur with any element IE doesn't recognize.
120
+ *
121
+ * @param element
122
+ * An element node.
123
+ * @return
124
+ * true if the given element isn't recognized by IE and
125
+ * causes a broken DOM structure as outlined above.
126
+ */
127
+ function isUnrecognized(element) {
128
+ var closingName = "/" + element.nodeName;
129
+ var sibling = element.nextSibling;
130
+ while (null != sibling) {
131
+ if (closingName == sibling.nodeName) {
132
+ return true;
133
+ }
134
+ sibling = sibling.nextSibling;
135
+ }
136
+ return false;
137
+ }
138
+
139
+ /**
140
+ * Serializes the children of the given element into an XHTML string.
141
+ *
142
+ * The same as serializeElement() except it only serializes the children.
143
+ * The start and end tag of the given element will not appear in the resulting XHTML.
144
+ *
145
+ * @see serializeElement()
146
+ */
147
+ function serializeChildren(element, child, unrecognized, xhtml) {
148
+ while (null != child) {
149
+ if (1 === child.nodeType && unrecognized && "/" + element.nodeName == child.nodeName) {
150
+ child = child.nextSibling;
151
+ break;
152
+ } else if (1 === child.nodeType && isUnrecognized(child)) {
153
+ child = serializeElement(child, child.nextSibling, true, xhtml);
154
+ } else {
155
+ serialize(child, xhtml);
156
+ child = child.nextSibling;
157
+ }
158
+ }
159
+ return child;
160
+ }
161
+
162
+ /**
163
+ * Serializes an element into an XHTML string.
164
+ *
165
+ * @param element
166
+ * An element to serialize.
167
+ * @param child
168
+ * The first child of the given element. This will usually be
169
+ * element.firstChild. On IE this may be element.nextSibling because
170
+ * of the broken DOM structure IE sometimes generates.
171
+ * @param unrecognized
172
+ * Whether the given element is unrecognized on IE. If IE doesn't
173
+ * recognize the element, it will create a broken DOM structure
174
+ * which has to be compensated for. See isUnrecognized() for more.
175
+ * @param xhtml
176
+ * An array which receives the serialized element and whic, if joined,
177
+ * will yield the XHTML string.
178
+ * @return
179
+ * null if all siblings of the given child have been processed as children
180
+ * of the given element, or otherwise the first sibling of child that is not considered
181
+ * a child of the given element.
182
+ */
183
+ function serializeElement(element, child, unrecognized, xhtml) {
184
+ // TODO: we should only lowercase element names if they are in an HTML namespace
185
+ var elementName = element.nodeName.toLowerCase();
186
+ // This is a hack around an IE bug which strips the namespace prefix
187
+ // of element.nodeName if it occurs inside an contentEditable=true.
188
+ if (element.scopeName && 'HTML' != element.scopeName && -1 === elementName.indexOf(':')) {
189
+ elementName = element.scopeName.toLowerCase() + ':' + elementName;
190
+ }
191
+ if ( ! unrecognized && null == child && -1 !== $.inArray(elementName, emptyElements) ) {
192
+ xhtml.push('<' + elementName + makeAttrString(element) + '/>');
193
+ } else {
194
+ xhtml.push('<' + elementName + makeAttrString(element) + '>');
195
+ child = serializeChildren(element, child, unrecognized, xhtml);
196
+ xhtml.push('</' + elementName + '>');
197
+ }
198
+ return child;
199
+ }
200
+
201
+ /**
202
+ * Serializes a DOM node into a XHTML string.
203
+ *
204
+ * @param node
205
+ * A DOM node to serialize.
206
+ * @param xhtml
207
+ * An array that will receive snippets of XHTML,
208
+ * which if joined will yield the XHTML string.
209
+ */
210
+ function serialize(node, xhtml) {
211
+ var nodeType = node.nodeType;
212
+ if (1 === nodeType) {
213
+ serializeElement(node, node.firstChild, isUnrecognized(node), xhtml);
214
+ } else if (3 === node.nodeType) {
215
+ xhtml.push(encodePcdata(node.nodeValue));
216
+ } else if (8 === node.nodeType) {
217
+ xhtml.push('<' + '!--' + node.nodeValue + '-->');
218
+ } else {
219
+ console.log('Unknown node type encountered during serialization, ignoring it:'
220
+ + ' type=' + node.nodeType
221
+ + ' name=' + node.nodeName
222
+ + ' value=' + node.nodeValue);
223
+ }
224
+ }
225
+
226
+ return {
227
+ /**
228
+ * Serializes a number of DOM nodes in an array-like object to an XHTML string.
229
+ *
230
+ * The XHTML of the nodes in the given array-like object will be concatenated.
231
+ *
232
+ * @param nodes
233
+ * An array or jQuery object or another array-like object to serialize.
234
+ * @return
235
+ * The serialized XHTML String representing the given DOM nodes in the given array-like object.
236
+ * The result may look like an XML fragment with multiple top-level elements and text nodes.
237
+ * @see nodeToXhtml()
238
+ */
239
+ contentsToXhtml: function(element) {
240
+ var xhtml = [];
241
+ serializeChildren(element, element.firstChild, false, xhtml);
242
+ return xhtml.join("");
243
+ },
244
+
245
+ /**
246
+ * Serializes a DOM node to an XHTML string.
247
+ *
248
+ * Beware that the serialization method will generate XHTML as
249
+ * close as possible to the DOM tree represented by the given
250
+ * node. The result will only be valid XHTML if the DOM tree
251
+ * doesn't violate any contained-in rules.
252
+ *
253
+ * Element attributes with an empty string as value will not
254
+ * appear in the serialized output.
255
+ *
256
+ * When iterating over the DOM, CDATA sections are comment nodes
257
+ * on some browsers (Chrome) and not there at all on others (IE).
258
+ * This is the same as what comes out from element.innerHTML.
259
+ *
260
+ * IE8 bug: comments will sometimes be silently stripped inside
261
+ * contentEditable=true. Conditional includes don't work inside
262
+ * contentEditable=true. See the tests for more information.
263
+ *
264
+ * IE8 bug: a title element will not be serialized correctly
265
+ * unless it occurs in the head of a HTML document, even if it occurs
266
+ * in a non-HTML namespace (maybe it works with a prefix).
267
+ * This will probably also apply for other HTML elements that
268
+ * occur in the header.
269
+ *
270
+ * IE8 bug: unrecognized elements in the HTML scope will cause
271
+ * broken DOM structure (some HTML5 elements that are not yet
272
+ * implemented in IE for example). Some effort was made to fix a
273
+ * broken DOM structure, if it is encountered. There is one case
274
+ * which results in an unrecoverably broken DOM structure, which
275
+ * is an unrecognized element not preceded by some text. See the
276
+ * tests for further information.
277
+ *
278
+ * IE8 bug: whitespace is not reliably preserved when the style
279
+ * white-space:pre (or similar) is used. See the tests for
280
+ * further information. Whitespace inside <pre> elements will
281
+ * be preserved, but \n characters will become \r characters.
282
+ *
283
+ * IE7 bug: URLs in href and src attributes of a and img
284
+ * elements will be absolutized (including hostname and
285
+ * protocol) if they are given as a relative path.
286
+ *
287
+ * IE bug: Namespace support inside contentEditable=true is a
288
+ * bit shaky on IE. Don't use it if possible. See the tests to
289
+ * get an idea of what seems to work. Make namespace prefixes
290
+ * and element names all lower-case, as they are always
291
+ * lower-cased, even if the element doesn't occur in an HTML
292
+ * namespace. Don't use default namespaces, use prefixes (except
293
+ * for an HTML namespace).
294
+ *
295
+ * @param node
296
+ * A DOM node to serialize
297
+ * @return
298
+ * The serialized XHTML string represnting the given DOM node.
299
+ */
300
+ nodeToXhtml: function(node) {
301
+ var xhtml = [];
302
+ serialize(node, xhtml);
303
+ return xhtml.join("");
304
+ }
305
+ };
306
+ });