Skip to content
This repository has been archived by the owner on Dec 21, 2021. It is now read-only.

Commit

Permalink
AUI-152 - Special elements are not properly cloned
Browse files Browse the repository at this point in the history
git-svn-id: svn://svn.liferay.com/repos/public/alloy/trunk@59971 05bdf26c-840f-0410-9ced-eb539d925f36
  • Loading branch information
natecavanaugh committed Aug 10, 2010
1 parent 65ecdf3 commit 77c942c
Show file tree
Hide file tree
Showing 8 changed files with 627 additions and 42 deletions.
7 changes: 6 additions & 1 deletion ATTRIBUTION.txt
Expand Up @@ -6,4 +6,9 @@ Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses
Fugue Icons (icon_sprite.png)
Copyright (C) 2009 Yusuke Kamiyamane. All rights reserved.
The icons are licensed under a Creative Commons Attribution 3.0 license.
<http://creativecommons.org/licenses/by/3.0/>
<http://creativecommons.org/licenses/by/3.0/>
----------------------------------
Portions of the aui-node-base module
were used from the jQuery Javascript library
Copyright (c) 2010 John Resig & the jQuery team (http://jquery.com)
Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
130 changes: 123 additions & 7 deletions build/aui-node/aui-node-base-debug.js
Expand Up @@ -15,7 +15,9 @@ var Lang = A.Lang,

getClassName = A.ClassNameManager.getClassName,

CLONED_EVENTS = false,
STR_EMPTY = '',

ARRAY_EMPTY_STRINGS = [STR_EMPTY, STR_EMPTY],

HELPER = 'helper',

Expand All @@ -27,17 +29,25 @@ var Lang = A.Lang,
NONE = 'none',
PARENT_NODE = 'parentNode',
SCRIPT = 'script',

SUPPORT_CLONED_EVENTS = false,

VALUE = 'value';

// Event cloning detection support based on pieces from jQuery
/*
Parts of this file are used from jQuery (http://jquery.com)
Dual-licensed under MIT/GPL
*/
var div = document.createElement('div');
div.innerHTML = '&nbsp;'; // IE throws an error on fireEvent if the element does not have child nodes

div.style.display = 'none';
div.innerHTML = ' <link/><table></table>&nbsp;';

if (div.attachEvent && div.fireEvent) {
div.attachEvent(
'onclick',
function(){
CLONED_EVENTS = true;
SUPPORT_CLONED_EVENTS = true;

div.detachEvent('onclick', arguments.callee);
}
Expand All @@ -46,6 +56,43 @@ var Lang = A.Lang,
div.cloneNode(true).fireEvent('onclick');
}

var SUPPORT_SERIALIZE_HTML = !!div.getElementsByTagName('link').length,
SUPPORT_OPTIONAL_TBODY = !div.getElementsByTagName('tbody').length,
SUPPORT_LEADING_WHITESPACE = div.firstChild.nodeType === 3;

var REGEX_LEADING_WHITE_SPACE = /^\s+/,
REGEX_IE8_ACTION = /=([^=\x27\x22>\s]+\/)>/g,
REGEX_XHTML_TAG = /(<([\w:]+)[^>]*?)\/>/g,
REGEX_SELF_CLOSING_ELEMENT = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,
REGEX_TAGNAME = /<([\w:]+)/,
REGEX_TBODY = /<tbody/i,
REGEX_HTML = /<|&#?\w+;/,

FN_CLOSE_TAG = function(all, start, tagName) {
return REGEX_SELF_CLOSING_ELEMENT.test(tagName)
? all
: start + '></' + tagName + '>';
};

var MAP_WRAPPERS = {
_default: [0, STR_EMPTY, STR_EMPTY],
area: [1, '<map>', '</map>'],
col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
legend: [1, '<fieldset>', '</fieldset>'],
option: [1, '<select multiple="multiple">', '</select>'],
td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
thead: [1, '<table>', '</table>'],
tr: [2, '<table><tbody>', '</tbody></table>']
};

MAP_WRAPPERS.optgroup = MAP_WRAPPERS.option;
MAP_WRAPPERS.tbody = MAP_WRAPPERS.tfoot = MAP_WRAPPERS.colgroup = MAP_WRAPPERS.caption = MAP_WRAPPERS.thead;
MAP_WRAPPERS.th = MAP_WRAPPERS.td;

if (!SUPPORT_SERIALIZE_HTML) {
MAP_WRAPPERS._default = [1, 'div<div>', '</div>'];
}

/**
* Augment the <a href="Node.html">YUI3 Node</a> with more util methods.
*
Expand Down Expand Up @@ -215,13 +262,17 @@ A.mix(A.Node.prototype, {
clone: (function() {
var clone;

if (CLONED_EVENTS) {
if (SUPPORT_CLONED_EVENTS) {
clone = function() {
var el = this.getDOM();
var clone;

if (el.nodeType != 3) {
clone = A.Node.create(this.outerHTML())
var outerHTML = this.outerHTML();

outerHTML = outerHTML.replace(REGEX_IE8_ACTION, '="$1">').replace(REGEX_LEADING_WHITE_SPACE, '');

clone = A.one(A.Node._prepareHTML(outerHTML)[0]);
}
else {
clone = A.one(el.cloneNode());
Expand Down Expand Up @@ -913,7 +964,7 @@ A.mix(A.Node.prototype, {
var parent = instance.get(PARENT_NODE);

if (parent) {
if (Lang.isString(newNode)) {
if (isString(newNode)) {
newNode = A.Node.create(newNode);
}

Expand All @@ -933,6 +984,71 @@ A.mix(A.Node.prototype, {
}
}, true);

A.Node._prepareHTML = function(element) {
var doc = A.config.doc;

var returnData = [];

if (isString(element)) {
if (!REGEX_HTML.test(element)) {
element = doc.createTextNode(element);
}
else {
element = element.replace(REGEX_XHTML_TAG, FN_CLOSE_TAG);

var tagName = (REGEX_TAGNAME.exec(element) || ARRAY_EMPTY_STRINGS)[1].toLowerCase();
var wrap = MAP_WRAPPERS[tagName] || MAP_WRAPPERS._default;
var depth = wrap[0];
var div = doc.createElement('div');

div.innerHTML = wrap[1] + element + wrap[2];

while (depth--) {
div = div.lastChild;
}

if (!SUPPORT_OPTIONAL_TBODY) {
var hasTBody = REGEX_TBODY.test(element);
var tbody = [];

if (tagName == 'table' && !hasTBody) {
if (div.firstChild) {
tbody = div.firstChild.childNodes;
}
}
else {
if (wrap[1] == '<table>' && !hasTBody) {
tbody = div.childNodes;
}
}

for (var i = tbody.length - 1; i >= 0; --i) {
var node = tbody[i];

if (node.nodeName.toLowerCase() == 'tbody' && node.childNodes.length) {
node.parentNode.removeChild(node);
}
}
}

if (!SUPPORT_LEADING_WHITESPACE && REGEX_LEADING_WHITE_SPACE.test(element)) {
div.insertBefore(doc.createTextNode(REGEX_LEADING_WHITE_SPACE.exec(element)[0]), div.firstChild);
}

element = div.childNodes;
}
}

if (element.nodeType) {
returnData.push(element);
}
else {
returnData = element;
}

return returnData;
};

/**
* Augment the <a href="NodeList.html">YUI3 NodeList</a> with more util methods.
*
Expand Down
4 changes: 2 additions & 2 deletions build/aui-node/aui-node-base-min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 77c942c

Please sign in to comment.