CLJSでClosure LibraryのLinkDialogPluginの挙動を変更する
何がしたかったか
Web address として : を含まない文字列を入力した時に http:// が補完されてしまう挙動を変えたい人生だった
c.f.
元々のやりかたでは自動的に追加されたものをあとから変更していたので、例えば http:// が自動的に追加されたものなのか、ユーザーが明示的に入力したものなのかの区別が付けられなかった
よって自動的に追加する処理自体を無かったことにする
新やったこと
LinkDialog を継承して、 入力されたURLに : がなかった場合の補完処理を削除する
LinkDialogPlugin を継承して、変更を加えた新しい LinkDialog を使うよう修正する
code:foo/plugin/linkdialog.cljs
(ns foo.plugin.linkdialog
(:import goog.editor.Link
goog.editor.plugins.LinkDialogPlugin
goog.ui.editor.LinkDialog))
;; LinkDialog
(this-as this (.call LinkDialog this dom-helper link)))
(goog/inherits WrappedLinkDialog LinkDialog)
(set! (.. WrappedLinkDialog -prototype -createOkEventFromWebTab_)
(fn []
(this-as this
;; URL に ":" がなくても "http://" を自動的に追加しないようにする (let [input (dom/getElement goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT)
url (.-value input)]
(if (Link.isLikelyEmailAddress url)
;; HACK: goog.base を使って継承元の関数を呼び出そうとすると
;; GCLの最適化の影響で First argument must be 'this' エラーになってしまうため .call をつかって呼び出す
(.call (.. LinkDialog -prototype -createOkEventFromEmailTab_)
this goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT)
(.call (.. LinkDialog -prototype -createOkEventFromUrl_)
this url))))))
;; LinkDialogPlugin
(defn WrappedLinkDialogPlugin []
(this-as this (.call LinkDialogPlugin this)))
(goog/inherits WrappedLinkDialogPlugin LinkDialogPlugin)
(set! (.. WrappedLinkDialogPlugin -prototype -getTrogClassId)
(fn [] "MyWrappedLinkDialog"))
(set! (.. WrappedLinkDialogPlugin -prototype -createDialog)
(this-as this
;; ダイアログとして上記の WrappedLinkDialog を使うよう変更
(when (.-emailWarning_ this)
(.setEmailWarning dialog (.-emailWarning_ this)))
(when (.-showOpenLinkInNewWindow_ this)
(.showOpenLinkInNewWindow dialog (.-isOpenLinkInNewWindowChecked_ this)))
(when (.-showRelNoFollow_ this)
(.showRelNoFollow dialog))
(.setStopReferrerLeaks dialog (.-stopReferrerLeaks_ this))
(doto (.-eventHandler_ this)
(.listen dialog goog.ui.editor.AbstractDialog.EventType.OK (.-handleOk this))
(.listen dialog goog.ui.editor.AbstractDialog.EventType.CANCEL (.-handleCancel_ this))
(.listen dialog goog.ui.editor.LinkDialog.EventType.BEFORE_TEST_LINK (.-handleBeforeTestLink this)))
dialog))))
旧やったこと
LinkDialogPlugin を継承した新しいプラグインを用意して、ダイアログ内の Ok ボタンを押された時のイベントをフックする
c.f.
ここで anchor タグにリンクテキストとURLを設定しているので、これより前にURLを書き換えてしまえばよい
code:foo/plugin/linkdialog.cljs
(ns foo.plugin.linkdialog
(:import goog.editor.plugins.LinkDialogPlugin))
;; LinkDialogPlugin を継承
(defn MyLinkDialogPlugin []
(this-as this (.call LinkDialogPlugin this)))
(goog/inherits MyLinkDialogPlugin LinkDialogPlugin)
;; 元々のIDと被らないように独自IDを付与
(set! (.. MyLinkDialogPlugin -prototype -getTrogClassId)
(fn [] "MyWrappedLinkDialog"))
;; 独自のhandleOk を定義
(set! (.. MyLinkDialogPlugin -prototype -handleOk)
(this-as this
;; e.linkUrl に最終的なURLが入っているので好きなように編集する
(set! (.-linkUrl e) url)
;; 元々のhandleOk関数に処理をお任せする
(.base MyLinkDialogPlugin this "handleOk" e)))))