< Windows Media エンコード スクリプトで一括エンコード |

December 24, 2012

ブログ記事にイメージを埋め込み、さらに拡大表示時に前後のイメージに移動することのできるスクリプト

写真をいっぱい埋め込んだブログ記事を書くのが面倒になってきて、省力化しようとスクリプトを書いてみました。
ライブラリフリー。innerHTML でなくて、普通に DOM 操作しているので処理速度は微妙かも。
まだちゃんと CSS ファイルを作成していなくて、スクリプト内部でいっぱい style アトリビュートを設定していますがご笑覧ください。
実際に diary の記事で使ってます。2個目以降のイメージをクリックすると拡大表示になり、拡大表示したイメージの上にマウスポインタを乗せると、前後のイメージを表示するための「<」と「>」が表示されます。

/** photo.js
 *
 * @author Kuwabara Miyuki (ba)
 * @version 1.0.0
 */
var jp;
if (!jp) jp = {};
if (!jp.raindrop) jp.raindrop = {};
if (!jp.raindrop.frog) jp.raindrop.frog = {};
if (!jp.raindrop.frog.photo) (function () {

    var _albums = [];

    var _getElementsByTagName = function (node, namespaceURI, tagName, prefix) {
//        var elements = node.getElementsByTagNameNS (namespaceURI, tagName);
//        if (!elements.length)
//            elements = node.getElementsByTagName ([prefix, tagName].join (':'));
        var elements = node.getElementsByTagName ([prefix, tagName].join (':'));
        if (!elements.length)
            elements = node.getElementsByTagName (tagName);
        return elements;
    };

    var _getContainedAlbum = function (id) {
        for (var i = 0; i < _albums.length; i ++)
            if (_albums [i].isExists (id))
                return _albums [i];
        return null;
    };

    var _load = function (targetDocument) {
        _loadAlbums (targetDocument);
        _loadThumbnails (targetDocument);
    };

    var _loadAlbums = function (targetDocument) {
        _albums = [];
        var albumElements = _getElementsByTagName (targetDocument, 'http://frog.raindrop.jp/ns', 'photo-album', 'frog');
        for (var i = 0; i < albumElements.length; i ++) {
            var itemElements = _getElementsByTagName (albumElements [i], 'http://frog.raindrop.jp/ns', 'photo-item', 'frog');
            if (itemElements.length) {
                var album = new jp.raindrop.frog.photo.__album ();
                for (var j = 0; j < itemElements.length; j ++) {
                    var id        = itemElements [j].getAttribute ('id');
                    var src        = itemElements [j].getAttribute ('src');
                    var title    = itemElements [j].getAttribute ('title');
                    album.add (id, src, title);
                }
                _albums.push (album);
            }
        }
    };

    var _loadThumbnails = function (targetDocument) {
        var elements = _getElementsByTagName (targetDocument, 'http://frog.raindrop.jp/ns', 'photo-thumbnail', 'frog');
        for (var i = 0; i < elements.length; i ++) {
            var caption    = (elements [i].getAttribute ('caption').match (/^yes$/i))? true: false;
            var link    = (elements [i].getAttribute ('link').match (/^yes$/i))? true: false;
            var content    = elements [i].getAttribute ('content');
            
            var album    = _getContainedAlbum (content);
            if (album) {
                var item = album.get (content);
                var thumbnail = item.getThumbnail (targetDocument, caption, link);
                elements [i].parentNode.insertBefore (thumbnail, elements [i]);
            }
        }
        for (var i = 0; i < elements.length; i ++) {
            elements [i].parentNode.removeChild (elements [i]);
        }
    };

    jp.raindrop.frog.photo = {
        "__album": function () {
            this._catalog = {};
        },
        "__item": function (id, src, title) {
            this.id        = id;
            this.src    = src;
            this.title    = title;
        },
        "__iterator": function (catalog, first, key) {
            var _keys = [];
            for (var k in catalog)
                _keys.push (k);
            
            var _index = first? 0: (_keys.length - 1);
            if (arguments.length > 2) {
                var index = 0;
                var length = _keys.length;
                
                _keys.push (key);
                while (_keys [index] != key)
                    index ++;
                _keys.length = length;
                if (index < length)
                    _index = index;
            }
            var _move = function (i) {
                if ((i < 0) || (i >= _keys.length))
                    return null;
                _index = i;
                return catalog[_keys[i]];
            };

            return {
                item: function () {
                    return _move (_index);
                },
                next: function () {
                    return _move (_index + 1);
                },
                previous: function () {
                    return _move (_index - 1);
                }
            };
        },
        '__albumWindow': function (iterator) {
            this._current    = iterator;
            var _this = this;
            var newWindow = window.open('', 'album', 'width=300,height=300,toolbar=no,directories=no,menubar=no,status=no,left=0,top=0');
            var newDocument = newWindow.document;
            newDocument.body.setAttribute ('style', [
                    'position: relative',
                    'background: black',
                    'color: #ccc',
                    'margin: 0',
                    'padding: 0',
                    'text-align: center',
                    ''
                ].join (';'));

            var baseLocation = newDocument.createElement ('base');
            baseLocation.setAttribute ('href', newWindow.opener.location.href);
            var head = newDocument.getElementsByTagName ('head');
            if (head.length) {
                head [0].insertBefore (baseLocation, head [0].firstChild);
            }
            else {
                head = newDocument.createElement ('head');
                head.appendChild (baseLocation);
                newDocument.body.parentNode.insertBefore (head, newDocument.body);
            }
            var container = newDocument.createElement ('div');
            container.setAttribute ('id', 'photo-container');
            container.setAttribute ('style', [
                'margin: 0',
                'padding: 0',
                ''
            ].join (';'));
            newDocument.body.appendChild (container);
            var caption = newDocument.createElement ('div');
            caption.setAttribute ('id', 'photo-caption');
            caption.setAttribute ('style', [
                'position: absolute',
                'visibility: hidden',
                'padding: 5px',
                'left: 0',
                'top: 0',
                'width: 100%',
                'text-align: center',
                'font: bold 25px/1.1 sans-serif',
                'color: white',
                ''
            ].join (';'));
            newDocument.body.appendChild (caption);
            var navigation = newDocument.createElement ('div');
            navigation.setAttribute ('id', 'album-navigation');
            navigation.setAttribute ('style', [
                'position: absolute',
                'visibility: hidden',
                'left: 0',
                'top: 0',
                'margin: 0',
                'padding: 0',
                'width: 100%',
                'vertical-align: middle',
                'font: bold 40px/1.1 sans-serif',
                'color: white',
                ''
            ].join (';'));
            var previous = newDocument.createElement ('div');
            previous.setAttribute ('id', 'album-navigation-previous');
            previous.setAttribute ('style', [
                'position: absolute',
                'left: 0',
                'top: 0',
                'margin: 0',
                'padding: 5px',
                'cursor: pointer',
                ''
            ].join (';'));
            previous.onclick = function (event) {
                _this.movePrevious ();
            };
            previous.innerHTML = '&lt;';
            navigation.appendChild (previous);
            var next = newDocument.createElement ('div');
            next.setAttribute ('id', 'album-navigation-next');
            next.setAttribute ('style', [
                'position: absolute',
                'right: 0',
                'top: 0',
                'margin: 0',
                'padding: 5px',
                'cursor: pointer',
                ''
            ].join (';'));
            next.onclick = function (event) {
                _this.moveNext ();
            };
            next.innerHTML = '&gt;'
            navigation.appendChild (next);
            newDocument.body.appendChild (navigation);

            newDocument.body.onmouseover = function (event) {
                caption.style.visibility = 'visible';
                navigation.style.visibility = 'visible';
            };
            newDocument.body.onmouseout = function (event) {
                caption.style.visibility = 'hidden';
                navigation.style.visibility = 'hidden';
            };

            this._update = function (item) {
                var image = item.getImageElement (newDocument);
                image.onload = function (event) {
                    newWindow.resizeTo (image.width, image.height + 20);
                    navigation.style.top = (image.height - 50) / 2;
                };
                if (container.firstChild)
                    container.replaceChild (image, container.firstChild);
                else
                    container.appendChild (image);
                caption.innerHTML = item.title;
                newDocument.title = item.title;
            };
            this._update (iterator.item ());
        },
        load: function (targetDocument) {
            return _load (targetDocument);
        }
    };
    
    jp.raindrop.frog.photo.__album.prototype = {
        add: function (id, src, title) {
            return this.append (new jp.raindrop.frog.photo.__item (id, src, title));
        },
        append: function (item) {
            item._setAlbum (this);
            this._catalog [item.id] = item;
            return item;
        },
        getCount: function () {
            return this._catalog.length;
        },
        get: function (id) {
            return this._catalog [id];
        },
        isExists: function (id) {
            return (id in this._catalog);
        },
        begin: function () {
            return new jp.raindrop.frog.photo.__iterator (this._catalog, true);
        },
        end: function () {
            return new jp.raindrop.frog.photo.__iterator (this._catalog, false);
        },
        iterator: function (id) {
            return new jp.raindrop.frog.photo.__iterator (this._catalog, false, id);
        }
    };

    jp.raindrop.frog.photo.__item.prototype = {
        getAlbum: function () {
            return this._album;
        },
        getImageElement: function (targetDocument) {
            var image = targetDocument.createElement ('img');
            image.setAttribute ('src', this.src);
            image.setAttribute ('alt', this.title);
            image.setAttribute ('title', this.title);
            return image;
        },
        getThumbnailURI: function () {
            var m = this.src.match (/^(.+)\.([^\.]+)$/);
            if (m)
                return [m [1], '-thumb.', m [2].toLowerCase ()].join ('');
            else
                return [this.src, '-thumb'].join ('');
        },
        getThumbnail: function (targetDocument, captionFlag, linkFlag) {
            var container = targetDocument.createElement ('div');
            container.setAttribute ('class', 'album-thumbnail');
            container.setAttribute ('style', 'display: inline-block; margin: 2px; vertical-align: top;');    // ★
            var thumbnail = targetDocument.createElement ('img');
            thumbnail.setAttribute ('title', this.title);
            thumbnail.setAttribute ('alt', this.title);
            thumbnail.setAttribute ('src', this.getThumbnailURI ());
            if (linkFlag) {
                var ancher = targetDocument.createElement ('a');
                var current = this._album.iterator (this.id);
                ancher.setAttribute ('href', this.src);
                ancher.setAttribute ('title', this.title);
                ancher.onclick = function (event) {
                    new jp.raindrop.frog.photo.__albumWindow (current);
                    return false;
                };
                ancher.appendChild (thumbnail);
                container.appendChild (ancher);
            }
            if (captionFlag) {
                var caption = targetDocument.createElement ('div');
                caption.setAttribute ('class', 'album-thumbnail-caption');
                caption.setAttribute ('style', 'margin: 0 0 0.5em 0;');    // ★
                thumbnail.onload = function (event) {
                    caption.setAttribute ('style', 'margin: 0 0 0.5em 0; width: ' + thumbnail.width + 'px;')
                };
                caption.appendChild (targetDocument.createTextNode (this.title));
                container.appendChild (caption);
            }
            return container;
        },
        '_setAlbum': function (album) {
            this._album = album;
        }
    };

    jp.raindrop.frog.photo.__albumWindow.prototype = {
        movePrevious: function () {
            var item = this._current.previous ();
            if (item)
                this._update (item);
        },
        moveNext: function () {
            var item = this._current.next ();
            if (item)
                this._update (item);
        }
    };

} ());

