リビジョン | ef25747bebf1799d49f9bd0d64e339da9ea61d13 (tree) |
---|---|
日時 | 2016-11-13 03:00:06 |
作者 | itozyun <itozyun@user...> |
コミッター | itozyun |
Version 0.6.221, Update the X.TextRange.
@@ -62,6 +62,24 @@ if( X_Script_VBS_ENABLED ){ | ||
62 | 62 | * */ |
63 | 63 | ].join( '\n' ) + '</script>' ); |
64 | 64 | |
65 | + // http://space.geocities.jp/nequomame/others/excelvba/excelvba_01_03.html | |
66 | + // Document.ActiveElement に安全に触れるか?確認 | |
67 | + // そういえば error は iframe 内で起きていた | |
68 | + // http://stackoverflow.com/questions/14378224/document-activeelement-in-iframe-shows-unspecified-error-in-ie-standards-mode | |
69 | + // document.activeElement in iframe shows unspecified error in IE standards mode | |
70 | + X_Script_gte15 || document.write( '<script type=text/vbscript>' + | |
71 | + [ | |
72 | + 'Function vbs_testAE()', | |
73 | + 'On Error Resume Next', | |
74 | + 'Set ae = Document.ActiveElement', | |
75 | + 'If Err.Number Then', | |
76 | + 'ae = 1', | |
77 | + 'End If', | |
78 | + 'Err.Clear', | |
79 | + 'vbs_testAE = ae', | |
80 | + 'End Function' | |
81 | + ].join( '\n' ) + '</script>' ); | |
82 | + | |
65 | 83 | // TODO Object のメンバを辿る vba |
66 | 84 | // byte Array を扱う vba |
67 | 85 | }; |
@@ -75,6 +93,8 @@ if( X_Script_VBS_ENABLED ){ | ||
75 | 93 | function X_Script_try( func, args ){ |
76 | 94 | if( !X_Script_gte15 ){ |
77 | 95 | //return func.apply( {}, args ); |
96 | + // window.onerror = return true を設定 | |
97 | + // vbs 側から呼び出し? | |
78 | 98 | return; |
79 | 99 | }; |
80 | 100 | return X_Script_gte15( func, args || [] ); |
@@ -1,8 +1,12 @@ | ||
1 | +/* | |
2 | +http://shimax.cocolog-nifty.com/search/2006/09/post_b296.html | |
3 | +ここで、「String.fromCharCode(13,10)」というのは、「\r\n」のことであり、Windowsの改行コードです。もちろん、「\r\n」でも良いのですが、半角円マークが出現すると、LinuxのブラウザKonquerorで正しく動作しないことがあるため、半角円マークを使わないようにしています(参照:Konquerorとエスケープ文字(JavaScript謎のエラーを解く))。 | |
4 | +*/ | |
1 | 5 | |
2 | 6 | // ------------------------------------------------------------------------- // |
3 | 7 | // ------------ local variables -------------------------------------------- // |
4 | 8 | // ------------------------------------------------------------------------- // |
5 | -var X_String_CRLF = String.fromCharCode( 13 ) + String.fromCharCode( 10 ), | |
9 | +var X_String_CRLF = String.fromCharCode( 13 ) + String.fromCharCode( 10 ), // String.fromCharCode( 13, 10 ) | |
6 | 10 | X_String_CHAR_REFS = {"¡":161,"¢":162,"£":163,"¤":164,"¥":165,"¦":166,"§":167,"¨":168,"©":169, |
7 | 11 | "ª":170,"«":171, |
8 | 12 | "¬":172,"­":173,"®":174,"¯":175,"°":176,"±":177,"²":178,"³":179,"´":180,"µ":181,"¶":182, |
@@ -733,7 +733,8 @@ function X_EventDispatcher_actualRemoveEvent( that, type, raw, list, skip ){ | ||
733 | 733 | |
734 | 734 | |
735 | 735 | // TODO ブラウザからの呼び出しの最後に登録された関数を呼び出す機能(例えば画面の更新) |
736 | -var X_EventDispatcher_CURRENT_EVENTS = []; | |
736 | +var X_EventDispatcher_CURRENT_EVENTS = []; | |
737 | +var X_EventDispatcher_ignoreActualEvent = ''; | |
737 | 738 | |
738 | 739 | // handleEvent を拡張可能にするために、クロージャに移動した |
739 | 740 | // Is this in regard to the Safari 1.x preventDefault bug on click/dblclick? |
@@ -741,8 +742,16 @@ var X_EventDispatcher_CURRENT_EVENTS = []; | ||
741 | 742 | var X_EventDispatcher_actualHandleEvent = |
742 | 743 | X_UA_EVENT.IE4 || X_UA_EVENT.IE ? // ie45678 EVENT_IE & EVENT_DOM0 for ie4 |
743 | 744 | (function(){ |
744 | - var e = event, ret, | |
745 | - ev = new X_DomEvent( e, this, this[ '_rawObject' ] ); | |
745 | + var e = event, | |
746 | + elm = this[ '_rawObject' ], | |
747 | + ev, ret; | |
748 | + | |
749 | + /* if( e.type === X_EventDispatcher_ignoreActualEvent ){ | |
750 | + e.cancelBubble = true; | |
751 | + return; | |
752 | + }; */ | |
753 | + | |
754 | + ev = new X_DomEvent( e, this, elm ); | |
746 | 755 | |
747 | 756 | X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length ] = ev; |
748 | 757 |
@@ -754,16 +763,21 @@ var X_EventDispatcher_actualHandleEvent = | ||
754 | 763 | e.cancelBubble = true; |
755 | 764 | }; |
756 | 765 | if( ret & X_CALLBACK_PREVENT_DEFAULT ){ |
757 | - this[ '_tag' ] === 'A' && this[ '_rawObject' ].blur(); | |
766 | + this[ '_tag' ] === 'A' && elm.blur(); | |
758 | 767 | return e.returnValue = false; |
759 | 768 | }; |
760 | 769 | }) : |
761 | 770 | //X_UA_EVENT.W3C || X_UA_EVENT.DOM0 |
762 | 771 | (function( e ){ |
763 | - var ev = new X_DomEvent( e, this ), | |
764 | - ret = X_CALLBACK_NONE, | |
765 | - i, l; | |
772 | + var ret = X_CALLBACK_NONE, | |
773 | + ev, i, l; | |
774 | + | |
775 | + /* if( e.type === X_EventDispatcher_ignoreActualEvent ){ | |
776 | + e.stopPropagation(); | |
777 | + return; | |
778 | + }; */ | |
766 | 779 | |
780 | + ev = new X_DomEvent( e, this ); | |
767 | 781 | X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length ] = ev; |
768 | 782 | |
769 | 783 | // touch event -> pointer |
@@ -49,10 +49,9 @@ X_ViewPort = X_Class_override( | ||
49 | 49 | //https://developer.mozilla.org/ja/docs/Web/JavaScript/A_re-introduction_to_JavaScript |
50 | 50 | //Firefox 1.5 の bfcache が無効になりますので、他に理由がない限り Firefox では unload リスナを登録するべきではないことに注意してください。 |
51 | 51 | X_ViewPort[ 'dispatch' ]( X_EVENT_UNLOAD ); |
52 | - //alert('unload'); | |
52 | + //alert('unload'); | |
53 | 53 | X_ViewPort_document[ 'kill' ](); |
54 | 54 | X_ViewPort[ 'kill' ](); |
55 | - | |
56 | 55 | //X_System[ 'dispatch' ]( X_EVENT_SHUT_DOWN ); |
57 | 56 | break; |
58 | 57 |
@@ -75,8 +74,11 @@ X_ViewPort = X_Class_override( | ||
75 | 74 | |
76 | 75 | case 'blur' : |
77 | 76 | case 'focusout' : |
78 | - // TODO ie5... | |
79 | - if( 5.5 < X_UA[ 'IE' ] && X_UA[ 'IE' ] < 9 ){ | |
77 | + if( ( 5.5 < X_UA[ 'IE' ] && X_UA[ 'IE' ] < 9 ) | |
78 | + || | |
79 | + // TODO ie5... activeElement に障るとエラーになるため VBS 経由で activeElement に触り安全確認する(未確認) | |
80 | + ( 5 <= X_UA[ 'IE' ] && X_UA[ 'IE' ] < 5.5 && !window[ 'vbs_testAE' ]() ) | |
81 | + ){ | |
80 | 82 | xnode = X_Node_getXNode( document.activeElement ); |
81 | 83 | if( xnode ){ |
82 | 84 | xnode[ 'listenOnce' ]( [ 'focus', 'blur' ], X_ViewPort_detectFocusForIE ); |
@@ -299,14 +299,14 @@ if( !X_UA[ 'IE' ] || 9 <= X_UA[ 'IE' ] ){ | ||
299 | 299 | if( this[ 'target' ] && !this[ 'target' ][ '_tag' ] ) this[ 'target' ] = this[ 'target' ].parent; // ie4 の fake Textnode がヒットしていないか? |
300 | 300 | this[ 'currentTarget' ] = xnode; // xnode |
301 | 301 | this[ 'relatedTarget' ] = X_Node_getXNode( e.formElement || e.toElement ); // xnode |
302 | - this[ 'relatedTarget' ] && console.dir( 'relatide...' ); | |
302 | + //this[ 'relatedTarget' ] && console.dir( 'relatide...' ); | |
303 | 303 | this[ 'eventPhase' ] = e.srcElement === element ? 2: 3; |
304 | 304 | |
305 | 305 | this[ 'keyCode' ] = e.keyCode; |
306 | 306 | this[ 'charCode' ] = e.keyCode; |
307 | 307 | this[ 'altKey' ] = e.altKey; |
308 | 308 | this[ 'ctrlKey' ] = e.ctrlKey; |
309 | - this[ 'shiftKey' ] = e.shiftKey; | |
309 | + this[ 'shiftKey' ] = e.shiftKey; | |
310 | 310 | |
311 | 311 | |
312 | 312 | switch( this[ 'type' ] ){ |
@@ -228,6 +228,10 @@ function X_Node_attr( nameOrObj /* v */ ){ | ||
228 | 228 | if( this[ '_newAttrs' ] && X_Object_inObject( nameOrObj, this[ '_newAttrs' ] ) ) return this[ '_newAttrs' ][ nameOrObj ]; |
229 | 229 | if( elm = X_UA_DOM.IE4 ? this[ '_rawObject' ] || X_Node__ie4getRawNode( this ) : this[ '_rawObject' ] ){ |
230 | 230 | if( !attrs ) attrs = this[ '_attrs' ] = {}; |
231 | + | |
232 | + if( this[ '_tag' ] === 'TEXTAREA' && nameOrObj === 'value' && X_UA[ 'IE' ] < 9 ){ | |
233 | + return attrs[ nameOrObj ] = X_Node_Attr_getValueForIE( elm ); | |
234 | + }; | |
231 | 235 | return attrs[ nameOrObj ] = elm[ nameOrObj ]; // getAttribute( nameOrObj )? |
232 | 236 | }; |
233 | 237 | }; |
@@ -236,6 +240,16 @@ function X_Node_attr( nameOrObj /* v */ ){ | ||
236 | 240 | return attrs && attrs[ X_Node_Attr_renameForTag[ nameOrObj ] || nameOrObj ]; |
237 | 241 | }; |
238 | 242 | }; |
243 | + | |
244 | + | |
245 | + // ie8- 用に改行文字が \n の場合、 \r\n に変換しておく <- fromawork 内に移動 | |
246 | + // http://qiita.com/hanoopy/items/71456afe32f207369d24 | |
247 | +function X_Node_Attr_getValueForIE( elm ){ | |
248 | + // console.log( elm[ nameOrObj ].length + ' -> ' + elm[ nameOrObj ].split( '\r' ).join( '' ).length ); | |
249 | + // IE は改行文字が /r/n になるがこれを /n に変換 | |
250 | + return elm.value.split( '\r' ).join( '' ); | |
251 | +}; | |
252 | + | |
239 | 253 | function X_Node_Attr_setAttr( that, attrs, newAttrs, name, v ){ |
240 | 254 | switch( name ){ |
241 | 255 | case 'ns' : |
@@ -1382,7 +1382,7 @@ function X_Node_reserveUpdate(){ | ||
1382 | 1382 | var X_Node_updateReservedByReleaseGPU = false; |
1383 | 1383 | |
1384 | 1384 | function X_Node_startUpdate( time ){ |
1385 | - var removal, i, xnodeOrElm, xnodesIEFilterFixAfter, xnode; | |
1385 | + var removal, i, xnodeOrElm, xnodesIEFilterFixAfter, xnode, active; | |
1386 | 1386 | |
1387 | 1387 | if( !X_Node_updateTimerID || X_ViewPort_readyState < X_EVENT_INIT ){ |
1388 | 1388 | return; |
@@ -1422,17 +1422,24 @@ function X_Node_startUpdate( time ){ | ||
1422 | 1422 | removal.length = 0; |
1423 | 1423 | }; |
1424 | 1424 | |
1425 | - // | |
1426 | - X_UA[ 'IE5' ] && ( X_elmBody.style.visibility = 'hidden' ); | |
1427 | - | |
1425 | + // 強制的に再描画を起こす, 但し activeElement からフォーカスが外れるため復帰する | |
1426 | + // IE5mode win10 で 確認 | |
1427 | + if( X_UA[ 'IE5' ] ){ | |
1428 | + active = document.activeElement; | |
1429 | + X_elmBody.style.visibility = 'hidden'; | |
1430 | + }; | |
1431 | + | |
1428 | 1432 | if( X_Node_html[ '_flags' ] & X_Node_BitMask_IS_DIRTY ){ |
1429 | 1433 | X_Node__commitUpdate( X_Node_html, X_Node_html[ '_rawObject' ].parentNode, null, X_Node_html[ '_flags' ], 1, xnodesIEFilterFixAfter = [] ); |
1430 | 1434 | } else { |
1431 | 1435 | X_Node__commitUpdate( X_Node_head, X_Node_head[ '_rawObject' ].parentNode, null, X_Node_head[ '_flags' ], 1, xnodesIEFilterFixAfter = [] ); |
1432 | 1436 | X_Node__commitUpdate( X_Node_body, X_Node_body[ '_rawObject' ].parentNode, null, X_Node_body[ '_flags' ], 1, xnodesIEFilterFixAfter = [] ); |
1433 | 1437 | }; |
1434 | - | |
1435 | - X_UA[ 'IE5' ] && ( X_elmBody.style.visibility = '' ); | |
1438 | + | |
1439 | + if( X_UA[ 'IE5' ] ){ | |
1440 | + X_elmBody.style.visibility = ''; | |
1441 | + active && active.parentNode && active.focus(); | |
1442 | + }; | |
1436 | 1443 | |
1437 | 1444 | if( X_Node_updateReservedByReleaseGPU ){ |
1438 | 1445 | X_Node_reserveUpdate(); |
@@ -1522,7 +1529,12 @@ var X_Node__commitUpdate = | ||
1522 | 1529 | if( !elm ){ |
1523 | 1530 | if( !that[ '_tag' ] ){ |
1524 | 1531 | that[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY; |
1525 | - elm = document.createTextNode( X_String_chrReferanceTo( that[ '_text' ] ) ); | |
1532 | + if( X_UA[ 'IE' ] < 8 ){ | |
1533 | + // \n -> \r\n に変換しないと pre タグで開業されない win10ie7(ie11 emu) で確認 | |
1534 | + elm = document.createTextNode( X_String_chrReferanceTo( that[ '_text' ] ).split( '\n' ).join( X_String_CRLF ) ); | |
1535 | + } else { | |
1536 | + elm = document.createTextNode( X_String_chrReferanceTo( that[ '_text' ] ) ); | |
1537 | + }; | |
1526 | 1538 | if( !X_UA[ 'IE' ] ){ |
1527 | 1539 | elm[ 'UID' ] = that[ '_uid' ]; |
1528 | 1540 | }; |
@@ -1798,7 +1810,12 @@ var X_Node__updateRawNode = | ||
1798 | 1810 | |
1799 | 1811 | // textNode |
1800 | 1812 | if( !that[ '_tag' ] ){ |
1801 | - elm.data = X_String_chrReferanceTo( that[ '_text' ] ); | |
1813 | + if( X_UA[ 'IE' ] < 8 ){ | |
1814 | + // \n -> \r\n に変換しないと pre タグで開業されない win10ie7(ie11 emu) で確認 | |
1815 | + elm.data = X_String_chrReferanceTo( that[ '_text' ] ).split( '\n' ).join( X_String_CRLF ); | |
1816 | + } else { | |
1817 | + elm.data = X_String_chrReferanceTo( that[ '_text' ] ); | |
1818 | + }; | |
1802 | 1819 | that[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY; |
1803 | 1820 | return; |
1804 | 1821 | }; |
@@ -2,13 +2,16 @@ | ||
2 | 2 | * tr = X.Doc.createRange('selection') |
3 | 3 | * X.Doc.createRange({from : num, to : num}) |
4 | 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 } | |
5 | + * ( 'selection' ) docment の slection のうち xnode の配下のもの, textarea, input, iframe[desineMode] の場合、選択範囲またはカーソル位置 | |
6 | + * ( 'select', from[, to] ) 選択する | |
7 | + * ( 'char', from[, to] ) | |
8 | + * ( 'lineAt', index ), | |
9 | + * ( 'line', x, y ), | ( 'line', pointerEvent ) | |
10 | + * ( 'point', x, y ) | ( 'point', pointerEvent ) | |
11 | + * tr.move( from, to ) | |
12 | + * tr.select( true | false ) | |
13 | + * tr.getRect() { width, height, x, y } -> tr.mesure() | |
14 | + * tr.getOffset() { from, to } | |
12 | 15 | * tr.text() |
13 | 16 | * |
14 | 17 | * naming は mozilla に寄せる |
@@ -27,6 +30,8 @@ var X_TextRange_range, | ||
27 | 30 | var X_TextRange = X_Class_create( |
28 | 31 | 'X.TextRange', |
29 | 32 | |
33 | + // TODO コールバックの最後に破棄されるクラス 1刻みの間存在するクラス. X.XML も | |
34 | + | |
30 | 35 | /** @lends X.TextRange.prototype */ |
31 | 36 | { |
32 | 37 | xnode : null, |
@@ -57,9 +62,15 @@ var X_TextRange = X_Class_create( | ||
57 | 62 | if( arg2 !== 'selection' ){ |
58 | 63 | this.v1 = arg3 || 0; |
59 | 64 | this.v2 = arg4 || 0; |
65 | + } else { | |
66 | + this[ 'getOffset' ](); | |
60 | 67 | }; |
61 | 68 | }, |
62 | 69 | |
70 | + 'move' : X_TextRange_move, | |
71 | + | |
72 | + 'select' : X_TextRange_select, | |
73 | + | |
63 | 74 | 'getRect' : X_TextRange_getRect, |
64 | 75 | |
65 | 76 | 'getOffset' : X_TextRange_getOffset, |
@@ -87,7 +98,7 @@ function X_TextRange_collectTextNodes( elm, ary ){ | ||
87 | 98 | }; |
88 | 99 | }; |
89 | 100 | |
90 | -function X_TextRange_getRawRange( tr ){ | |
101 | +function X_TextRange_getRawRange( tr, createFrom ){ | |
91 | 102 | var xnode = tr.xnode, |
92 | 103 | // |
93 | 104 | range = 10 <= X_UA[ 'IE' ] /* || X_UA[ 'iOS' ] */ ? document.createRange() : |
@@ -101,11 +112,20 @@ function X_TextRange_getRawRange( tr ){ | ||
101 | 112 | |
102 | 113 | elm = xnode[ '_rawObject' ]; |
103 | 114 | |
104 | - switch( tr.createFrom ){ | |
115 | + switch( createFrom || tr.createFrom ){ | |
105 | 116 | case 'selection' : |
106 | 117 | if( X_TextRange_isW3C ){ |
107 | 118 | selection = window.getSelection(); |
108 | - return selection.rangeCount && selection.getRangeAt( 0 ); | |
119 | + | |
120 | + if( selection.getRangeAt ){ | |
121 | + return selection.rangeCount && selection.getRangeAt( 0 ); | |
122 | + }; | |
123 | + // http://d.hatena.ne.jp/dayflower/20080423/1208941641 | |
124 | + // for Safari 1.3 | |
125 | + range = document.createRange(); | |
126 | + range.setStart( selection.anchorNode, selection.anchorOffset ); | |
127 | + range.setEnd( selection.focusNode, selection.focusOffset ); | |
128 | + return range; | |
109 | 129 | } else { |
110 | 130 | switch( document.selection.type ){ |
111 | 131 | case 'text' : |
@@ -139,10 +159,10 @@ function X_TextRange_getRawRange( tr ){ | ||
139 | 159 | }; |
140 | 160 | if( rect.left <= x && x <= rect.right && rect.top <= y && y <= rect.bottom ){ |
141 | 161 | return { |
142 | - hitRange : range, | |
143 | - rect : rect, | |
144 | - offset : offset, | |
145 | - text : text | |
162 | + 'hitRange' : range, | |
163 | + 'rect' : rect, | |
164 | + 'offset' : offset, | |
165 | + 'text' : text | |
146 | 166 | }; |
147 | 167 | }; |
148 | 168 | }; |
@@ -153,14 +173,14 @@ function X_TextRange_getRawRange( tr ){ | ||
153 | 173 | // 未チェック! |
154 | 174 | range.setEnd( elm, l < tr.v2 ? l : tr.v2 ); |
155 | 175 | range.setStart( elm, tr.v1 ); |
156 | - return { hitRange : range }; | |
176 | + return { 'hitRange' : range }; | |
157 | 177 | }; |
158 | 178 | } else { |
159 | 179 | // !save && ( text = text.split( '\r\n' ).join( '\n' ) ); textarea用 |
160 | 180 | if( isPoint ){ |
161 | 181 | // ie11 の ie10モード で moveToPoint がないといわれる. よって isW3C:false で動作するのは ie9 以下 |
162 | 182 | range.moveToPoint( tr.v1, tr.v2 ); |
163 | - if( !range.expand( 'character' ) ) range = null; | |
183 | + if( !range.duplicate().expand( 'character' ) ) range = null; | |
164 | 184 | } else { |
165 | 185 | range.moveToElementText( elm ); |
166 | 186 | //range.collapse( true ); |
@@ -179,14 +199,16 @@ function X_TextRange_getRect(){ | ||
179 | 199 | |
180 | 200 | if( result ){ |
181 | 201 | 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 | |
202 | + if( result.hitRange ){ | |
203 | + rect = result.hitRange.getBoundingClientRect(); | |
204 | + ret = { | |
205 | + 'x' : rect.left, | |
206 | + 'y' : rect.top, | |
207 | + 'width' : rect.width, | |
208 | + 'height' : rect.height | |
209 | + }; | |
210 | + //range.detach && range.detach(); | |
188 | 211 | }; |
189 | - //range.detach && range.detach(); | |
190 | 212 | } else { |
191 | 213 | ret = { |
192 | 214 | 'x' : result.boundingLeft, |
@@ -216,46 +238,68 @@ function X_TextRange_collectXTexts( xnode, ary ){ | ||
216 | 238 | }; |
217 | 239 | |
218 | 240 | function X_TextRange_getOffset(){ |
219 | - var result = X_TextRange_getRawRange( this ), | |
220 | - range, ret, all, from, xtexts, n, i, l, xtext; | |
241 | + var xnode = this.xnode, | |
242 | + elm, result, range, | |
243 | + ret, from, xtexts, n, i, l, xtext; | |
221 | 244 | |
222 | - if( result ){ | |
245 | + if( xnode[ '_tag' ] === 'TEXTAREA' ){ | |
246 | + elm = xnode[ '_rawObject' ]; | |
247 | + | |
248 | + if( elm && xnode[ '_flags' ] & X_NodeFlags_IN_TREE ){ | |
249 | + if( X_UA[ 'IE' ] < 9 ){ | |
250 | + | |
251 | + | |
252 | + return cursorPosition.call( this, elm ); | |
253 | + | |
254 | + } else if( elm.setSelectionRange ){ | |
255 | + if( X_UA[ 'IE' ] < 12 ){ | |
256 | + l = elm.value.length; | |
257 | + ret = { | |
258 | + 'from' : this.v1 = elm.selectionStart < l ? elm.selectionStart : l, | |
259 | + 'to' : this.v2 = elm.selectionEnd < l ? elm.selectionEnd : l | |
260 | + }; | |
261 | + } else { | |
262 | + ret = { | |
263 | + 'from' : this.v1 = elm.selectionStart, | |
264 | + 'to' : this.v2 = elm.selectionEnd | |
265 | + }; | |
266 | + }; | |
267 | + }; | |
268 | + }; | |
269 | + } else | |
270 | + if( result = X_TextRange_getRawRange( this ) ){ | |
223 | 271 | if( X_TextRange_isW3C ){ |
224 | 272 | range = result.hitRange; |
225 | 273 | ret = { |
226 | 274 | 'offset' : result.offset, |
227 | - 'from' : range.startOffset, | |
228 | - 'to' : range.endOffset, | |
275 | + 'from' : this.v1 = range.startOffset, | |
276 | + 'to' : this.v2 = range.endOffset, | |
229 | 277 | 'text' : X_Node_getXNode( result.text ) |
230 | 278 | }; |
231 | 279 | // range.detach && range.detach(); |
232 | 280 | } else { |
233 | 281 | // http://www.studio-freesky.net/programming/javascript/3/ |
234 | - range = X_TextRange_range2; | |
235 | - //var _rang = X_elmBody.createTextRange(); | |
236 | 282 | |
283 | + range = X_TextRange_range2; | |
284 | + range.moveToElementText( xnode[ '_rawObject' ] ); | |
285 | + range.setEndPoint( 'EndToStart', result ); | |
286 | + from = range.text.length; | |
237 | 287 | |
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 = [] ); | |
288 | + X_TextRange_collectXTexts( xnode, xtexts = [] ); | |
244 | 289 | |
245 | 290 | if( xtexts.length ){ |
246 | - // 改行が入ると正しく startIndex を取ることができない... | |
247 | - for( n = l = 0, i = -1; xtext = xtexts[ ++i ]; ){ | |
248 | - l = xtext[ '_text' ].length; | |
291 | + for( n = 0, i = -1; xtext = xtexts[ ++i ]; ){ | |
292 | + l = xtext[ '_rawObject' ].data.length; | |
249 | 293 | if( from < n + l ){ |
250 | 294 | break; |
251 | 295 | }; |
252 | 296 | n += l; |
253 | 297 | }; |
254 | - | |
298 | + | |
255 | 299 | ret = { |
256 | - 'offset' : n, | |
257 | - 'from' : from - n, | |
258 | - 'to' : from - n + result.text.length, | |
300 | + 'offset' : n, // elm の何個目の node か? | |
301 | + 'from' : this.v1 = from - n, | |
302 | + 'to' : this.v2 = from - n + result.text.length, | |
259 | 303 | 'text' : xtext |
260 | 304 | }; |
261 | 305 | }; |
@@ -266,10 +310,222 @@ function X_TextRange_getOffset(){ | ||
266 | 310 | }; |
267 | 311 | |
268 | 312 | function X_TextRange_text( v ){ |
313 | + var xnode = this.xnode, elm, val, offset, from, to; | |
314 | + | |
269 | 315 | if( v === undefined ){ |
270 | 316 | |
271 | 317 | } else { |
318 | + if( xnode[ '_tag' ] === 'TEXTAREA' ){ | |
319 | + elm = xnode[ '_rawObject' ]; | |
320 | + val = X_UA[ 'IE' ] < 9 ? X_Node_Attr_getValueForIE( elm ) : elm.value; | |
321 | + | |
322 | + if( this.createFrom === 'char' ){ | |
323 | + xnode.attr( { | |
324 | + 'value' : val.substr( 0, this.v1 ) + v + val.substr( this.v2 ) | |
325 | + } ); | |
326 | + } else { | |
327 | + offset = this[ 'getOffset' ](); | |
328 | + | |
329 | + from = offset[ 'from' ]; | |
330 | + to = offset[ 'to' ]; | |
331 | + | |
332 | + if( X_UA[ 'IE' ] < 9 ){ | |
333 | + range = document.selection.createRange(); | |
334 | + // TODO check textarea | |
335 | + range.text = v; | |
336 | + // ここには range.text がいない https://msdn.microsoft.com/ja-jp/library/cc427934.aspx | |
337 | + } else { | |
338 | + val = val.substr( 0, from ) + v + val.substr( to ); | |
339 | + elm.value = val; | |
340 | + }; | |
341 | + | |
342 | + if( to !== from ){ | |
343 | + // カーソル位置を挿入した文字列の最後へ | |
344 | + to = from + v.length; | |
345 | + } else { | |
346 | + // カーソル位置を挿入した文字列の後ろへ | |
347 | + to += v.length; | |
348 | + }; | |
349 | + this.move( to, to ); | |
350 | + }; | |
351 | + }; | |
352 | + }; | |
353 | +}; | |
354 | + | |
355 | +function X_TextRange_move( from, to ){ | |
356 | + var xnode = this.xnode, | |
357 | + elm = xnode[ '_rawObject' ], | |
358 | + len, range; | |
359 | + | |
360 | + if( 0 <= from ){ | |
361 | + this.v1 = from; | |
362 | + } else { | |
363 | + this.v1 = this.v1 + from; | |
364 | + this.v1 < 0 && ( this.v1 = 0 ); | |
365 | + }; | |
366 | + | |
367 | + if( X_Type_isNumber( to ) ){ | |
368 | + if( 0 <= to ){ | |
369 | + this.v2 = to; | |
370 | + } else { | |
371 | + this.v2 = this.v2 + to; | |
372 | + this.v2 < this.v1 && ( this.v2 = this.v1 ); | |
373 | + }; | |
374 | + }; | |
375 | + | |
376 | + if( xnode[ '_tag' ] === 'TEXTAREA' ){ | |
377 | + // http://blog.enjoyxstudy.com/entry/20060305/p1 | |
272 | 378 | |
379 | + if( X_UA[ 'IE' ] < 9 || X_UA[ 'Opera' ] ){ | |
380 | + len = ( X_UA[ 'IE' ] < 9 ? X_Node_Attr_getValueForIE( elm ) : elm.value ).length; | |
381 | + | |
382 | + if( X_UA[ 'Opera' ] ){ | |
383 | + X_EventDispatcher_ignoreActualEvent = 'focus'; | |
384 | + elm.focus(); // Operaの為(IEでは無くても大丈夫) | |
385 | + X_EventDispatcher_ignoreActualEvent = ''; | |
386 | + }; | |
387 | + | |
388 | + range = elm.createTextRange(); | |
389 | + | |
390 | + if( this.v1 === this.v2 && this.v1 === 0 ){ | |
391 | + range.collapse( true ); // 先頭に移動 | |
392 | + } else { | |
393 | + if( this.v1 !== this.v2 || this.v1 < len ){ | |
394 | + range.collapse(); // おまじない? | |
395 | + | |
396 | + if( this.v1 === this.v2 ){ | |
397 | + range.move( 'character', this.v1 ); | |
398 | + } else { | |
399 | + range.moveEnd( 'character', this.v2 ); | |
400 | + range.moveStart( 'character', this.v1 ); | |
401 | + }; | |
402 | + } else { | |
403 | + range.collapse( false ); // 末美に移動 | |
404 | + }; | |
405 | + }; | |
406 | + range.select(); | |
407 | + | |
408 | + } else if( elm.setSelectionRange ){ | |
409 | + elm.setSelectionRange( this.v1, this.v2 ); | |
410 | + }; | |
273 | 411 | }; |
274 | 412 | }; |
275 | 413 | |
414 | +function X_TextRange_select( v ){ | |
415 | + | |
416 | +}; | |
417 | + | |
418 | +// http://www.studio-freesky.net/programming/javascript/3/ | |
419 | +// それは、IEのTextRangeオブジェクトで取得した範囲にもしラストに改行コード¥r¥nがあった場合それが含まれないのです。(視覚的な選択範囲には含まれています) | |
420 | + | |
421 | +// https://web.archive.org/web/20090904134938/http://www.dedestruct.com/2008/03/22/howto-cross-browser-cursor-position-in-textareas/ | |
422 | + // https://web.archive.org/web/20090904183807/http://www.dedestruct.com/cursorPosition.html | |
423 | + function cursorPosition( textarea ){ | |
424 | + | |
425 | + var selection_range = document.selection.createRange().duplicate(); | |
426 | + | |
427 | + | |
428 | + if (selection_range.parentElement() !== textarea) { | |
429 | + // TODO 正しくはカーソル位置・選択範囲の復帰 | |
430 | + | |
431 | + X_EventDispatcher_ignoreActualEvent = 'focus'; | |
432 | + textarea.focus(); | |
433 | + X_EventDispatcher_ignoreActualEvent = ''; | |
434 | + | |
435 | + // BODY要素のテキスト範囲を作成する | |
436 | + selection_range = X_elmBody.createTextRange(); | |
437 | + | |
438 | + // BODY要素のテキスト範囲をeのテキスト範囲に移動する | |
439 | + // これはe.createTextRange()とほぼ同等 | |
440 | + selection_range.moveToElementText( textarea ); | |
441 | + | |
442 | + selection_range.collapse( true ); // 末美に移動 | |
443 | + selection_range.select(); | |
444 | + }; | |
445 | + | |
446 | + //if (selection_range.parentElement() == textarea) {// Check that the selection is actually in our textarea | |
447 | + // Create three ranges, one containing all the text before the selection, | |
448 | + // one containing all the text in the selection (this already exists), and one containing all | |
449 | + // the text after the selection. | |
450 | + var before_range = X_elmBody.createTextRange(); | |
451 | + before_range.moveToElementText(textarea); | |
452 | + // Selects all the text | |
453 | + before_range.setEndPoint('EndToStart', selection_range); | |
454 | + // Moves the end where we need it | |
455 | + | |
456 | + var after_range = X_elmBody.createTextRange(); | |
457 | + after_range.moveToElementText(textarea); | |
458 | + // Selects all the text | |
459 | + after_range.setEndPoint('StartToEnd', selection_range); | |
460 | + // Moves the start where we need it | |
461 | + | |
462 | + var before_finished = false, selection_finished = false, after_finished = false; | |
463 | + var before_text, untrimmed_before_text, selection_text, untrimmed_selection_text, after_text, untrimmed_after_text; | |
464 | + | |
465 | + // Load the text values we need to compare | |
466 | + before_text = untrimmed_before_text = before_range.text; | |
467 | + selection_text = untrimmed_selection_text = selection_range.text; | |
468 | + after_text = untrimmed_after_text = after_range.text; | |
469 | + | |
470 | + // Check each range for trimmed newlines by shrinking the range by 1 character and seeing | |
471 | + // if the text property has changed. If it has not changed then we know that IE has trimmed | |
472 | + // a \r\n from the end. | |
473 | + do { | |
474 | + if (!before_finished) { | |
475 | + if (before_range.compareEndPoints('StartToEnd', before_range) == 0) { | |
476 | + before_finished = true; | |
477 | + } else { | |
478 | + before_range.moveEnd('character', -1); | |
479 | + if (before_range.text == before_text) { | |
480 | + untrimmed_before_text += '\r\n'; | |
481 | + } else { | |
482 | + before_finished = true; | |
483 | + } | |
484 | + } | |
485 | + } | |
486 | + if (!selection_finished) { | |
487 | + if (selection_range.compareEndPoints('StartToEnd', selection_range) == 0) { | |
488 | + selection_finished = true; | |
489 | + } else { | |
490 | + selection_range.moveEnd('character', -1); | |
491 | + if (selection_range.text == selection_text) { | |
492 | + untrimmed_selection_text += '\r\n'; | |
493 | + } else { | |
494 | + selection_finished = true; | |
495 | + } | |
496 | + } | |
497 | + } | |
498 | + if (!after_finished) { | |
499 | + if (after_range.compareEndPoints('StartToEnd', after_range) == 0) { | |
500 | + after_finished = true; | |
501 | + } else { | |
502 | + after_range.moveEnd('character', -1); | |
503 | + if (after_range.text == after_text) { | |
504 | + untrimmed_after_text += '\r\n'; | |
505 | + } else { | |
506 | + after_finished = true; | |
507 | + } | |
508 | + } | |
509 | + } | |
510 | + | |
511 | + } while ((!before_finished || !selection_finished || !after_finished)); | |
512 | + | |
513 | + // Untrimmed success test to make sure our results match what is actually in the textarea | |
514 | + // This can be removed once you're confident it's working correctly | |
515 | + /* | |
516 | + var untrimmed_text = untrimmed_before_text + untrimmed_selection_text + untrimmed_after_text; | |
517 | + var untrimmed_successful = false; | |
518 | + if (textarea.value == untrimmed_text) { | |
519 | + untrimmed_successful = true; | |
520 | + } */ | |
521 | + // ** END Untrimmed success test | |
522 | + | |
523 | + var startPoint = untrimmed_before_text.split( '\r' ).join( '' ).length; | |
524 | + // alert(startPoint); | |
525 | + return { | |
526 | + 'from' : this.v1 = startPoint, | |
527 | + 'to' : this.v2 = startPoint + untrimmed_selection_text.split( '\r' ).join( '' ).length | |
528 | + }; | |
529 | + //} | |
530 | + } | |
531 | + |
@@ -45,8 +45,6 @@ var X_NinjaIframe = X[ 'Util' ][ 'NinjaIframe' ] = Node[ 'inherits' ]( | ||
45 | 45 | this._name = 'hidden-iframe-' + X_Timer_now(); |
46 | 46 | // https://github.com/polygonplanet/Pot.js/blob/master/src/Worker.js |
47 | 47 | |
48 | - X_Node_newByTag = true; | |
49 | - | |
50 | 48 | this[ 'Super' ]( |
51 | 49 | 'IFRAME', |
52 | 50 | { |
@@ -211,7 +211,7 @@ if( X_XHR_w3c || X_XHR_msXML ){ | ||
211 | 211 | break; |
212 | 212 | case 'json' : // firefox9- は moz-json |
213 | 213 | raw.responseType = X_UA[ 'Gecko' ] < 10 ? 'moz-json' : X_UA[ 'Gecko' ] ? dataType : ''; // Iron 37 でエラー |
214 | - //X_XHR._dataType = 'json'; | |
214 | + X_XHR._dataType = 'json'; | |
215 | 215 | break; |
216 | 216 | case 'document' : |
217 | 217 | case 'xml' : |