リビジョン | bafa8683f87b2f909d1301fca80684bf9ff221ed (tree) |
---|---|
日時 | 2016-02-26 17:17:01 |
作者 | itozyun <itozyun@user...> |
コミッター | itozyun |
Version 0.6.213, add X.Node.TextRange.
@@ -2,7 +2,7 @@ | ||
2 | 2 | // ------------------------------------------------------------------------- // |
3 | 3 | // ------------ local variables -------------------------------------------- // |
4 | 4 | // ------------------------------------------------------------------------- // |
5 | -var X_String_CRLF = String.fromCharCode( 13 ) + String.fromCharCode( 10 ); | |
5 | +var X_String_CRLF = String.fromCharCode( 13 ) + String.fromCharCode( 10 ), | |
6 | 6 | X_String_CHAR_REFS = {"¡":161,"¢":162,"£":163,"¤":164,"¥":165,"¦":166,"§":167,"¨":168,"©":169, |
7 | 7 | "ª":170,"«":171, |
8 | 8 | "¬":172,"­":173,"®":174,"¯":175,"°":176,"±":177,"²":178,"³":179,"´":180,"µ":181,"¶":182, |
@@ -270,6 +270,7 @@ X[ 'ViewPort' ] = { | ||
270 | 270 | // http://orera.g.hatena.ne.jp/edvakf/20100515/1273908051 |
271 | 271 | //http://onozaty.hatenablog.com/entry/20060803/p1 |
272 | 272 | // Safari2.0.4では標準・互換どちらも document.body |
273 | + // http://hisasann.com/housetect/2008/08/jqueryheightwidthopera95.html このdocument.body[ "client" + name ]はおそらくOpera9.5未満のバージョンで有効なんじゃないかな? | |
273 | 274 | |
274 | 275 | X_Node_updateTimerID && X_Node_startUpdate(); |
275 | 276 | /*X_UA[ 'Opera' ] ? |
@@ -19,6 +19,11 @@ var X_Dom_Event_devicePixelRatio = window.devicePixelRatio || ( window.screen.de | ||
19 | 19 | '3' : 'pen', |
20 | 20 | '4' : 'mouse' |
21 | 21 | }; */ |
22 | + /* | |
23 | + * https://github.com/markleusink/ios-html5-drag-drop-shim/blob/master/ios-drag-drop.js | |
24 | + */ | |
25 | + X_Dom_Event_coordinateSystemForElementFromPoint = X_UA[ 'iOS' ] < 5 ? 'page' : 'client', // iOS4 以下は clientX が undeifned... | |
26 | + | |
22 | 27 | X_Dom_Event_CANCEL_MOUSE = {}, |
23 | 28 | X_DomEvent; |
24 | 29 |
@@ -31,9 +36,10 @@ if( X_Dom_Event_devicePixelRatio !== 1 ){ | ||
31 | 36 | if( !X_UA[ 'IE' ] || 9 <= X_UA[ 'IE' ] ){ |
32 | 37 | X_DomEvent = function( e, xnode ){ |
33 | 38 | var originalType = e.type, |
39 | + isNum = X_Type_isNumber, | |
34 | 40 | type, pointerEventType, |
35 | 41 | touches, events, |
36 | - altKey, ctrlKey, metaKey, shiftKey, target, related, force, | |
42 | + altKey, ctrlKey, metaKey, shiftKey, target, xtarget, offset, related, force, | |
37 | 43 | elm, i, n, time, touch, ev; |
38 | 44 | |
39 | 45 | //this._event = e; |
@@ -63,11 +69,13 @@ if( !X_UA[ 'IE' ] || 9 <= X_UA[ 'IE' ] ){ | ||
63 | 69 | //console.log( 'original : ' + originalType + ' > ' + type ); |
64 | 70 | // http://msdn.microsoft.com/ja-jp/library/ie/dn304886%28v=vs.85%29.aspx |
65 | 71 | // ポインター イベントの更新 |
66 | - if( e.pointerType ){ | |
72 | + if( e.pointerType || | |
73 | + // IE11 の IE10 モードで click イベントの pointerType が undefined | |
74 | + ( X_UA[ 'IE' ] === 10 && type === 'click' && ( e.pointerType = 'mouse' ) ) ){ | |
67 | 75 | // PointerEvent; |
68 | 76 | if( X_Dom_Event_convertMSPointerType ){ |
69 | 77 | this[ 'pointerType' ] = X_Dom_Event_convertMSPointerType[ e.pointerType ]; |
70 | - this[ 'pressure' ] = e.pressure || ( e.button !== -1 ? 0.5 : 0 ); | |
78 | + this[ 'pressure' ] = isNum( e.pressure ) ? e.pressure : ( e.button !== -1 ? 0.5 : 0 ); | |
71 | 79 | // ポインターの接触形状の スクリーン ピクセル単位の幅と高さ なので変換。(多分、、、) |
72 | 80 | this[ 'width' ] = e.width / X_Dom_Event_devicePixelRatio; |
73 | 81 | this[ 'height' ] = e.height / X_Dom_Event_devicePixelRatio; |
@@ -139,11 +147,16 @@ if( !X_UA[ 'IE' ] || 9 <= X_UA[ 'IE' ] ){ | ||
139 | 147 | for( i = touches.length; i; ){ |
140 | 148 | touch = touches[ --i ]; |
141 | 149 | target = touch.target; |
150 | + target = target.nodeType === 3 ? target.parentNode : target; | |
151 | + xtarget = X_Node_getXNode( target ); | |
152 | + // https://developer.mozilla.org/en/docs/Web/API/Element/getBoundingClientRect | |
153 | + // Android 2+, iOS4+ | |
154 | + offset = X_UA[ 'iOS' ] < 5 ? xtarget.offset() : target.getBoundingClientRect(); | |
142 | 155 | related = touch.relatedTarget; |
143 | 156 | events[ i ] = { |
144 | 157 | 'type' : pointerEventType, |
145 | 158 | 'pointerType' : 'touch', |
146 | - 'target' : X_Node_getXNode( target.nodeType === 3 ? target.parentNode : target ),// defeat Safari bug // xnodetouch.target, | |
159 | + 'target' : xtarget,// defeat Safari bug // xnodetouch.target, | |
147 | 160 | 'currentTarget' : xnode, |
148 | 161 | 'relatedTarget' : related && X_Node_getXNode( related.nodeType === 3 ? related.parentNode : related ), // xnode iOS3 には relatedTarget がない |
149 | 162 | 'isPrimary' : true, |
@@ -158,12 +171,17 @@ if( !X_UA[ 'IE' ] || 9 <= X_UA[ 'IE' ] ){ | ||
158 | 171 | 'pointerId' : touch.identifier + 2, // iOS4 は 変換が必要! |
159 | 172 | //screenX : touch.screenX, |
160 | 173 | //screenY : touch.screenY, |
161 | - 'clientX' : touch.clientX || ( touch.pageX - X_ViewPort_scrollX ), // iOS4以下は clientX が undefined, コードでは入れ子のスクロールに対応できない | |
162 | - 'clientY' : touch.clientY || ( touch.pageY - X_ViewPort_scrollY ), | |
163 | 174 | 'pageX' : touch.pageX, |
164 | - 'pageY' : touch.pageY, | |
165 | - 'offsetX' : touch.offsetX, // 要素上の座標を取得 | |
166 | - 'offsetY' : touch.offsetY, | |
175 | + 'pageY' : touch.pageY, | |
176 | + // iOS4 以下では clientX が undef, pageX から scrollLeft を引く. | |
177 | + // TODO getter にする? | |
178 | + 'clientX' : isNum( touch.clientX ) ? touch.clientX : ( touch.pageX - X_ViewPort_scrollX ), | |
179 | + 'clientY' : isNum( touch.clientY ) ? touch.clientY : ( touch.pageY - X_ViewPort_scrollY ), | |
180 | + // 要素上の座標を取得 | |
181 | + // iOS8 でも offsetX が undef, iOS4 以下では pageX - offset.x, iOS5 以上は clientX - getBCR.left | |
182 | + // TODO getter にする? | |
183 | + 'offsetX' : isNum( touch.offsetX ) ? touch.offsetX : touch[ X_Dom_Event_coordinateSystemForElementFromPoint + 'X' ] - ( offset.x || offset.left || 0 ), | |
184 | + 'offsetY' : isNum( touch.offsetY ) ? touch.offsetY : touch[ X_Dom_Event_coordinateSystemForElementFromPoint + 'Y' ] - ( offset.y || offset.top || 0 ), | |
167 | 185 | 'radiusX' : touch.radiusX || 0, |
168 | 186 | 'radiusY' : touch.radiusY || 0, |
169 | 187 | 'rotationAngle' : touch.rotationAngle || 0, |
@@ -172,6 +190,7 @@ if( !X_UA[ 'IE' ] || 9 <= X_UA[ 'IE' ] ){ | ||
172 | 190 | 'height' : touch.height || 0 |
173 | 191 | }; |
174 | 192 | //console.log( 'e.pointerId = ' + touch.identifier ); |
193 | + //X_UA[ 'iOS' ] < 5 && console.log( pointerEventType + ':[' + events[ i ].pageX + ',' + events[ i ].pageY + ']' + events[ i ].pointerId ); | |
175 | 194 | }; |
176 | 195 | return events.length === 1 ? events[ 0 ] : events; |
177 | 196 | } else { |
@@ -206,8 +225,8 @@ if( !X_UA[ 'IE' ] || 9 <= X_UA[ 'IE' ] ){ | ||
206 | 225 | this[ 'clientY' ] = e.clientY; |
207 | 226 | this[ 'pageX' ] = e.pageX; |
208 | 227 | this[ 'pageY' ] = e.pageY; |
209 | - this[ 'offsetX' ] = e.offsetX || e.layerX; // 要素上の座標を取得 | |
210 | - this[ 'offsetY' ] = e.offsetY || e.layerY; | |
228 | + this[ 'offsetX' ] = isNum( e.offsetX ) ? e.offsetX : e.layerX; // 要素上の座標を取得 | |
229 | + this[ 'offsetY' ] = isNum( e.offsetY ) ? e.offsetY : e.layerY; | |
211 | 230 | |
212 | 231 | // http://www.programming-magic.com/20090127231544/ |
213 | 232 | // Opera で button==2の場合、コンテキストメニューイベントを発火 「ツール」->「設定」->「詳細設定」->「コンテンツ」->「Javascriptオプション」で「右クリックを制御するスクリプトを許可する」 |
@@ -237,6 +237,8 @@ function X_Node_offset(){ | ||
237 | 237 | // エレメントの座標取得 ~スクロール要素~ |
238 | 238 | // http://n-yagi.0r2.net/script/2009/07/post_16.html |
239 | 239 | |
240 | +// TODO getClientRects Safari2- ? | |
241 | + | |
240 | 242 | //■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ |
241 | 243 | // エレメントの絶対座標を得たい |
242 | 244 | //------------------------------------------------------------------------------ |
@@ -246,7 +248,7 @@ var X_Node_getPosition = | ||
246 | 248 | ( |
247 | 249 | document.compatMode === 'CSS1Compat' && !X_UA[ 'Webkit' ] ? function( el ){ |
248 | 250 | var pos = el.getBoundingClientRect(), |
249 | - html = document.documentElement; | |
251 | + html = X_elmHtml; | |
250 | 252 | return { x:(pos.left + html.scrollLeft - html.clientLeft) |
251 | 253 | , y:(pos.top + html.scrollTop - html.clientTop) }; |
252 | 254 | } : |
@@ -611,6 +611,7 @@ function X_Node_Selector__parse( query, last ){ | ||
611 | 611 | var l = xnodes.length, |
612 | 612 | i = 0, |
613 | 613 | j, child, _xnodes; |
614 | + | |
614 | 615 | for( ; i < l; ++i ){ |
615 | 616 | child = xnodes[ i ]; |
616 | 617 | if( !child[ '_tag' ] ) continue; |
@@ -635,7 +636,8 @@ function X_Node_Selector__parse( query, last ){ | ||
635 | 636 | var l = xnodes.length, |
636 | 637 | i = 0, |
637 | 638 | child, uid, _tag, _xnodes; |
638 | - for( ; i < l; ++i ){ | |
639 | + | |
640 | + for( ; i < l; ++i ){ // for( ; child = xnodes[ ++i ]; ) | |
639 | 641 | child = xnodes[ i ]; |
640 | 642 | uid = child[ '_uid' ]; |
641 | 643 | _tag = child[ '_tag' ]; |
@@ -12,9 +12,7 @@ var X_NodeAnime_QUEUE = [], | ||
12 | 12 | /* Opera mobile で translateZ(0) が有効だと XY が 0 0 になる */ |
13 | 13 | /* GPUレイヤーにいる間に要素のコンテンツを変更をすると transitionend が動かなくなるっぽい Mac safari と firefox */ |
14 | 14 | X_NodeAnime_translateZ = X_Node_CSS_VENDER_PREFIX[ 'perspective' ] && |
15 | - !X_UA[ 'OperaMobile' ] && !X_UA[ 'OperaTablet' ] //&& | |
16 | - /* ハードウェアによると思うが IE11 と Win8.1 で画面(塗)が乱れる */ | |
17 | - /* !( ( X_UA[ 'IE' ] === 11 || X_UA[ 'IEHost' ] === 11 ) && X_UA[ 'Windows' ] === 8.1 ) */ ? ' translateZ(0)' : '', | |
15 | + !X_UA[ 'OperaMobile' ] && !X_UA[ 'OperaTablet' ] ? ' translateZ(0)' : '', | |
18 | 16 | |
19 | 17 | /* |
20 | 18 | * phase: |
@@ -354,7 +352,7 @@ function X_NodeAnime_updateAnimations( e ){ | ||
354 | 352 | now = X_Timer_now(), |
355 | 353 | c = false, |
356 | 354 | i, xnode, obj, _xnode, |
357 | - rm, easing, lazy; | |
355 | + rm, progress, easing, lazy; | |
358 | 356 | |
359 | 357 | if( X_NodeAnime_needsDetection ){ |
360 | 358 | X_NodeAnime_needsDetection = false; |
@@ -384,8 +382,8 @@ function X_NodeAnime_updateAnimations( e ){ | ||
384 | 382 | switch( obj.phase ){ |
385 | 383 | case 7 : // アニメーション中 |
386 | 384 | if( now < obj.toTime ){ |
387 | - obj.progress = ( now - obj.fromTime ) / obj.duration; | |
388 | - easing = obj.easing( obj.progress ); | |
385 | + obj.progress = progress = ( now - obj.fromTime ) / obj.duration; | |
386 | + easing = obj.easing( progress ); | |
389 | 387 | obj.x = ( obj.toX - obj.fromX ) * easing + obj.fromX; |
390 | 388 | obj.y = ( obj.toY - obj.fromY ) * easing + obj.fromY; |
391 | 389 | obj.rotate = ( obj.toRotate - obj.fromRotate ) * easing + obj.fromRotate; |
@@ -396,7 +394,7 @@ function X_NodeAnime_updateAnimations( e ){ | ||
396 | 394 | obj.alpha = ( obj.toAlpha - obj.fromAlpha ) * easing + obj.fromAlpha; |
397 | 395 | obj.scrollX = ( obj.toScrollX - obj.fromScrollX ) * easing + obj.fromScrollX; |
398 | 396 | obj.scrollY = ( obj.toScrollY - obj.fromScrollY ) * easing + obj.fromScrollY; |
399 | - X_NodeAnime_updatePosition( xnode, obj, obj.progress, true ); | |
397 | + X_NodeAnime_updatePosition( xnode, obj, progress, true ); | |
400 | 398 | c = true; |
401 | 399 | break; |
402 | 400 | }; |
@@ -253,6 +253,8 @@ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ]( | ||
253 | 253 | |
254 | 254 | 'createTextAt' : X_Node_createTextAt, |
255 | 255 | |
256 | + 'createRange' : X_Node_createRange, | |
257 | + | |
256 | 258 | 'clone' : X_Node_clone, |
257 | 259 | |
258 | 260 | 'append' : X_Node_append, |
@@ -494,6 +496,15 @@ function X_Node_createTextAt( index, text ){ | ||
494 | 496 | }; |
495 | 497 | |
496 | 498 | /** |
499 | + * 選択されたテキストへの参照やテキスト座標情報 | |
500 | + * @alias Node.prototype.createRange | |
501 | + * @return {TextRange} 新規作成されたテキストレンジ | |
502 | + */ | |
503 | +function X_Node_createRange( a, b, c ){ | |
504 | + return X_TextRange( this, a, b, c ); | |
505 | +}; | |
506 | + | |
507 | +/** | |
497 | 508 | * Node のクローンを作成し返す。id もクローンされる点に注意。イベントリスナはクローンされない。 |
498 | 509 | * http://d.hatena.ne.jp/think49/20110724/1311472811 |
499 | 510 | * http://d.hatena.ne.jp/uupaa/20100508/1273299874 |
@@ -0,0 +1,275 @@ | ||
1 | +/* | |
2 | + * tr = X.Doc.createRange('selection') | |
3 | + * X.Doc.createRange({from : num, to : num}) | |
4 | + * tr = xnode.createRange( from, to ), | |
5 | + * ( 'selection' ) docment の slection のうち xnode の配下のもの | |
6 | + * ( 'char', from, to ) | |
7 | + * ( 'line', index ), | |
8 | + * ( 'point', x, y ) | ( 'point', e ) | |
9 | + * tr.move( startIndex, endIndex ) | |
10 | + * tr.getRect() { width, height, x, y } | |
11 | + * tr.getOffset() { from, to } | |
12 | + * tr.text() | |
13 | + * | |
14 | + * naming は mozilla に寄せる | |
15 | + */ | |
16 | + | |
17 | +var X_TextRange_range, | |
18 | + X_TextRange_range2, | |
19 | + X_TextRange_isW3C = !document.selection || 10 <= X_UA[ 'IE' ]; | |
20 | + | |
21 | +/** | |
22 | + * ユーザーによって選択されたテキストへの参照や文字の座標の取得 | |
23 | + * @alias X.TextRange | |
24 | + * @class TextRange テキストレンジ | |
25 | + * @extends {__ClassBase__} | |
26 | + */ | |
27 | +var X_TextRange = X_Class_create( | |
28 | + 'X.TextRange', | |
29 | + | |
30 | + /** @lends X.TextRange.prototype */ | |
31 | + { | |
32 | + xnode : null, | |
33 | + createFrom : '', | |
34 | + v1 : 0, | |
35 | + v2 : 0, | |
36 | + | |
37 | + 'Constructor' : function( xnode, arg2, arg3, arg4 ){ | |
38 | + if( !X_TextRange_range ){ | |
39 | + X_TextRange_range = X_TextRange_isW3C ? document.createRange() : X_elmBody.createTextRange(); | |
40 | + if( !X_TextRange_isW3C ) X_TextRange_range2 = X_elmBody.createTextRange(); | |
41 | + }; | |
42 | + | |
43 | + this.xnode = xnode; | |
44 | + | |
45 | + switch( arg2 ){ | |
46 | + case 'selection' : | |
47 | + //break; | |
48 | + case 'point' : | |
49 | + case 'char' : | |
50 | + this.createFrom = arg2; | |
51 | + break; | |
52 | + default : | |
53 | + arg4 = arg3; | |
54 | + arg3 = arg2; | |
55 | + }; | |
56 | + | |
57 | + if( arg2 !== 'selection' ){ | |
58 | + this.v1 = arg3 || 0; | |
59 | + this.v2 = arg4 || 0; | |
60 | + }; | |
61 | + }, | |
62 | + | |
63 | + 'getRect' : X_TextRange_getRect, | |
64 | + | |
65 | + 'getOffset' : X_TextRange_getOffset, | |
66 | + | |
67 | + 'text' : X_TextRange_text | |
68 | + } | |
69 | +); | |
70 | + | |
71 | +// TextNode を探して flat な配列に格納する | |
72 | +function X_TextRange_collectTextNodes( elm, ary ){ | |
73 | + var kids = elm.childNodes, | |
74 | + i, e; | |
75 | + | |
76 | + if( !kids || !kids.length ) return; | |
77 | + | |
78 | + for( i = 0; e = kids[ i ]; ++i ){ | |
79 | + switch( e.nodeType ){ | |
80 | + case 1 : | |
81 | + X_TextRange_collectTextNodes( e, ary ); | |
82 | + break; | |
83 | + case 3 : | |
84 | + ary[ ary.length ] = e; | |
85 | + break; | |
86 | + }; | |
87 | + }; | |
88 | +}; | |
89 | + | |
90 | +function X_TextRange_getRawRange( tr ){ | |
91 | + var xnode = tr.xnode, | |
92 | + // | |
93 | + range = 10 <= X_UA[ 'IE' ] /* || X_UA[ 'iOS' ] */ ? document.createRange() : | |
94 | + 8 <= X_UA[ 'IE' ] ? X_elmBody.createTextRange() : X_TextRange_range, | |
95 | + elm, selection, isPoint, | |
96 | + texts, i, offset, j, l, x, y, rect; | |
97 | + | |
98 | + if( xnode[ '_flags' ] & X_NodeFlags_IN_TREE ){ | |
99 | + | |
100 | + X_Node_updateTimerID && X_Node_startUpdate(); | |
101 | + | |
102 | + elm = xnode[ '_rawObject' ]; | |
103 | + | |
104 | + switch( tr.createFrom ){ | |
105 | + case 'selection' : | |
106 | + if( X_TextRange_isW3C ){ | |
107 | + selection = window.getSelection(); | |
108 | + return selection.rangeCount && selection.getRangeAt( 0 ); | |
109 | + } else { | |
110 | + switch( document.selection.type ){ | |
111 | + case 'text' : | |
112 | + return document.selection.createRange(); | |
113 | + case 'Control' : | |
114 | + // TODO | |
115 | + case 'none' : | |
116 | + }; | |
117 | + }; | |
118 | + break; | |
119 | + | |
120 | + case 'point' : | |
121 | + isPoint = true; | |
122 | + case 'char' : | |
123 | + if( X_TextRange_isW3C ){ | |
124 | + // textarea で異なる | |
125 | + | |
126 | + if( isPoint ){ | |
127 | + // TextNode をフラットな配列に回収 | |
128 | + X_TextRange_collectTextNodes( elm, texts = [] ); | |
129 | + | |
130 | + for( i = offset = 0; text = texts[ i ]; ++i ){ | |
131 | + range.selectNodeContents( text ); // selectNodeContents は TextNode のみ?? Firefox | |
132 | + l = text.data.length; | |
133 | + | |
134 | + for( j = 0, x = tr.v1, y = tr.v2; j < l; ++j ) { | |
135 | + if( range ){ | |
136 | + range.setStart( text, j ); | |
137 | + range.setEnd( text, j + 1 ); | |
138 | + rect = range.getBoundingClientRect(); | |
139 | + }; | |
140 | + if( rect.left <= x && x <= rect.right && rect.top <= y && y <= rect.bottom ){ | |
141 | + return { | |
142 | + hitRange : range, | |
143 | + rect : rect, | |
144 | + offset : offset, | |
145 | + text : text | |
146 | + }; | |
147 | + }; | |
148 | + }; | |
149 | + offset += l; | |
150 | + }; | |
151 | + range = null; | |
152 | + } else { | |
153 | + // 未チェック! | |
154 | + range.setEnd( elm, l < tr.v2 ? l : tr.v2 ); | |
155 | + range.setStart( elm, tr.v1 ); | |
156 | + return { hitRange : range }; | |
157 | + }; | |
158 | + } else { | |
159 | + // !save && ( text = text.split( '\r\n' ).join( '\n' ) ); textarea用 | |
160 | + if( isPoint ){ | |
161 | + // ie11 の ie10モード で moveToPoint がないといわれる. よって isW3C:false で動作するのは ie9 以下 | |
162 | + range.moveToPoint( tr.v1, tr.v2 ); | |
163 | + if( !range.expand( 'character' ) ) range = null; | |
164 | + } else { | |
165 | + range.moveToElementText( elm ); | |
166 | + //range.collapse( true ); | |
167 | + range.moveEnd( 'character', l < tr.v2 ? l : tr.v2 ); | |
168 | + range.moveStart( 'character', tr.v1 ); | |
169 | + }; | |
170 | + }; | |
171 | + return range; | |
172 | + }; | |
173 | + }; | |
174 | +}; | |
175 | + | |
176 | +function X_TextRange_getRect(){ | |
177 | + var result = X_TextRange_getRawRange( this ), | |
178 | + rect, ret; | |
179 | + | |
180 | + if( result ){ | |
181 | + if( X_TextRange_isW3C ){ | |
182 | + rect = result.hitRange.getBoundingClientRect(); | |
183 | + ret = { | |
184 | + 'x' : rect.left, | |
185 | + 'y' : rect.top, | |
186 | + 'width' : rect.width, | |
187 | + 'height' : rect.height | |
188 | + }; | |
189 | + //range.detach && range.detach(); | |
190 | + } else { | |
191 | + ret = { | |
192 | + 'x' : result.boundingLeft, | |
193 | + 'y' : result.boundingTop, | |
194 | + 'width' : result.boundingWidth, | |
195 | + 'height' : result.boundingHeight // ie は right, bottom を持たない... | |
196 | + }; | |
197 | + }; | |
198 | + }; | |
199 | + return ret || { 'x' : 0, 'y' : 0, 'width' : 0, 'height' : 0 }; | |
200 | +}; | |
201 | + | |
202 | +// X.Text を探して flat な配列に格納する | |
203 | +function X_TextRange_collectXTexts( xnode, ary ){ | |
204 | + var kids = xnode[ '_xnodes' ], | |
205 | + i; | |
206 | + | |
207 | + if( !kids || !kids.length ) return; | |
208 | + | |
209 | + for( i = -1; xnode = kids[ ++i ]; ){ | |
210 | + if( xnode[ '_tag' ] ){ | |
211 | + X_TextRange_collectXTexts( xnode, ary ); | |
212 | + } else { | |
213 | + ary[ ary.length ] = xnode; | |
214 | + }; | |
215 | + }; | |
216 | +}; | |
217 | + | |
218 | +function X_TextRange_getOffset(){ | |
219 | + var result = X_TextRange_getRawRange( this ), | |
220 | + range, ret, all, from, xtexts, n, i, l, xtext; | |
221 | + | |
222 | + if( result ){ | |
223 | + if( X_TextRange_isW3C ){ | |
224 | + range = result.hitRange; | |
225 | + ret = { | |
226 | + 'offset' : result.offset, | |
227 | + 'from' : range.startOffset, | |
228 | + 'to' : range.endOffset, | |
229 | + 'text' : X_Node_getXNode( result.text ) | |
230 | + }; | |
231 | + // range.detach && range.detach(); | |
232 | + } else { | |
233 | + // http://www.studio-freesky.net/programming/javascript/3/ | |
234 | + range = X_TextRange_range2; | |
235 | + //var _rang = X_elmBody.createTextRange(); | |
236 | + | |
237 | + | |
238 | + //_rang.moveToElementText( this.xnode.getChildAt(1)[ '_rawObject' ] ); | |
239 | + range.moveToElementText( this.xnode[ '_rawObject' ] ); | |
240 | + range.setEndPoint( 'EndToStart', result ); //_rang )// | |
241 | + from = range.text.length;// - result.text.length; | |
242 | + | |
243 | + X_TextRange_collectXTexts( this.xnode, xtexts = [] ); | |
244 | + | |
245 | + if( xtexts.length ){ | |
246 | + // 改行が入ると正しく startIndex を取ることができない... | |
247 | + for( n = l = 0, i = -1; xtext = xtexts[ ++i ]; ){ | |
248 | + l = xtext[ '_text' ].length; | |
249 | + if( from < n + l ){ | |
250 | + break; | |
251 | + }; | |
252 | + n += l; | |
253 | + }; | |
254 | + | |
255 | + ret = { | |
256 | + 'offset' : n, | |
257 | + 'from' : from - n, | |
258 | + 'to' : from - n + result.text.length, | |
259 | + 'text' : xtext | |
260 | + }; | |
261 | + }; | |
262 | + }; | |
263 | + }; | |
264 | + | |
265 | + return ret || { 'from' : -1, 'to' : -1 }; | |
266 | +}; | |
267 | + | |
268 | +function X_TextRange_text( v ){ | |
269 | + if( v === undefined ){ | |
270 | + | |
271 | + } else { | |
272 | + | |
273 | + }; | |
274 | +}; | |
275 | + |
@@ -448,6 +448,7 @@ function XMLWrapper_val( queryString, type ){ | ||
448 | 448 | var l = xmlList.length, |
449 | 449 | i = 0, |
450 | 450 | j, child, _xmlList; |
451 | + | |
451 | 452 | for( ; i < l; ++i ){ |
452 | 453 | child = xmlList[ i ]; |
453 | 454 | //if( child.nodeType !== 1 ) continue; |
@@ -473,6 +474,7 @@ function XMLWrapper_val( queryString, type ){ | ||
473 | 474 | l = xmlList.length, |
474 | 475 | i = 0, |
475 | 476 | child; |
477 | + | |
476 | 478 | for( ; i < l; ++i ){ |
477 | 479 | child = xmlList[ i ]; |
478 | 480 | if( child.nodeType === 1 ){ |
@@ -280,7 +280,9 @@ if( X_Audio_constructor ){ | ||
280 | 280 | } else |
281 | 281 | if( this.playing ){ |
282 | 282 | end = X_Audio_getEndTime( this ) + this._shortPlayFixTime; |
283 | - //console.log( now + ' / ' + end ); | |
283 | + | |
284 | + console.log( now + ' / ' + end );// Firefox44.0.2 で音声の再生開始に難あり... | |
285 | + | |
284 | 286 | if( ( 0 + end <= 0 + now ) || // 0+ なぜか iem9 で必要,,, |
285 | 287 | ( now < this._lastCurrentTime && now < 2000 ) ){ |
286 | 288 | //( ( X_HTMLAudio_endedFixAOSP2 || X_HTMLAudio_endedFixAOSP4 ) && ( now < this._lastCurrentTime && now < 1000 ) ) ){ |
@@ -43,6 +43,7 @@ document.write( [ | ||
43 | 43 | 'js/02_dom/10_XNodeAnime.js', |
44 | 44 | 'js/02_dom/20_XNode.js', |
45 | 45 | 'js/02_dom/22_XTreeBuilder.js', |
46 | + 'js/02_dom/30_XTextRange.js', | |
46 | 47 | |
47 | 48 | 'js/03_plugin/00_XPlugin.js', |
48 | 49 |