ウェブサイトへの埋め込みはこんな感じ。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:frog="http://frog.raindrop.jp/ns" xml:lang="ja">
    <head>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
        <script type="text/javascript" src="photo.js"></script>
        <script type="text/javascript">
        // <![CDATA[
        // 良く考えたら、ライブラリフリーと言いながらここで JQuery を使っている…
        // body.onload でも動くと思うけど、試してません。
        $(function () {
            jp.raindrop.frog.photo.load (document);
        });
        // ]]>
        </script>
    </head>
    <body>
        <!-- ここでアルバムに含める写真と説明を記述 -->
        <frog:photo-album xmlns:frog="http://frog.raindrop.jp/ns">
            <frog:photo-item id="1354345630278" src="http://frog.raindrop.jp/diary/archives/images/20121201/1354345630278.jpg" title="温野菜とオイルサーディンのクリームソース。沁みる。" ></frog:photo-item>
            <frog:photo-item id="1354345642818" src="http://frog.raindrop.jp/diary/archives/images/20121201/1354345642818.jpg" title="温野菜とオイルサーディンのクリームソース。沁みる。" ></frog:photo-item>
            <frog:photo-item id="1354346373447" src="http://frog.raindrop.jp/diary/archives/images/20121201/1354346373447.jpg" title="モロッコパンケーキにマロンのトッピング。" ></frog:photo-item>
            <frog:photo-item id="1354346401787" src="http://frog.raindrop.jp/diary/archives/images/20121201/1354346401787.jpg" title="チャイ。でかい。" ></frog:photo-item>
        </frog:photo-album>

        <!-- 実際にサムネイルを張り付けたい箇所では以下を記載 -->
        <frog:photo-thumbnail content="1354345642818" caption="yes" link="yes" ></frog:photo-thumbnail>
        <frog:photo-thumbnail content="1354346373447" caption="yes" link="yes" ></frog:photo-thumbnail>
        <frog:photo-thumbnail content="1354346401787" caption="yes" link="yes" ></frog:photo-thumbnail>
    </body>
</html>

トラックバック

このエントリーにトラックバック:
http://frog.raindrop.jp/cgi-bin/mt/mt-tb.cgi/2772

コメント

コメントする

※ コメントスパム対策のため、コメント本文はおはよう、こんにちわ、こんばんわのいずれかより始めるようにしてください。

name:
email:

※ 必要ですが、表示しません。

url:
情報を保存する ?