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