2016年11月3日木曜日

Blogger でリアルタイム プレビュー

イメージ

Blogger で記事を書いているとき、プレビューを表示して記事の体裁を確認することがあると思います。一度の確認であれば「プレビュー」ボタンをクリックするだけなので大した手間もかかりません。しかし、何度も確認をする場合は、ボタンのクリックや「投稿」ページとプレビューを行き来するためのタブの切り替えが煩わしくなってきます。

そこで、この煩わしさから解放されるべく、リアルタイム プレビューと呼ばれる機能をブックマークレットで作ってみました。

このブックマークレットを使うと、「投稿」ページと同じ画面内にプレビューが表示されるようになり、「プレビュー」ボタンをクリックすることなく自動的にプレビューが更新されるようになるため、記事の体裁を即座に確認することができるようになります。

デモ

動作確認ブラウザ

  • Chrome 54 (Windows 10)

ブックマークレットの登録

以下のリンクをブラウザーのブックマーク バーまでドラッグして、ブックマークレットとして登録します。

リアルタイム プレビュー

使い方

「投稿」ページを開きます。

「投稿」ページ

先ほど登録したブックマークレットをクリックします。

ブックマークレットをクリック

すると、画面が以下のように分割されて表示されます。

分割された画面

左側に表示されるのが「投稿」ページで右側がプレビューです。画面の真ん中にある灰色のバーを動かすと、それぞれの表示領域のサイズを変更できます。

あとは普段と同じように、記事を書いていくだけです。

記事を書いていく

文字を書き込むたびに自動的にプレビューが更新されます。

プレビューが更新される

画面の分割を解除するには、記事を保存してからブラウザーの「更新」ボタンをクリックしてください。「投稿」ページ内のボタンやリンクをクリックして別のページに移動しても、分割は解除されません。

ソース コード (圧縮前)

このブックマークレットは MIT ライセンスで公開しています。

/**
 * Copyright (c) 2016 Toshiya Asai.
 *
 * License: The MIT License (https://opensource.org/licenses/MIT)
 */

// デバッグ用
// debugger;

(function () {
  var framePost;           // 投稿用のフレーム
  var framePreview;        // プレビュー用のフレーム
  var title;               // 「タイトル」テキスト フィールド
  var previewButton;       // 「プレビュー」ボタン
  var postingComposeBox;   // 投稿用のリッチ テキスト エディタ
  var postingHtmlBox;      // 投稿用のテキストエリア
  var prevTitle;           // 比較用のタイトルの内容
  var prevRichTextContent; // 比較用のリッチ テキスト エディタの投稿内容
  var prevContent;         // 比較用のテキストエリアの投稿内容
  var timerId = 0;         // プレビューを更新するために使うタイマー

  // 初期処理
  var init = function () {
    framePost = frames[0];
    framePreview = frames[1];

    // 投稿用のフレームから開かれるウィンドウをプレビュー用のフレームにする
    framePost.window.open = function (url, name, params) {
      framePreview.location.href = url;
      return framePreview.window;
    }

    waitUntilLoad(function () {
      waitUntilLoaded(function () {
        // 必要な要素を取得する
        title = framePost.document.querySelector('input[type=text][title=タイトル]');
        previewButton = findElement('.blogg-button', 'プレビュー');
        postingComposeBox = framePost.document.getElementById('postingComposeBox')
          .contentDocument.getElementById('postingComposeBox');
        postingHtmlBox = framePost.document.getElementById('postingHtmlBox');

        // タイトルと投稿内容を取得する
        prevTitle = title.value;
        prevRichTextContent = postingComposeBox.innerHTML;
        prevHtmlContent = postingHtmlBox.value;

        // 「プレビュー」ボタンを擬似的にクリックしてプレビュー
        previewButton.click();

        // 監視を開始する
        watch();
      });
    });
  };

  // 「読込中...」が表示されるまで待機
  var waitUntilLoad = function (loadFunc) {
    var loading = findElement('.gwt-HTML', '読込中...');
    if (loading !== null) {
      loadFunc();
      return;
    }

    // 500 ミリ秒ごとに確認する
    setTimeout(function () { waitUntilLoad(loadFunc); }, 500);
  }

  // 「読込中...」が非表示になるまで待機
  var waitUntilLoaded = function (loadedFunc) {
    var loading = findElement('.gwt-HTML', '読込中...');
    if (loading === null) {
      loadedFunc();
      return;
    }

    // 500 ミリ秒ごとに確認する
    setTimeout(function () { waitUntilLoaded(loadedFunc); }, 500);
  }

  // 要素を検索
  var findElement = function (selectors, text) {
    var elements = framePost.document.querySelectorAll(selectors);
    for (var i = 0; i < elements.length; i++) {
      if (elements[i].textContent === text) {
        return elements[i];
      }
    }
    return null;
  }

  // 監視
  var watch = function () {
    // タイトルか投稿内容が変更されていたらプレビューを更新する
    if (title.value !== prevTitle
        || postingComposeBox.innerHTML !== prevRichTextContent
        || postingHtmlBox.value !== prevHtmlContent) {
      updatePreview();
    }

    // 比較用のタイトルと投稿内容を更新する
    prevTitle = title.value;
    prevRichTextContent = postingComposeBox.innerHTML;
    prevHtmlContent = postingHtmlBox.value;

    // 500 ミリ秒ごとに確認する
    setTimeout(watch, 500);
  }

  // プレビューの更新
  var updatePreview = function () {
    // 1 秒以内に投稿内容が更新された場合には、前回のタイマーをキャンセルする
    clearTimeout(timerId);

    // プレビューを更新する
    timerId = setTimeout(function () { previewButton.click(); }, 1000);
  }

  // フレームに置き換える
  var fs = document.createElement('frameset');
  var f1 = document.createElement('frame');
  var f2 = document.createElement('frame');
  fs.cols = "*,*";
  f1.src = location.href;
  f1.addEventListener('load', init);
  fs.appendChild(f1);
  fs.appendChild(f2);
  document.documentElement.innerHTML = '';
  document.body.appendChild(fs);
  document.body.style.margin = '0px';
})();

0 件のコメント:

コメントを投稿