var X_Node_Attr_noValue = {\r
- checked : 1,\r
- compact : 1,\r
- declare : 1,\r
- defer : 1,\r
- disabled : 1,\r
- ismap : 1,\r
- multiple : 1,\r
- nohref : 1,\r
- noresize : 1,\r
- noshade : 1,\r
- nowrap : 1,\r
- readonly : 1,\r
- selected : 1\r
+ 'checked' : 1,\r
+ 'compact' : 1,\r
+ 'declare' : 1,\r
+ 'defer' : 1,\r
+ 'disabled' : 1,\r
+ 'ismap' : 1,\r
+ 'multiple' : 1,\r
+ 'nohref' : 1,\r
+ 'noresize' : 1,\r
+ 'noshade' : 1,\r
+ 'nowrap' : 1,\r
+ 'readonly' : 1,\r
+ 'selected' : 1\r
},\r
X_Node_Attr_renameForDOM = {\r
- 'class' : 'className',\r
- accesskey : 'accessKey',\r
- 'accept-charset' : 'acceptCharset',\r
- bgcolor : 'bgColor',\r
- cellpadding : 'cellPadding',\r
- cellspacing : 'cellSpacing',\r
- 'char' : 'ch',\r
- charoff : 'chOff',\r
- codebase : 'codeBase',\r
- codetype : 'codeType',\r
- colspan : 'colSpan',\r
- datetime : 'dateTime',\r
- 'for' : 'htmlFor',\r
- frameborder : 'frameBorder',\r
- 'http-equiv' : 'httpEquiv',\r
- ismap : 'isMap',\r
- longdesc : 'longDesc',\r
- maxlength : 'maxLength',\r
- nohref : 'noHref',\r
- readonly : 'readOnly',\r
- rowspan : 'rowSpan',\r
- tabindex : 'tabIndex',\r
- usemap : 'useMap',\r
- valuetype : 'valueType',\r
- checked : 'defaultChecked'\r
+ 'class' : 'className',\r
+ 'accesskey' : 'accessKey',\r
+ 'accept-charset' : 'acceptCharset',\r
+ 'bgcolor' : 'bgColor',\r
+ 'cellpadding' : 'cellPadding',\r
+ 'cellspacing' : 'cellSpacing',\r
+ 'char' : 'ch',\r
+ 'charoff' : 'chOff',\r
+ 'codebase' : 'codeBase',\r
+ 'codetype' : 'codeType',\r
+ 'colspan' : 'colSpan',\r
+ 'datetime' : 'dateTime',\r
+ 'for' : 'htmlFor',\r
+ 'frameborder' : 'frameBorder',\r
+ 'http-equiv' : 'httpEquiv',\r
+ 'ismap' : 'isMap',\r
+ 'longdesc' : 'longDesc',\r
+ 'maxlength' : 'maxLength',\r
+ 'nohref' : 'noHref',\r
+ 'readonly' : 'readOnly',\r
+ 'rowspan' : 'rowSpan',\r
+ 'tabindex' : 'tabIndex',\r
+ 'usemap' : 'useMap',\r
+ 'valuetype' : 'valueType',\r
+ 'checked' : 'defaultChecked'\r
},\r
\r
X_Node_Attr_HAS_VALUE = {\r
- INPUT : true,\r
- TEXTAREA : true,\r
- SELECT : true,\r
- BUTTON : true,\r
- OBJECT : true,\r
- PARAM : true // FlashVars が flash 側から書き換えられるケースがある??\r
+ 'INPUT' : true,\r
+ 'TEXTAREA' : true,\r
+ 'SELECT' : true,\r
+ 'BUTTON' : true,\r
+ 'OBJECT' : true,\r
+ 'PARAM' : true // FlashVars が flash 側から書き換えられるケースがある??\r
},\r
\r
// <input type=button,hidden,submit,reset,radio,checkbox> の場合、value の値はユーザーで変えることはない\r
// <input type=text,password,file> はユーザーによって常に変更される HTML5 ではこれにさらにいろいろ加わる\r
X_Node_Attr_STATIC_VALUE_TYPES = {\r
- button : true,\r
- hidden : true,\r
- submit : true,\r
- reset : true,\r
- radio : true,\r
- checkbox : true\r
+ 'button' : true,\r
+ 'hidden' : true,\r
+ 'submit' : true,\r
+ 'reset' : true,\r
+ 'radio' : true,\r
+ 'checkbox' : true\r
+},\r
+\r
+// 自由な内容が入るため、参照文字への変換が必要\r
+X_Node_Attr_toChrReferance = {\r
+ 'value' : true,\r
+ 'title' : true,\r
+ 'alt' : true\r
},\r
\r
X_Node_Attr_renameForTag = {};\r
// http://nanto.asablo.jp/blog/2005/10/29/123294\r
// checked -> defaultChecked\r
// 動的に生成した input 要素を文書ツリーに挿入する前に設定した checked 属性は反映されず、defaultChecked だと反映される\r
- // 先頭にスペース\r
-function X_Node_Attr_objToAttrText( obj ){\r
- var noValue = X_Node_Attr_noValue,\r
- attrs = [ '' ], n = 0, k, v;\r
- if( !obj ) return ''; // Opera7\r
- for( k in obj ){\r
- //if( X_EMPTY_OBJECT[ k ] ) continue;\r
- v = obj[ k ];\r
- if( k === 'value' ){\r
- v = v.split( '"' ).join( '"' ).split( '>' ).join( '>' ).split( '<' ).join( '<' );\r
+ // ロードイベントを拾うために、要素生成時にネットワーク関連の属性を設定しない。\r
+ // -> src (img, iframe, ), link の href, <param name="movie" src=>\r
+ // \r
+function X_Node_Attr_objToAttrText( that, skipNetworkForElmCreation ){\r
+ var obj = that[ '_attrs' ],\r
+ noValue = X_Node_Attr_noValue,\r
+ attrs = [ '' ], // 先頭にスペース\r
+ plain = X_EMPTY_OBJECT,\r
+ n = 0, k, check;\r
+\r
+ if( skipNetworkForElmCreation ){\r
+ delete that[ '_newAttrs' ];\r
+ // このあとで _newAttr にネットワーク系の属性を控える, attrText には加えない\r
+ } else {\r
+ that[ '_flags' ] &= ~X_NodeFlags_OLD_ATTRTEXT;\r
+ // 完全な attrText\r
+ };\r
+ \r
+ if( !obj ){ // Opera7\r
+ delete that[ '_attrText' ];\r
+ return '';\r
+ };\r
+ \r
+ for( k in obj ){\r
+ if( plain[ k ] ) continue;\r
+ \r
+ if( skipNetworkForElmCreation ){\r
+ check = false;\r
+ switch( that[ '_tag' ] + k ){\r
+ case 'PARAMvalue' :\r
+ check = obj[ 'name' ] !== 'movie';\r
+ case 'INPUTsrc' :\r
+ check = check || ( obj[ 'type' ] !== 'image' );\r
+ case 'LINKhref' :\r
+ check = check || ( obj[ 'rel' ] !== 'stylesheet' );\r
+ \r
+ if( !check ) break;\r
+\r
+ case 'IMGsrc' :\r
+ case 'IFRAMEsrc' :\r
+ case 'FRAMEsrc' :\r
+ case 'SCRIPTsrc' :\r
+ case 'EMBEDsrc' :\r
+ case 'OBJECTdata' :\r
+ case 'BGSOUNDsrc' :\r
+ case 'APPLETcode' :\r
+ //case 'AUDIOsrc' :\r
+ //case 'VIDEOsrc' :\r
+ if( !that[ '_newAttrs' ] ) that[ '_newAttrs' ] = {};\r
+ that[ '_newAttrs' ][ k ] = obj[ k ];\r
+ continue;\r
};\r
- attrs[ ++n ] = noValue[ k ] ? k : [ k, '="', v, '"' ].join( '' );\r
};\r
- return 0 < n ? attrs.join( ' ' ) : '';\r
+\r
+ attrs[ ++n ] = noValue[ k ] ? k : [\r
+ k, '="',\r
+ X_Node_Attr_toChrReferance[ k ] ? X_String_toChrReferance( obj[ k ] ) : obj[ k ],\r
+ '"' ].join( '' );\r
+ };\r
+ \r
+ if( 0 < n ){\r
+ return that[ '_attrText' ] = attrs.join( ' ' );\r
+ };\r
+ delete that[ '_attrText' ];\r
+ return '';\r
};\r
\r
(function( renameForDOM, renameForTag ){\r
- var k, i;\r
+ var k;\r
for( k in renameForDOM ){\r
//if( X_EMPTY_OBJECT[ k ] ) continue;\r
renameForTag[ renameForDOM[ k ] ] = k;\r
})( X_Node_Attr_renameForDOM, X_Node_Attr_renameForTag );\r
\r
\r
-\r
-/* --------------------------------------\r
- * attribute\r
- * \r
- * http://nanto.asablo.jp/blog/2005/10/29/123294\r
- * className, onclick等 はここで設定しない\r
- * \r
+/**\r
+ * 属性の getter と setter。onclick等はできないので listen, listenOnce を使うこと。http://nanto.asablo.jp/blog/2005/10/29/123294\r
+ * @alias Node.prototype.attr\r
+ * @param {string|object} [nameOrObj] 属性名、または追加する属性のハッシュ\r
+ * @param {string|number} [value=] 属性の値\r
+ * @return {Node|string|number} getter の場合は値を、setter の場合は自身を返す。(メソッドチェーン)\r
+ * @example // getter\r
+ * node.attr( 'tagName' ) === 'DIV';\r
+ * // setter - 1\r
+ * node.attr( { src : url, width : 100, height : 100 } );\r
+ * // setter - 2\r
+ * node.attr( 'src', url );\r
*/\r
-Node.prototype.attr = function( nameOrObj /* v */ ){\r
- var attrs = this._attrs, newAttrs, f, k, elm, v;\r
+function X_Node_attr( nameOrObj /* v */ ){\r
+ var attrs = this[ '_attrs' ], newAttrs, f, k, elm, v;\r
\r
- if( this._xnodeType !== 1 ) return this;\r
+ if( !this[ '_tag' ] ) return this;\r
\r
- if( nameOrObj && X.Type.isObject( nameOrObj ) ){\r
- attrs || ( attrs = this._attrs = {} );\r
- newAttrs = this._newAttrs || ( this._newAttrs = {} );\r
+ if( nameOrObj && X_Type_isObject( nameOrObj ) ){\r
+ attrs || ( attrs = this[ '_attrs' ] = {} );\r
+ newAttrs = this[ '_newAttrs' ] || ( this[ '_newAttrs' ] = {} );\r
\r
for( k in nameOrObj ){\r
//if( X_EMPTY_OBJECT[ k ] ) continue;\r
if( X_Node_Attr_setAttr( this, attrs, newAttrs, k, nameOrObj[ k ] ) === true ) f = true;\r
};\r
if( f ){\r
- this._attrText = false;\r
- this._dirty |= X_Node_Dirty.ATTR;\r
- this._root && X_Node_reserveUpdate();\r
+ delete this[ '_attrText' ];\r
+ this[ '_flags' ] |= X_NodeFlags_DIRTY_ATTR | X_NodeFlags_OLD_ATTRTEXT;\r
+ this[ '_flags' ] & X_NodeFlags_IN_TREE && X_Node_reserveUpdate();\r
};\r
return this;\r
} else\r
if( 1 < arguments.length ){\r
// setter\r
- if( X_Node_Attr_setAttr( this, attrs || ( this._attrs = {} ), this._newAttrs || ( this._newAttrs = {} ), nameOrObj, arguments[ 1 ] ) === true ){\r
- this._attrText = false;\r
- this._dirty |= X_Node_Dirty.ATTR;\r
- this._root && X_Node_reserveUpdate();\r
+ if( X_Node_Attr_setAttr( this, attrs || ( this[ '_attrs' ] = {} ), this[ '_newAttrs' ] || ( this[ '_newAttrs' ] = {} ), nameOrObj, arguments[ 1 ] ) === true ){\r
+ delete this[ '_attrText' ];\r
+ this[ '_flags' ] |= X_NodeFlags_DIRTY_ATTR | X_NodeFlags_OLD_ATTRTEXT;\r
+ this[ '_flags' ] & X_NodeFlags_IN_TREE && X_Node_reserveUpdate();\r
};\r
return this;\r
} else\r
// getter\r
switch( nameOrObj ){\r
case 'id' :\r
- return this._id;\r
+ return this[ '_id' ];\r
case 'class' :\r
case 'className' :\r
- return this._className;\r
+ return this[ '_className' ];\r
case 'tag' :\r
case 'tagName' :\r
- return this._tag;\r
+ return this[ '_tag' ];\r
case 'style' :\r
case 'cssText' :\r
- return this.cssText();\r
- case 'text' :\r
- return this.text();\r
- case 'html' :\r
- case 'innerHTML' :\r
- return this.html();\r
- case 'outerHTML' :\r
- X_Node_outerXNode = this;\r
- v = this.html();\r
- X_Node_outerXNode = null;\r
- return v;\r
+ return this[ 'cssText' ]();\r
\r
+ case 'src' : // src は遷移して変化する, name も?\r
+ if( this[ '_tag' ] !== 'IFRAME' ) break;\r
+ if( this[ '_newAttrs' ] && X_Object_inObject( nameOrObj, this[ '_newAttrs' ] ) ) return this[ '_newAttrs' ][ nameOrObj ];\r
+ if( elm = X_UA_DOM.IE4 ? this[ '_rawObject' ] || X_Node__ie4getRawNode( this ) : this[ '_rawObject' ] ){\r
+ if( !attrs ) attrs = this[ '_attrs' ] = {};\r
+ return attrs[ nameOrObj ] = elm[ nameOrObj ]; // getAttribute( nameOrObj )?\r
+ };\r
+ break;\r
+ \r
case 'selected' :\r
// kquery.js : safariのバグ対策\r
// if ($.browser.safari && key === "selected" && tmp) tmp.selectedIndex;\r
// 親ノードの selectedIndex の getter を呼んでおくと値が正しくなる、ということ?( by itozyun )\r
- if( X_UA.WebKit ) this._rawObject.parentNode && this._rawObject.parentNode.selectedIndex;\r
+ if( X_UA[ 'WebKit' ] ) this[ '_rawObject' ].parentNode && this[ '_rawObject' ].parentNode.selectedIndex;\r
case 'value' :\r
- if( this._tag === 'INPUT' && X_Node_Attr_STATIC_VALUE_TYPES[ attrs[ 'type' ] ] ) break;\r
+ if( this[ '_tag' ] === 'INPUT' && X_Node_Attr_STATIC_VALUE_TYPES[ attrs[ 'type' ] ] ) break;\r
case 'checked' :\r
case 'disabled' : \r
case 'selectedIndex' :\r
- if( X_Node_Attr_HAS_VALUE[ this._tag ] ){\r
- if( this._newAttrs && X_Object_inObject( nameOrObj, this._newAttrs ) ) return this._newAttrs[ nameOrObj ];\r
- if( elm = X_UA_DOM.IE4 ? this._rawObject || X_Node__ie4getRawNode( this ) : this._rawObject ){\r
- if( !attrs ) attrs = this._attrs = {};\r
+ if( X_Node_Attr_HAS_VALUE[ this[ '_tag' ] ] ){\r
+ if( this[ '_newAttrs' ] && X_Object_inObject( nameOrObj, this[ '_newAttrs' ] ) ) return this[ '_newAttrs' ][ nameOrObj ];\r
+ if( elm = X_UA_DOM.IE4 ? this[ '_rawObject' ] || X_Node__ie4getRawNode( this ) : this[ '_rawObject' ] ){\r
+ if( !attrs ) attrs = this[ '_attrs' ] = {};\r
return attrs[ nameOrObj ] = elm[ nameOrObj ]; // getAttribute( nameOrObj )?\r
};\r
};\r
};\r
function X_Node_Attr_setAttr( that, attrs, newAttrs, name, v ){\r
switch( name ){\r
+ case 'ns' :\r
+ case 'NS' :\r
+ if( v === 'svg' || v === 'SVG' ){\r
+ that[ '_flags' ] |= X_NodeFlags_IS_SVG;\r
+ };\r
+ if( v === 'vml' || v === 'VML' ){\r
+ that[ '_flags' ] |= X_NodeFlags_IS_VML;\r
+ };\r
+ return;\r
+ \r
// case 'type' : TODO IE は input, button, object に対して type の再設定が出来ない _state が要素生成済なら不可\r
case 'UID' :\r
case 'tag' :\r
case 'tagName' :\r
return;\r
case 'id' :\r
- v = ( v !== 'ie4uid' + that._uid ) ? v : undefined;\r
+ v = ( v !== 'ie4uid' + that[ '_uid' ] ) ? v : undefined;\r
// TODO unique の check\r
- if( v !== that._id ){\r
- that._id = v;\r
- that._dirty |= X_Node_Dirty.ID;\r
- that._root && X_Node_reserveUpdate();\r
+ if( v !== that[ '_id' ] ){\r
+ that[ '_id' ] = v;\r
+ that[ '_flags' ] |= X_NodeFlags_DIRTY_ID;\r
+ that[ '_flags' ] & X_NodeFlags_IN_TREE && X_Node_reserveUpdate();\r
};\r
return; \r
case 'class' :\r
case 'className' :\r
- return that.className( v );\r
+ return that[ 'className' ]( v );\r
case 'style' :\r
case 'cssText' :\r
- return that.cssText( v );\r
+ return that[ 'cssText' ]( v );\r
case 'text' :\r
- return that.text( v );\r
+ return that[ 'text' ]( v );\r
case 'html' :\r
- return that.html( v );\r
+ return that[ 'html' ]( v );\r
};\r
// debug\r
if( name.indexOf( 'on' ) === 0 ){\r
\r
if( v == null ){\r
newAttrs[ name ] = undefined;\r
- if( attrs.hasOwnProperty( name ) ) delete attrs[ name ];\r
+ if( X_Object_inObject( name, attrs ) ) delete attrs[ name ];\r
} else {\r
newAttrs[ name ] = attrs[ name ] = v;\r
};\r