Changeset 18317

Show
Ignore:
Timestamp:
08/27/08 19:50:30 (4 months ago)
Author:
anekos
Message:

問題なくなったっぽい?
・フレームに対応
・MF.storageのバグ修正

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • lang/javascript/vimperator-plugins/trunk/migemized_find.js

    r18093 r18317  
    33// @description-ja デフォルトのドキュメント内検索をミゲマイズする。 
    44// @license        Creative Commons 2.1 (Attribution + Share Alike) 
    5 // @version        1.0 
     5// @version        1.2 
    66// ==/VimperatorPlugin== 
    77// 
     
    3232  } 
    3333 
    34   let delayCallTimer = null; 
     34  function slashArray (ary, center) { 
     35    let head = [], tail = []; 
     36    let current = head; 
     37    for (let i = 0; i < ary.length; i++) { 
     38      let it = ary[i]; 
     39      if (it == center) 
     40        current = tail; 
     41      else 
     42        current.push(it); 
     43    } 
     44    return [head, tail]; 
     45  } 
    3546 
    3647  let MF = { 
    37     lastSearchText: null, 
    38     previousSearchText: null, 
    39     lastDirection: null, 
    40  
    41     get buffer function () liberator.buffer, 
    42  
    43     get document function () content.document, 
    44  
    45     get storage function () (this.buffer.__migemized_find_storage || (this.buffer.__migemized_find_storage = {})), 
    46  
    47     get defaultRange function () { 
    48       let range = this.document.createRange(); 
    49       range.selectNodeContents(this.document.body); 
    50       return range; 
    51     }, 
    52  
    53     get highlightRemover function () (this.storage.highlightRemover || function () void(0)), 
    54     set highlightRemover function (fun) (this.storage.highlightRemover = fun), 
    55  
     48    // 定数 
    5649    MODE_NORMAL: 0, 
    5750    MODE_REGEXP: 1, 
    5851    MODE_MIGEMO: 2, 
     52 
     53    lastSearchText: null, 
     54    lastSearchExpr: null, 
     55    previousSearchText: null, 
     56    lastDirection: null, 
     57 
     58    get buffer function () liberator.buffer, 
     59 
     60    get document function () content.document, 
     61 
     62    // タブ毎に状態を保存するために、変数を用意 
     63    get storage function () (gBrowser.mCurrentTab.__migemized_find_storage || (gBrowser.mCurrentTab.__migemized_find_storage = {})), 
     64 
     65    makeBodyRange: function (frame) { 
     66      let range = frame.document.createRange(); 
     67      range.selectNodeContents(frame.document.body); 
     68      return range; 
     69    }, 
     70 
     71    get highlightRemover function () (this.storage.highlightRemover || function () void(0)), 
     72    set highlightRemover function (fun) (this.storage.highlightRemover = fun), 
    5973 
    6074    // 検索文字列から検索モードと検索文字列を得る。 
     
    7589    }, 
    7690 
    77     highlightRange: function (range, setRemover) { 
     91    highlight: function (target, setRemover) { 
    7892      let span = this.document.createElement('span'); 
    7993      let spanStyle = 'background-color: lightblue; color: black; border: dotted 3px blue;'; 
    8094 
    8195      span.setAttribute('style', spanStyle); 
    82       range.surroundContents(span); 
     96      target.range.surroundContents(span); 
    8397 
    8498      let scroll = function () { 
    8599        let pos = getPosition(span); 
    86         content.scroll(pos.x - (content.innerWidth / 2), 
    87                        pos.y - (content.innerHeight / 2)); 
     100        target.frame.scroll(pos.x - (target.frame.innerWidth / 2), 
     101                            pos.y - (target.frame.innerHeight / 2)); 
    88102      }; 
    89103      setTimeout(scroll, 0); 
     
    106120 
    107121    find: function (str, backwards, range, start, end) { 
    108         if (!range) 
    109           range = this.defaultRange; 
    110  
    111         if (!start) { 
    112           start = range.startContainer.ownerDocument.createRange(); 
    113           start.setStartBefore(range.startContainer); 
     122      if (!range) 
     123        range = this.makeBodyRange(this.currentFrames[0]); 
     124 
     125      if (!start) { 
     126        start = range.startContainer.ownerDocument.createRange(); 
     127        start.setStartBefore(range.startContainer); 
     128      } 
     129      if (!end) { 
     130        end = range.endContainer.ownerDocument.createRange(); 
     131        end.setEndAfter(range.endContainer); 
     132      } 
     133 
     134      // 検索方向に合わせて、開始終了位置を交換 
     135      if (backwards) 
     136        [start, end] = [end, start]; 
     137 
     138      try { 
     139        return XMigemoCore.regExpFind(str, 'i', range, start, end, backwards); 
     140      } catch (e) { 
     141        return false; 
     142      } 
     143    }, 
     144 
     145    findFirst: function (str, backwards) { 
     146      this.lastDirection = backwards; 
     147      this.lastSearchText = str; 
     148      this.lastSearchExpr = str = this.searchTextToRegExpString(str); 
     149 
     150      let result, frames = this.currentFrames; 
     151      if (backwards) 
     152        frames = frames.reverse(); 
     153 
     154      for each (let frame in frames) { 
     155        let ret = this.find(str, backwards, this.makeBodyRange(frame)); 
     156        if (ret) { 
     157          result = this.storage.lastResult = { 
     158            frame: frame, 
     159            range: ret, 
     160          }; 
     161          break; 
    114162        } 
    115         if (!end) { 
    116           end = range.endContainer.ownerDocument.createRange(); 
    117           end.setEndAfter(range.endContainer); 
     163      } 
     164 
     165      this.removeHighlight(); 
     166      if (result) 
     167        this.highlight(result, true); 
     168 
     169      return result; 
     170    }, 
     171 
     172    findAgain: function (reverse) { 
     173      let backwards = !!(!this.lastDirection ^ !reverse); 
     174      let last = this.storage.lastResult; 
     175      let currentFrames = this.currentFrames; 
     176 
     177      // 前回の結果がないので、(初め|最後)のフレームを対象にする 
     178      // findFirst と"似た"挙動になる 
     179      if (!last) { 
     180        let idx = backwards ? frames.length - 1  
     181                            : 0; 
     182        last = {frame: frames[idx], range: this.makeBodyRange(frames[idx])}; 
     183      } 
     184 
     185      this.removeHighlight(); 
     186 
     187      let str = this.lastSearchExpr; 
     188      let start, end; 
     189 
     190      if (backwards) { 
     191        end = last.range.cloneRange(); 
     192        end.setEnd(last.range.startContainer, last.range.startOffset); 
     193      } else { 
     194        start = last.range.cloneRange(); 
     195        start.setStart(last.range.endContainer, last.range.endOffset); 
     196      } 
     197 
     198      let result; 
     199      let ret = this.find(str, backwards, this.makeBodyRange(last.frame), start, end); 
     200 
     201      if (ret) { 
     202        result = {frame: last.frame, range: ret}; 
     203      } else { 
     204        // 見つからなかったので、ほかのフレームから検索 
     205        let [head, tail] = slashArray(currentFrames, last.frame); 
     206        let next = backwards ? head.reverse().concat(tail.reverse()) 
     207                             : tail.concat(head); 
     208        for each (let frame in next) { 
     209          let r = this.find(str, backwards, this.makeBodyRange(frame)); 
     210          if (r) { 
     211            result = {frame: frame, range: r}; 
     212            break; 
     213          } 
    118214        } 
    119  
    120         if (backwards) 
    121           [start, end] = [end, start]; 
    122  
    123         try { 
    124           return XMigemoCore.regExpFind(str, 'i', range, start, end, backwards); 
    125         } catch (e) { 
    126           return false; 
    127         } 
    128     }, 
    129  
    130     findFirst: function (str, backwards) { 
    131       let f = function () { 
    132         this.lastDirection = backwards; 
    133         this.lastSearchText = str = this.searchTextToRegExpString(str); 
    134  
    135         let result = this.storage.lastResult = this.find(str, backwards); 
    136  
    137         this.removeHighlight(); 
    138         if (result) 
    139           this.highlightRange(result, true); 
    140  
    141         return result; 
    142       }; 
    143  
     215      } 
     216 
     217      this.storage.lastResult = result; 
     218 
     219      if (result) 
     220        this.highlight(result, true); 
     221 
     222      return result; 
     223    }, 
     224 
     225    submit: function () { 
     226      this.previousSearchText = this.lastSearchText; 
     227    }, 
     228 
     229    cancel: function () { 
     230      this.lastSearchText = MF.previousSearchText; 
     231    }, 
     232 
     233    get currentFrames function () { 
     234      let result = []; 
     235      (function (frame) { 
     236        // ボディがない物は検索対象外なので外す 
     237        if (frame.document.body.localName.toLowerCase() == 'body') 
     238          result.push(frame); 
     239        for (let i = 0; i < frame.frames.length; i++) 
     240          arguments.callee(frame.frames[i]); 
     241      })(content); 
     242      return result; 
     243    }, 
     244  }; 
     245 
     246 
     247  // 前のタイマーを削除するために保存しておく 
     248  let delayCallTimer = null; 
     249 
     250  let migemized = { 
     251    find: function find (str, backwards) { 
     252      // 短時間に何回も検索をしないように遅延させる 
     253      let f = function () MF.findFirst(str, backwards); 
    144254      if (delayCallTimer) 
    145255        clearTimeout(delayCallTimer); 
    146  
    147       delayCallTimer = setTimeout(function () f.call(MF), 300); 
    148     }, 
    149  
    150     findAgain: function (reverse) { 
    151       this.removeHighlight(); 
    152  
    153       let str = this.lastSearchText; 
    154       let range = this.defaultRange; 
    155       let last = this.storage.lastResult; 
    156       let backwards = !!(!this.lastDirection ^ !reverse); 
    157       let start, end; 
    158  
    159       if (last) { 
    160         if (backwards) { 
    161           end = last.cloneRange(); 
    162           end.setEnd(last.startContainer, last.startOffset); 
    163         } else { 
    164           start = last.cloneRange(); 
    165           start.setStart(last.endContainer, last.endOffset); 
    166         } 
    167       } 
    168  
    169       let result = this.storage.lastResult = this.find(str, backwards, range, start, end); 
    170       if (!result) 
    171         result = this.storage.lastResult = this.find(str, backwards, range); 
    172  
    173       if (result) 
    174         this.highlightRange(result, true); 
    175       else 
    176         liberator.echoerr('not found: ' + str); 
    177  
    178       return result; 
    179     }, 
    180   }; 
    181  
    182   let original = {}; 
    183  
    184   let migemized = { 
    185     find: function find (str, backwards) { 
    186       MF.findFirst(str, backwards); 
     256      delayCallTimer = setTimeout(function () f(), 300); 
    187257    }, 
    188258 
    189259    findAgain: function findAgain (reverse) { 
    190260      MF.findAgain(reverse); 
    191     }, 
    192  
    193     searchSubmitted: function searchSubmitted (command, forcedBackward) { 
    194261      if (!MF.storage.lastResult) 
    195262        liberator.echoerr('not found: ' + MF.lastSearchText); 
    196       MF.previousSearchText = MF.lastSearchText; 
     263    }, 
     264 
     265    searchSubmitted: function searchSubmitted (command, forcedBackward) { 
     266      MF.submit(); 
     267      if (!MF.storage.lastResult) 
     268        liberator.echoerr('not found: ' + MF.lastSearchText); 
    197269    }, 
    198270 
    199271    searchCanceled: function searchCanceled () { 
    200       MF.lastSearchText = MF.previousSearchText; 
     272      MF.cancel(); 
    201273    }, 
    202274  }; 
    203275 
    204   for (let name in migemized) 
    205     original[name] = liberator.search[name]; 
    206  
    207   function set (funcs) { 
    208     for (let name in funcs) 
    209       liberator.search[name] = funcs[name]; 
     276 
     277  // オリジナルの状態に戻せるように保存しておく 
     278  { 
     279    let original = {}; 
     280 
     281    for (let name in migemized) 
     282      original[name] = liberator.search[name]; 
     283 
     284    function set (funcs) { 
     285      for (let name in funcs) 
     286        liberator.search[name] = funcs[name]; 
     287    } 
     288 
     289    set(migemized); 
     290 
     291    MF.install = function () set(migemized); 
     292    MF.uninstall = function () set(original); 
    210293  } 
    211294 
    212   set(migemized); 
    213  
    214   liberator.plugins.migemizedFind = { 
    215     install: function () set(migemized), 
    216     uninstall: function () set(original), 
    217   }; 
     295 
     296  // 外から使えるように 
     297  liberator.plugins.migemizedFind = MF; 
    218298 
    219299}catch(e){liberator.log(e);}})();