slide.js 6日目
今回のポイント
- #next()と#prev()を汎化させて#loadPage()を作った
#next()と#prev()ではページ番号のインクリメント・デクリメント?だけして
loadPageでそのページ番号に対応する配列インデックスをロード(style切り替え)
- titleを取得してid=headerなdivに埋め込み
- nextなどのボタンを下部につけた
- cssのグリッドレイアウトに苦しむ(;´Д`)
でもスライドショーっぽくなってきた!
- エフェクト系を調べ始め、FishEyeエフェクトを改変してみた(コードの整理してないからHTMLに直書)
- script.aculo.usのeffectにあるHighLightもつけてみたが、つけてみただけorz
slide.js
/* * slide.js * @version: 2007/05/09 * @author: futa23 */ // Slide class function Slide() { this.initialize.apply(this, arguments); } Slide.prototype.initialize = function() { this.header; this.contents = new Array(); this.page = 0; //deafult: false(normal mode) this.mode = false; }; Slide.prototype.start = function(){ //neglect slide mode if (this.mode) { return; } //change mode this.mode = true; //create header, footer into body document.getElementById('body').innerHTML = '<div id=\"header\" class=\"header\">header</div>' + document.getElementById('body').innerHTML + '<div id=\"footer\" class=\"footer\">' + '<a href=\"#\" onClick=\"javascript:Modalbox.show(\'slide.js -help-\'\, \'slide/help.html\'\, {width: 460\, height:400})\;return false\;\">(h)elp</a>' + '<input type=\"button\" value=\"start!\" id=\"startBtn\" onclick=\"slide.start()\" disable>' + '<input type=\"button\" value=\"prev!\" id=\"prevBtn\" onclick=\"slide.prev()\" disable>' + '<input type=\"button\" value=\"next!\" id=\"nextBtn\" onclick=\"slide.next()\"></div>'; //store slide base element on memory this.header = document.getElementById('header'); //change startBtn button disable if (document.getElementById('startBtn')) { // document.getElementById('startBtn').value = 'quit!'; // document.getElementById('startBtn').addEventListener('onClick', slde.quit(), false); document.getElementById('startBtn').disabled = true; } if (document.getElementById('nextBtn')) { document.getElementById('nextBtn').disabled = false; } //load contents var divPages = document.getElementsByTagName('div'); for (var i=0; i<divPages.length ; i++) { if (divPages[i].className == 'page') { divPages[i].id = this.contents.length; this.contents.push(divPages[i]); divPages[i].className = 'hide'; } } //load first page this.loadPage(0); }; Slide.prototype.next = function() { this.loadPage(++this.page); }; Slide.prototype.prev = function() { this.loadPage(--this.page); }; Slide.prototype.loadPage = function(p) { if (!this.mode) { return; } if (0 <= p && p < this.contents.length) { for (var i=0; i<this.contents.length; i++) { this.contents[i].className = 'hide'; } //for current page this.contents[p].className = 'main'; //TODO if (typeof Effect != 'undefined') { new Effect.Highlight(document.getElementById(p), {duration: 2}); } //get title for(var j=0; j<this.contents[p].childNodes.length; j++) { if (this.contents[p].childNodes[j].className && this.contents[p].childNodes[j].className == 'title') { // alert(this.contents[p].childNodes[j].innerHTML); this.header.innerHTML = this.contents[p].childNodes[j].innerHTML; break; } } //set inputed page to the current page. this.page = p; // change next button disable if (p == this.contents.length - 1){ if (document.getElementById('nextBtn')){ document.getElementById('nextBtn').disabled = true; } } // change prev button disable if (p == 0){ if (document.getElementById('prevBtn')){ document.getElementById('prevBtn').disabled = true; } }else { if (document.getElementById('prevBtn')){ document.getElementById('prevBtn').disabled = false; } } }else{ this.quit(); } }; Slide.prototype.quit = function() { if (!this.mode) { return; } for(var i=0; i<this.contents.length; i++) { this.contents[i].className = 'page'; this.contents[i].removeAttribute('style'); } //remove header document.getElementById('body').removeChild(this.header); //remove footer document.getElementById('body').removeChild(document.getElementById('footer')); this.initialize(); if (document.getElementById('startBtn')){ document.getElementById('startBtn').disabled = false; } if (document.getElementById('nextBtn')){ document.getElementById('nextBtn').disabled = false; } }; //app var slide = new Slide();
呼び出すhtml側
<html> <head> <title>slide.js</title> <link rel="stylesheet" type="text/css" href="includes/modalbox.css" media="screen" /> <link rel="stylesheet" type="text/css" href="slide/slide.css"/> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"> <!--help--> <script type="text/javascript" src="includes/prototype.js"></script> <script type="text/javascript" src="includes/scriptaculous.js"></script> <script type="text/javascript" src="includes/modalbox.js"></script> <script type="text/javascript" language="JavaScript" charset="utf-8" src="FishEye.js"></script> <script type="text/javascript" language="JavaScript" charset="utf-8" src="shortcuts.js"></script> <script type="text/javascript" language="JavaScript" charset="utf-8" src="slide.js"></script> <script type="text/javascript"> <!-- //add keybind shortcut('s', function(){slide.start();}); shortcut('left', function(){slide.prev();}); shortcut('right', function(){slide.next();}); shortcut('space', function(){slide.next();}); shortcut('q', function(){slide.quit();}); shortcut('h', function(){ Modalbox.show( 'slide.js -help-', 'slide/help.html', {width: 460, height:400} ); return false; } ); --> </script> </head> <body id="body" bgcolor="#FFFFFF" text="#003366" link="#3399FF" vlink="#99CCFF" alink="#FF3333"> <div class="page"> <h3 class="title">自己紹介</h3> <ul> <li >名前:futa23 <li>職業:SEでもプログラマーでもないIT系 <li>装備:Java(普通に), PHP(並以下), Perl(並以下), Ruby(初心者) </ul> </div> <div class="page"> <h3 class="title">slide.jsを作るきっかけ</h3> <ul> <li>oopなJavaScriptを書いてみたかった。 <li>作るなら実用的なもの。 <li>他のライブラリも使ってエフェクトも掛けたい。 <li>ショートカット厨なので、ショートカット機能は必須実装機能。 <li>HTML表示モードとプレゼンモードの切り替えができるように。 </ul> </div> <div class="page"> <h3 class="title">slide.jsのショートカット一覧</h3> <ul> <li><strong>s</strong> --- start slide show <li><strong>right(→) or space</strong> --- go to next page <li><strong>left(←)</strong> --- go to previous page <li><strong>q</strong> --- quit slide show <li><strong>h</strong> --- show this help page <li><strong>esc</strong> --- close this help page </ul> </div> <script type="text/javascript"> <!-- //FishEye var fishEye = new FishEye( {'large':'3em', 'medium':'2em', 'regular':'1em'} , {'target': 'li'} ); targets = document.getElementsByTagName('li'); for(var i=0; i<targets.length; i++) { // alert(targets.length); targets[i].addEventListener('onmouseover', this.bigger ,true); targets[i].addEventListener('onmouseout', this.normal ,true); } --> </script> </body> </html>
css
/* header */ #header{ height:15%; width:100%; background-color:#4a617b; margin:0px; padding:0.5em 0.7em 0em 1em;/*top right bottom left */ color:#ffffff; font-size:2em; font-weight:bold; vertical-align:middle; } /* current page */ .main{ height:77%; width:100%; font-size:1.5em; background-color:#eeeeee; border:0px; border-top:#FFFFFF 0px solid; margin:0px; padding:1.5em 1em 0em 1em;/*top right bottom left */ /*行間隔*/ } /* current page's title */ .main .title{ display:none; } /* footer */ #footer{ height:8%; width:100%; background-color:#314051; border-top:#FFFFFF 0px solid; margin:0px; padding:0.1em 0em 0em 0em;/*top right bottom left */ text-align:right; vertical-align:middle; } img{ border:none; } A:link{ color:#0ac0ff; text-decoration:none; } A:visited{ color:#5080e0; text-decoration:none; } A:hover{ color:#2ae0ff; text-decoration:underline; } .hide{ display: none; }
FishEye.js
おまけ。
DOMのpreviousSibling、nextSiblingを知った。
こんなシンプルに実装できるのね。感動。
FishEyeのオリジナルにオプションで引数渡せられるようにしたのと、クラス化しただけ。
/** * FishEye * by http://dannyayers.com/2003/10/fisheye.html * * revised by futa23 */ // FishEye class function FishEye() { this.initialize.apply(this, arguments); } FishEye.prototype.initialize = function() { //default this.large = '3em'; this.medium = '2em'; this.regular = '1em'; this.targetTagName = null; if(fontSize = arguments[0]) { if(fontSize['large']) this.large = fontSize['large']; if(fontSize['medium']) this.medium = fontSize['medium']; if(fontSize['regular']) this.regular = fontSize['regular']; } // if(option = arguments[1]) { // alert(option['target']); // if(option['target']) { // this.targetTagName = option['target']; // targets = document.getElementsByName(this.targetTagName); // for(var i=0; i<targets.length; i++) { // alert(targets.length); // targets[i].addEventListener('onmouseover', this.bigger ,true); // targets[i].addEventListener('onmouseout', this.normal ,true); // } // } // } }; //function convertPreBlocks() {} FishEye.prototype.bigger = function (thing){ thing.style.fontSize = this.large; siblingElement = thing.previousSibling; while(siblingElement) { if(siblingElement.tagName == thing.tagName) { siblingElement.style.fontSize = this.medium; break; } siblingElement = siblingElement.previousSibling; } siblingElement = thing.nextSibling; while(siblingElement) { if(siblingElement.tagName == thing.tagName) { siblingElement.style.fontSize = this.medium; break; } siblingElement = siblingElement.nextSibling; } } FishEye.prototype.normal = function(thing){ thing.style.fontSize = this.regular; siblingElement = thing.previousSibling; while(siblingElement) { if(siblingElement.tagName == thing.tagName) { siblingElement.style.fontSize = this.regular; break; } siblingElement = siblingElement.previousSibling; } siblingElement = thing.nextSibling; while(siblingElement) { if(siblingElement.tagName == thing.tagName) { siblingElement.style.fontSize = this.regular; break; } siblingElement = siblingElement.nextSibling; } }
参考
- Javascript(script.aculo.us)で、ブログをアニメーション・デザイン
- script.aculo.us リファレンス
- FishEye
- http://www.assoc-amazon.jp/e/ir?t=neta04-22&l=as2&o=9&a=4873110270:title:Amazon.co.jp: JavaScript: 本: デイビッド フラナガン,David Flanagan,村上 列,垰井 正雄,安藤 進
JavaScriptのコード自体は初めて書いたに等しいけど、ちょこちょこ本は読んでた。
オライリーのサイ本。
レビューにもあるとおり、書かれてるJavaScriptのバージョンは古いけどためになる。
prototypeベースなオブジェクト指向の意味がわかった本。
あと、JavaScriptにおいて
連想配列(JavaでいうHashMapクラスだと思っていいforJavaしか知らない人)はオブジェクト、
というかオブジェクトは連想配列なこととか、
documentクラスやwindowsクラス、for inなど基礎がたくさん載ってる名著。