読者です 読者をやめる 読者になる 読者になる

謎言語使いの徒然

適当に気になった技術や言語を流すブログ。

JavaScript(CoffeeScript) で似非 Ctrl + F 作ってみた。

CoffeeScript 日記 勉強

まじかと思ったんだけど、マジだったので驚いてる。

shertan.me

ちょっと待て基本だろ常考
こんなもん、Windows XP 初期の時代からデフォルトだぜ?

Keyboard Shortcuts for Internet Explorer 6

記憶が確かなら、Windows 98 時代からあった気もする。

まぁ、言ってもしょうがない。
仕方ないので、それっぽいものを作ってみた。

github.com

f:id:white-azalea:20151025153314p:plain

いつも通り、Play2.4 なので、Java8 入ってれば動くはず。

説明

つってもそんなに長くはならない。
当たり前だけど jQuery 1.11.x 系入れといて。

まずは、sandbox.js のハイライトでもって、検索を着色。

    searchArea = $('[data-app="inpage-search"]')

    template = () ->
        # 検索フォームテンプレート
        label = """<label for="__inpage_search_text">Search</label>"""
        inputTag = """<input id="__inpage_search_text" type="text" placeholder="text input here" />"""
        $("""#{label}#{inputTag}""")

    highlight = (tgt) ->
        # 実際のハイライト実行
        text = $(tgt.currentTarget).val()
        higlight =
          element: 'em'
          className: 'important'
        target = $('[data-role="inpage-search-target"]')
        target.unhighlight(higlight)
        target.highlight(text, higlight)

    changeText = (tgt) ->
        # テキストが更新される度にハイライト
        highlight(tgt)

    # disply and set event
    searchArea.append(template())
    $("#__inpage_search_text").keyup(changeText)

そして検索ボックスどうしようかと悩んだ。
検索フォームがコンテンツの外にあるわけではないので、フォーカスを使用する検索は不可能だ。

なので、ここでは着色と、スクロールで擬似的にフォーカスしようと考える。
すると、状態制御もあるので、class 無いとキッツイ…。という事でクラス化して作る。

    class FocusMover
        constructor: (@importants) ->
            # 埋め込み対象コンテナとか、検索対象サーチボタンとか
            @container = $("#__inpage_search_results")
            @currentIndex = 0
            @left = $("""<a href="#">&laquo;</a>""")
            @right = $("""<a href="#">&raquo;</a>""")
            @view()

        leftClick: () =>
            @currentIndex = @currentIndex - 1 if @currentIndex > 0
            @view()

        rightClick: () =>
            @currentIndex = @currentIndex + 1 if @currentIndex < (@importants.length - 1)
            @view()

        setFocus: (index) =>
            # 似非フォーカス。
            # 現在参照中のやつに、active のクラスを与えて
            @importants.removeClass("active")
            target = $(@importants[index])
            target.addClass("active")

            # 画面をスクロールする
            position = target.offset().top - 60 # ※ 数字は適当
            $('html,body').animate({ scrollTop: position }, 'fast');

        view: () =>
            # 表示制御。
            # 今何番目にフォーカスしてるか
            currentFocus = () =>
                showIndex = @currentIndex + 1
                allCount = @importants.length
                if allCount > 0
                    $("""<span>#{showIndex}/#{allCount}</span>""")

            # 似非フォーカス設定
            @setFocus(@currentIndex)

            # 「何番目を表示してる?」とか「次へ・前へ」リンクとか
            @container.empty()
            @container.append(currentFocus())
            @container.append(@left.click(@leftClick))
            @container.append(@right.click(@rightClick))

そしたら、それをハイライト表示のところに埋め込む

    highlight = (tgt) ->
        text = $(tgt.currentTarget).val()
        higlight =
          element: 'em'
          className: 'important'
        $(".important").removeClass('active') # ハイライトを消すついでに、active も消す
        target = $('[data-role="inpage-search-target"]')
        target.unhighlight(higlight)
        target.highlight(text, higlight)

    selects = () ->
        # 連続検索をするためのコンポーネントを追加。
        importants = $(".important")
        $("#__inpage_search_results").remove()
        selectMenu = """<span id="__inpage_search_results"></span>"""
        $('#__inpage_search_text').after(selectMenu)
        new FocusMover(importants)

    changeText = (tgt) ->
        highlight(tgt)
        selects() # ハイライトした後、選択ボックス関連を設定

てなことで、連続的な検索を作成した。