slide.js 7日目
まぁ目標としていたレベルは完成したかな。
自分的にはα版まではできた。
フェードインをつけたい。
あと目次の自動生成して、クリック移動できるモーダルウィンドウ・ナビゲーターつけたら終了かな。
今回のポイント
- エフェクトとして、もんたメソッド、zoom-inを実装
背景色(background-color)と文字色(color)を同じ色にして、
クリックしたら背景色をスライドの背景色と同じに変更するだけ。
zoom-inに至っては、cssの:hoverを使っただけ。
- グリッドレイアウトも一応それっぽくできた
CSS難しい。
- ページ指定ジャンプ機能実装
- ブラウザ互換addEventListener実装(どこからかのぱくり)
- クラス名でDOM Elementが取れるdocument#getElementsByClassNameを実装(どこからかのぱくり)
slide.js
/* * slide.js * @version: 2007/05/10 * @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; //set style sheet this.setStyleSheet('./slide.js/css/slide.css'); //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="./slide.js/core/help.html?height=200&width=400&modal=true" class="thickbox" title="slide.js -help-">help</a>' + '<a href="#top" id="start" onclick="javascript:slide.jump(0)">top</a>' + '<a href="#prev" id="prev" onclick="javascript:slide.prev()" disable>prev</a>' + '<input type="text" name="jump" id ="jump" width="30px" value="1"' + 'onkeypress="javascript:if(event.keyCode == 13) {slide.jump((this.value-1));}"/>' + '<span id="lastPage">/0</span>' + '<a href="#next" id="next" onclick="javascript:slide.next()">next</a>' + '<a href="#quit" id="quit" onclick="javascript:slide.quit()">quit</a>' + ' </div>'; //store slide base element on memory this.header = document.getElementById('header'); if (document.getElementById('next')) { document.getElementById('next').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'; } } //set lastPage document.getElementById('lastPage').innerHTML = '/' + this.contents.length; //load first page this.jump(0); }; Slide.prototype.next = function() { this.jump(++this.page); }; Slide.prototype.prev = function() { this.jump(--this.page); }; Slide.prototype.jump = function(p) { if (!this.mode || typeof p == 'undefined' || isNaN(p)) 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'; this.setEffect(); //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 = '<span class=title>' + this.contents[p].childNodes[j].innerHTML + '</span>'; break; } } //set inputed page to the current page. this.page = p; document.getElementById('jump').value = (p+1); // change next button disable if (p == this.contents.length - 1){ if (document.getElementById('next')){ document.getElementById('next').disabled = true; } } // change prev button disable if (document.getElementById('prev')){ if (p == 0){ document.getElementById('prev').disabled = true; }else { document.getElementById('prev').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.setStyleSheet(); //change to normal-mode(not slideshow-mode) this.initialize(); this.resetEffect(); }; Slide.prototype.setStyleSheet = function (sheet) { if(links = document.getElementsByTagName('link')){ for(var i=0; i<links.length; i++) { if (links[i].rel == 'stylesheet' && links[i].type == 'text/css') { //set normal or another stylesheet enable if slideshow-mode if (this.mode) { if(links[i].title != 'slide'){ links[i].disable = false; }else { links[i].disable = true; document.getElementsByTagName('head')[0].removeChild(links[i]); }; } } } } if (sheet) { linkTag = document.createElement('link'); linkTag.setAttribute('title', 'slide'); linkTag.setAttribute('rel', 'stylesheet'); linkTag.setAttribute('type', 'text/css'); linkTag.setAttribute('href', sheet); document.getElementsByTagName('head')[0].appendChild(linkTag); } }; Slide.prototype.setEffect = function() { //TODO //fade-in //monta var montas = document.getElementsByClassName('monta'); for(var i=0; i<montas.length; i++) { montas[i].setAttribute('style', 'z-index:10'); addEventListener(montas[i], 'click', function() { this.className = 'monta-off'; }); } }; Slide.prototype.resetEffect = function() { //monta-off var montas = document.getElementsByClassName('monta-off'); for(var i=0; i<montas.length; i++) { montas[i].className = 'monta'; } }; /** * general eventListner * @param {Object} target * @param {Object} type * @param {Object} func * * @usage:addEventListner(obj, 'click', func1); */ function addEventListener(target, type, func) { if(target.attachEvent) { target.attachEvent("on" + type, func); } else if(target.addEventListener) { target.addEventListener(type, func, true); } else { target["on" + type] = func; } } /** * * @param {Object} className */ document.getElementsByClassName = function(className) { var elementsAll = document.getElementsByTagName('*') || document.all; var elements = new Array(); for(var i = 0; i < elementsAll.length; i++) { var classNames = elementsAll[i].className.split(' '); for(var j = 0; j < classNames.length; j++) { if (classNames[j] == className) { elements[elements.length] = elementsAll[i]; break; } } } return elements; } //app var slide = new Slide();
呼び出すHTML
?<html> <head> <title>slide.js</title> <link rel="stylesheet" type="text/css" href="./slide.js/css/normal.css"/> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"> <!--help--> <script type="text/javascript" src="./slide.js/plugins/FishEye.js"></script> <script type="text/javascript" language="JavaScript" charset="utf-8" src="./slide.js/plugins/shortcuts.js"></script> <script type="text/javascript" language="JavaScript" charset="utf-8" src="./slide.js/core/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();}); --> </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> <div class="page"> <h3 class="title">class指定でできるエフェクト</h3> <ul> <li class="fishEye">li.fishEye --- FishEyeメニュー <li>monta --- <span class="monta">もんたメソッド</span> <li>zoom-in --- <span class="zoom-in">拡大</span> </ul> </div> </body> </html>
slide.css
z-indexっていうオーバーレイ表現でよく使う属性を初めて使った。
これでモーダルウィンドウ実装するのね。なるほど。
*{ margin:0px; border:0px; font-family:MeiryoKe_Pgothic, メイリオ, Osaka, Arial, Helvetica, sans-serif; } #body{ height:100%; width:100%; background-color:#c4daa3; } /* header */ #header{ height:2em; color:#003366; background-color:#c4daa3; margin:0px; padding:1em 0.7em 0em 1em;/*top right bottom left */ font-weight:bolder; font-size:2.5em; vertical-align:text-bottom; } #header .title{ border-bottom:0.2em solid; width:80%; border:solid #50682b; border-width:0 0 1px 12px; padding:0.4em 0.4em; } /* current page */ .main{ font-size:1.5em; font-weight:bold; color:#003366; background-color:#c4daa3; border:0px; border-top:#FFFFFF 0px solid; margin:0px; padding:0.2em 0.5em 0em 1em;/*top right bottom left */ line-height:40px; } /* current page's title */ .main .title{ display:none; } .main ul, .main ol{ padding-left:2em; } /* footer */ #footer { position:absolute; bottom:0px; z-index:10; width:100%; background-color:#314051; border-top:#FFFFFF 0px solid; padding:0.1em 0em 0.1em 0em;/*top right bottom left */ text-align:right; vertical-align:middle;; color:#ffffff; font-size:1em; } #footer input{ margin-left:10px; width:30px; } img{ border:none; } A{ margin-left:10px; } A:link{ color:#0ac0ff; text-decoration:none; } A:visited{ color:#5080e0; text-decoration:none; } A:hover{ color:#2ae0ff; text-decoration:underline; } /* effect */ .hide{ display: none; } .main li.zoom-in:hover{ font-size:2em; } .main .monta { background-color:yellow; color:yellow; } .main .monta-off{ }