Skip to content

Commit

Permalink
Merge branch 'master' into frame-scope
Browse files Browse the repository at this point in the history
  • Loading branch information
gleneivey committed Apr 23, 2010
2 parents a1894aa + 2f6bee6 commit 97f13b8
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 131 deletions.
4 changes: 4 additions & 0 deletions specs/html/spec.js
Expand Up @@ -584,6 +584,8 @@ test('HTMLTitleElement', function() {
test("Image", function() {
var x = new Image();
equals(x, '[object HTMLImageElement]', 'toString');
equals(x.nodeName, 'IMG', 'constructor sets nodeName');
equals(x.tagName, 'IMG', 'contructor sets tagName');
equals(x.src, '', 'new image has src as empty string');

// determined experimentally
Expand Down Expand Up @@ -620,6 +622,8 @@ test("Image", function() {
test("Option", function() {
var x = new Option();
equals(x.toString(), '[object HTMLOptionElement]', 'toString');
equals(x.nodeName, 'OPTION', 'constructor sets nodeName');
equals(x.tagName, 'OPTION', 'constructor sets tagName');
equals(x.form, null, 'get form is null');
equals(x.selected, false, 'selected is false');

Expand Down
42 changes: 33 additions & 9 deletions src/css/htmlelement.js
@@ -1,6 +1,15 @@
/**
* This extends HTMLElement to handle CSS-specific interfaces.
*
* More work / research would be needed to extend just (DOM) Element
* for xml use and additional changes for just HTMLElement.
*/


/**
* @author envjs team
* Replace or add the getter for 'style'
*
* This could be wrapped in a closure
*/
var $css2properties = [{}];

Expand All @@ -12,19 +21,34 @@ __extend__(HTMLElement.prototype, {
}
return $css2properties[this.css2uuid];
},
setAttribute: function (name, value) {
Element.prototype.setAttribute.apply(this,[name, value]);
if (name === "style") {
__updateCss2Props__(this, value);
}
}
});

var __updateCss2Props__ = function(elem, values){
/**
* Change for how 'setAttribute("style", ...)' works
*
* We are truly adding functionality to HtmlElement.setAttribute, not
* replacing it. So we need to save the old one first, call it, then
* do our stuff. If we need to do more hacks like this, HTMLElement
* (or regular Element) needs to have a hooks array or dispatch table
* for global changes.
*
* This could be wrapped in a closure if desired.
*/
var updateCss2Props = function(elem, values) {
//console.log('__updateCss2Props__ %s %s', elem, values);
if ( !elem.css2uuid ) {
elem.css2uuid = $css2properties.length;
$css2properties[elem.css2uuid] = new CSS2Properties(elem);
}
__cssTextToStyles__($css2properties[elem.css2uuid], values);
};
}

var origSetAttribute = HTMLElement.prototype.setAttribute;

HTMLElement.prototype.setAttribute = function(name, value) {
//console.log("CSS set attribute: " + name + ", " + value);
origSetAttribute.apply(this, arguments);
if (name === "style") {
updateCss2Props(this, value);
}
}
6 changes: 6 additions & 0 deletions src/html/button.js
Expand Up @@ -17,6 +17,12 @@ __extend__(HTMLButtonElement.prototype, {
set dataFormatAs(value){
this.setAttribute('dataFormatAs',value);
},
get value() {
this.getAttribute('value') || '';
},
set value(value) {
this.setAttribute('value', value);
},
toString: function() {
return '[object HTMLButtonElement]';
}
Expand Down
52 changes: 51 additions & 1 deletion src/html/element.js
Expand Up @@ -5,6 +5,7 @@
HTMLElement = function(ownerDocument) {
Element.apply(this, arguments);
};

HTMLElement.prototype = new Element();
//TODO: Not sure where HTMLEvents belongs in the chain
// but putting it here satisfies a lowest common
Expand Down Expand Up @@ -198,28 +199,60 @@ __extend__(HTMLElement.prototype, {
}
}
},

/**
* setAttribute use a dispatch table that other tags can set to
* "listen" to various values being set. The dispatch table
* and registration functions are at the end of the file.
*
*
*/

setAttribute: function(name, value) {
var result = Element.prototype.setAttribute.apply(this, arguments);
this.ownerDocument._addNamedMap(this);
this._updateFormForNamedElement();
return result;

var tagname = this.tagName;
var callback = HTMLElement.getAttributeCallback('set', tagname, name);
if (callback) {
callback(this, value);
}
},
setAttributeNS: function(namespaceURI, name, value) {
var result = Element.prototype.setAttributeNS.apply(this, arguments);
this.ownerDocument._addNamedMap(this);
this._updateFormForNamedElement();

var tagname = this.tagName;
var callback = HTMLElement.getAttributeCallback('set', tagname, name);
if (callback) {
callback(this, value);
}

return result;
},
setAttributeNode: function(newnode) {
var result = Element.prototype.setAttributeNode.apply(this, arguments);
this.ownerDocument._addNamedMap(this);
this._updateFormForNamedElement();

var tagname = this.tagName;
var callback = HTMLElement.getAttributeCallback('set', tagname, newnode.name);
if (callback) {
callback(this, node.value);
}
return result;
},
setAttributeNodeNS: function(newnode) {
var result = Element.prototype.setAttributeNodeNS.apply(this, arguments);
this.ownerDocument._addNamedMap(this);
this._updateFormForNamedElement();
var tagname = this.tagName;
var callback = HTMLElement.getAttributeCallback('set', tagname, newnode.name);
if (callback) {
callback(this, node.value);
}
return result;
},
removeAttribute: function(name) {
Expand Down Expand Up @@ -254,3 +287,20 @@ __extend__(HTMLElement.prototype, {
return newnode;
}
});


HTMLElement.attributeCallbacks = {};
HTMLElement.registerSetAttribute = function(tag, attrib, callbackfn) {
HTMLElement.attributeCallbacks[tag + ':set:' + attrib] = callbackfn;
};
HTMLElement.registerRemoveAttribute = function(tag, attrib, callbackfn) {
HTMLElement.attributeCallbacks[tag + ':remove:' + attrib] = callbackfn;
};

/**
* This is really only useful internally
*
*/
HTMLElement.getAttributeCallback = function(type, tag, attrib) {
return HTMLElement.attributeCallbacks[tag + ':' + type + ':' + attrib] || null;
};
110 changes: 39 additions & 71 deletions src/html/img.js
Expand Up @@ -71,6 +71,7 @@ Image = function(width, height) {
// is not an integer. Safari just converts to 0 on error.
this.width = parseInt(width, 10) || 0;
this.height = parseInt(height, 10) || 0;
this.nodeName = 'IMG';
};
Image.prototype = new HTMLImageElement();

Expand Down Expand Up @@ -116,80 +117,47 @@ __loadImage__ = function(node, value) {
};

__extend__(HTMLImageElement.prototype, {
/*
* Image Loading
*
* The difference between "owner.parsing" and "owner.fragment"
*
* If owner.parsing === true, then during the html5 parsing then,
* __elementPopped__ is called when a compete tag (with attrs and
* children) is full parsed and added the DOM.
*
* For images, __elementPopped__ is called with everything the tag has.
* which in turn looks for a "src" attr and calls __loadImage__
*
* If owner.parser === false (or non-existant), then we are not in a parsing step.
* For images, perhaps someone directly modified a 'src' attribute of an
* existing image.
*
* 'innerHTML' is tricky since we first create a "fake document", parse it, then
* import the right parts. This may call img.setAttributeNS twice. once during the
* parse and once during the clone of the node. We want event to trigger on the later
* and not during th fake doco. "owner.fragment" is set by the fake doco parser to
* indicate that events should not be triggered on this.
*
* We coud make 'owner.parser' == [ 'none', 'full', 'fragment']
* and just use one variable That was not done since the patch is
* quite large as is.
*
* This same problem occurs with scripts. innerHTML oddly does
* not eval any <script> tags inside.
*/

setAttribute: function(name, value) {
var result = HTMLElement.prototype.setAttribute.apply(this, arguments);
var owner = this.ownerDocument;
if (name === 'src' && !owner.parsing && !owner.fragment) {
__loadImage__(this, value);
}
return result;
},
setAttributeNS: function(namespaceURI, name, value) {
var result = HTMLElement.prototype.setAttributeNS.apply(this, arguments);
var owner = this.ownerDocument;
if (name === 'src' && !owner.parsing && !owner.fragment) {
__loadImage__(this, value);
}
return result;
},
setAttributeNode: function(newnode) {
var src;
var result = HTMLElement.prototype.setAttributeNode.apply(this, arguments);
var owner = this.ownerDocument;
if (!owner.parsing && !owner.fragment) {
src = this.getAttribute('src');
if (src) {
__loadImage__(this, src);
}
}
return result;
},
setAttributeNodeNS: function(newnode) {
var result = HTMLElement.prototype.setAttributeNodeNS.apply(this, arguments);
var owner = this.ownerDocument;
if (!owner.parsing && !owner.fragment) {
var src = this.getAttribute('src');
if (src) {
__loadImage__(this, src);
}
}
return result;
},
onload: function(event){
__eval__(this.getAttribute('onload') || '', this);
}
});




/*
* Image Loading
*
* The difference between "owner.parsing" and "owner.fragment"
*
* If owner.parsing === true, then during the html5 parsing then,
* __elementPopped__ is called when a compete tag (with attrs and
* children) is full parsed and added the DOM.
*
* For images, __elementPopped__ is called with everything the
* tag has. which in turn looks for a "src" attr and calls
* __loadImage__
*
* If owner.parser === false (or non-existant), then we are not in
* a parsing step. For images, perhaps someone directly modified
* a 'src' attribute of an existing image.
*
* 'innerHTML' is tricky since we first create a "fake document",
* parse it, then import the right parts. This may call
* img.setAttributeNS twice. once during the parse and once
* during the clone of the node. We want event to trigger on the
* later and not during th fake doco. "owner.fragment" is set by
* the fake doco parser to indicate that events should not be
* triggered on this.
*
* We coud make 'owner.parser' == [ 'none', 'full', 'fragment']
* and just use one variable That was not done since the patch is
* quite large as is.
*
* This same problem occurs with scripts. innerHTML oddly does
* not eval any <script> tags inside.
*/
HTMLElement.registerSetAttribute('IMG', 'src', function(node, value) {
var owner = node.ownerDocument;
if (!owner.parsing && !owner.fragment) {
__loadImage__(node, value);
}
});
34 changes: 14 additions & 20 deletions src/html/input-elements.js
Expand Up @@ -4,7 +4,21 @@
*
* the hierarchy of related HTML elements and their members is as follows:
*
* Condensed Version
*
* HTMLInputCommon
* * legent (no value attr)
* * fieldset (no value attr)
* * label (no value attr)
* * option (custom)
* HTMLTypeValueInputs (extends InputCommon)
* * select (custom)
* * button (just sets value)
* HTMLInputAreaCommon (extends TypeValueIput)
* * input (X)
* * textarea (just sets value)
*
* -----------------------
* HTMLInputCommon: common to all elements
* .form
*
Expand Down Expand Up @@ -226,26 +240,6 @@ __extend__(HTMLTypeValueInputs.prototype, {
set type(type){
return this.setAttribute('type', type);
},
get value(){
return this.getAttribute('value')||'';
},
set value(newValue){
this.setAttribute('value',newValue);
},
setAttribute: function(name, value){
//console.log('setting defaultValue (NS)');
if(name == 'value' && !this.defaultValue){
this.defaultValue = value;
}
HTMLElement.prototype.setAttribute.apply(this, [name, value]);
},
setAttributeNS: function(uri, name, value){
//console.log('setting defaultValue (NS)');
if(name == 'value' && !this.defaultValue){
this.defaultValue = value;
}
HTMLElement.prototype.setAttributeNS.apply(this, [uri, name, value]);
}
});


Expand Down
9 changes: 9 additions & 0 deletions src/html/input.js
Expand Up @@ -60,3 +60,12 @@ __extend__(HTMLInputElement.prototype, {
});


//http://dev.w3.org/html5/spec/Overview.html#dom-input-value
// TODO: needs work, not even clear this is needed and can be moved
// up into the object
HTMLElement.registerSetAttribute('INPUT', 'value', function(node, value) {
//console.log('setting defaultValue (NS)');
if(!node.defaultValue){
node.defaultValue = value;
}
});

0 comments on commit 97f13b8

Please sign in to comment.