function l(selector) { "use strict"; var forEach = Array.prototype.forEach; //forEach関数のエイリアス。呼び出しやすいように。 var elms; //最初に要素を格納する変数。 if (typeof selector === "string") { if (id_or_not(selector)) { elms = []; elms[0] = document.getElementById(selector.slice(1)); //引数がidの形式だったら1文字目取ってget~IDして配列0に格納。 } else { elms = qsa(selector); //引数として受け取ったセレクタ文字列でQSA。 } } else { if(selector.instanceof === "main"){ return selector; } if (selector.length) { elms = selector; } else { elms = []; elms[0] = selector; } } function main() { //クラスです。 var self = this; //callの中ではthisは変わってしまうので(elmsになっているので)変数に格納。 forEach.call(elms, function(elm, i, arr) { self[i] = elm; //取得した要素をクラスのメンバ変数(配列?)に1個ずつ入れる。 self[i].index = i; self[i].stop_anime = false; }); this.length = elms.length; //そのままだとlengthプロパティが無かったので追加。 Object.defineProperties(this, {"instanceof": {value: "main"}}); } /*----- 高さ揃えメソッド -----*/ main.prototype.unify_height = function() { var len = this.length;//lオブジェクトの数; if(len === 1){//1個なら高さ揃える意味ないのでreturn; return this; } var top_arr = []; //offsetTopを格納する配列。1列揃えると他の要素の位置が変わるので最初に全部格納はできない。 var height_arr = []; //offsetHeightを格納する配列。最初に全部入れておく。 forEach.call(this, function(elm, i, arr){ height_arr.push(elm.offsetHeight); }); var col_1 = 0;//最初の列。 var col_last;//最後の列。 while(col_1 < len - 1){//最後の列の1個前まで実行。 top_arr.push(this[col_1].offsetTop);//この行の一列目の高さを格納。 for(var i = col_1 + 1; i < len; i++){ top_arr.push(this[i].offsetTop);//offsetTopを格納する(比較するために) if(top_arr[col_1] === top_arr[i]){//もし最初の要素と縦位置が一緒なら col_last = i;//その要素までは高さ揃えるのでiを覚えておく。 } else { break; } } one_row_set(col_1, col_last, this);//一行分高さを合わせる。 col_1 = col_last + 1; top_arr.pop();//最後に格納した位置は一行合わせた事で変わる可能性があるので消す。次のターンで格納し直し。 } function one_row_set(col_1, col_last, self){//一行分高さを合わせる。 var nums = height_arr.slice(col_1, col_last + 1);//全要素の高さを格納した配列から一行分取ってくる。 var max_height = Math.max.apply(null, nums);//その行で一番高いやつの高さを取得。 for(var i = col_1; i <= col_last; i++) {//一列目から最後の列まで if(height_arr[i] != max_height){//すでに最高でなければ set_height(self[i], max_height);//最大の高さに合わせる。 } } } function set_height(elm, height) { //実際に高さをセットする関数。 var styles = window.getComputedStyle(elm, null); //1個の要素の計算済みスタイルを変数に格納。 if (styles.boxSizing != "border-box") { var sabun = parseInt(styles.borderTopWidth) + parseInt(styles.borderBottomWidth) + parseInt(styles.paddingTop) + parseInt(styles.paddingBottom); //上下paddingとborderを足した値を計算。"px"部分を取るためにparseInt。 height = height - sabun; //border-boxじゃない場合は、上下paddingとborderを引いた値でheightを上書き。 }; elm.style.height = height + "px"; //実際に高さ設定。 } return this; }; main.prototype.toggleClass = function(toggle_classes) { //引数はトグルしたいクラス名。文字列。スペース繋ぎで複数来ることも。 forEach.call(this, function(elm, i, array) {//thisはインスタンス。要素たち。 elm.className = change_class(elm.className, toggle_classes, "toggle");//新しいクラス名を入れていく。 }); return this; }; main.prototype.addClass = function(add_classes) { //引数は追加したいクラス名。文字列。スペース繋ぎで複数来ることも。 forEach.call(this, function(elm, i, array) {//thisはインスタンス。要素たち。 elm.className = change_class(elm.className, add_classes, "add");//新しいクラス名を入れていく。 }); return this; }; main.prototype.removeClass = function(remove_classes) { //引数は取り除きたいクラス名。文字列。スペース繋ぎで複数来ることも。 forEach.call(this, function(elm, i, array) {//thisはインスタンス。 elm.className = change_class(elm.className, remove_classes, "remove");//新しいクラス名を入れていく。 }); return this; }; main.prototype.sarc = function(remove_class_name, obj) { var target_class = remove_class_name.slice(1); var target = this; var len = target.length; var speed = 700; if (obj && obj.speed) speed = obj.speed; var top = 0.05; if (obj && obj.top) top = obj.top; var btm = 0.95; if (obj && obj.bottom) btm = obj.bottom; for (var i = 0; i < len; i++) { target[i].style.transition = speed + "ms"; } for (var i = 1; i <= 40; i++) { var speed = document.querySelectorAll("." + target_class + ".speed" + i * 100); var slen = speed.length; for (var k = 0; k < slen; k++) { speed[k].style.transition = i / 10 + "s"; } } var wh = window.innerHeight; function remove_class(top, btm) { return function() { for (var i = 0; i < len; i++) { var gBCR = target[i].getBoundingClientRect(); var tTop = gBCR.top; var tBtm = gBCR.bottom; var className = target[i].className; var delayClass = /delay[1-9]00/; if (tTop > wh * top && tBtm < wh * btm) { if (delayClass.test(className)) { setTimeout(function(i) { return function() { target[i].className = change_class(target[i].className, target_class, "remove"); }; }(i), (className.match(delayClass)[0]).slice(5)); } else { target[i].className = change_class(target[i].className, target_class, "remove"); } } else { if (obj && obj.reverse) target[i].className = change_class(target[i].className, target_class, "add"); } } } } window.addEventListener("scroll", remove_class(top, btm), false); window.addEventListener("load", remove_class(0, btm), false); return this; } main.prototype.go_top_fix = function(target, speed) { var self = this; var speed = speed || 300; window.addEventListener("scroll", func(speed)); function func(speed) { return function() { var footer_top = qs(target).getBoundingClientRect().top; forEach.call(self, function(elm, i, arr) { elm.style.zIndex = 1; }); if (window.pageYOffset > 100) { forEach.call(self, function(elm, i, arr) { elm.style.display = "block"; }); $(self).stop().animate({ opacity: 1 }, speed); } else { $(self).stop().animate({ opacity: 0 }, speed, function() { self.css("display", "none"); }); } if (footer_top < window.innerHeight) { forEach.call(self, function(elm, i, arr) { elm.style.position = "relative"; }); } else { forEach.call(self, function(elm, i, arr) { elm.style.position = "fixed"; }); } } } window.addEventListener("load", function() { func(0)(); }); return this; }; main.prototype.kaihei = function(target, obj) { var self = this; var l_target = l(target); var speed = "500"; if (obj && obj.speed) speed = obj.speed; l_target.css("overflow", "hidden"); if(self.length != l_target.length){ console.log("開閉ボタンと開閉対象の数が違います"); console.log("開閉ボタン:" + self.length + "個 開閉対象:" + l_target.length + "個"); } forEach.call(this, function(elm, i, arr) { elm.addEventListener("click", function() { kai(i); }); elm.style.cursor = "pointer"; }); function all_close(speed) { forEach.call(l(target), function(elm, i, arr) { if (elm.clientHeight != 0) { var position = window.pageYOffset - elm.clientHeight; $(elm).animate({ height: 0 }, speed); if(rect(elm).top < 0){ $("html, body").animate({scrollTop: position}, speed); } } }); if (obj && obj.open_class)self.removeClass(obj.open_class); } function kai(i) { if (obj && obj.close) all_close(speed); var kai_target = l_target[i]; var children = kai_target.children; var firstChild = children[0]; var lastChild = children[children.length - 1]; var auto = rect(lastChild).bottom - rect(firstChild).top + parseInt(getCss(lastChild).marginBottom) + parseInt(getCss(firstChild).marginTop); if (kai_target.clientHeight == 0) { $(kai_target).animate({ height: auto + "px" }, speed, function() { kai_target.style.height = "auto"; }); if (obj && obj.open_class) { l(self[i]).addClass(obj.open_class); } } else { if (obj && obj.open_class)self.removeClass(obj.open_class); var position = window.pageYOffset - kai_target.clientHeight; $(kai_target).animate({ height: 0 }, speed); if(rect(kai_target).top < 0){ $("html, body").animate({scrollTop: position}, speed); } } } forEach.call(l(target), function(elm, i, arr) { if (elm.clientHeight != 0) { elm.style.height = 0; } }); return this; }; main.prototype.tab_changer = function(target, obj) { var self = this; var l_target = l(target); var now_index = 0; forEach.call(this, function(elm, i, arr) { elm.addEventListener("click", function() { select_tab(i); }); elm.style.cursor = "pointer"; }); function zenkeshi() { l_target.css("display", "none"); if (obj && obj.open_class) { self.removeClass(obj.open_class); } } function select_tab(i) { zenkeshi(); l_target[i].style.display = "block"; now_index = i; //console.log(now_index); if (obj && obj.open_class) { l(self[i]).addClass(obj.open_class); } } if (obj && obj.prev) { obj.prev.addEventListener("click", function(){ if (now_index == 0) { select_tab(self.length - 1); } else { select_tab(now_index - 1); } }); } if (obj && obj.next) { obj.next.addEventListener("click", function(){ if (now_index == self.length - 1) { select_tab(0); } else { select_tab(now_index + 1); } }); } select_tab(0); return this; }; main.prototype.hover_img = function(state2, transition) { var btn = this; var img = document.querySelectorAll(selector + " img"); forEach.call(img, function(elm, i, arr) { var cln = elm.cloneNode(true); cln.src = cln.src.replace(/(\.png|\.jpg)$/, state2 + "$1"); cln.className = state2; cln.style.position = "absolute"; cln.style.top = 0; cln.style.left = 0; elm.style.zIndex = 1; elm.style.position = "relative"; if (transition) img[i].style.transition = transition + "ms"; btn[i].style.position = "relative"; btn[i].style.display = "inline-block"; btn[i].appendChild(cln); }); return this; }; main.prototype.css = function(props, val) { var obj = obj_or_not(props); forEach.call(this, function(elm, i, array) { if (obj) { for (var key in props) { elm.style[key] = props[key]; } } else { elm.style[props] = val; } }); return this; }; main.prototype.on = function(arg1, func) { var obj = obj_or_not(arg1); forEach.call(this, function(elm, i, array) { if (obj) { for (var key in arg1) { elm.addEventListener(key, arg1[key]); } } else { elm.addEventListener(arg1, func); } }); return this; }; /*-- 汎用的な関数たち --*/ function change_class(moto_className, change_classes, mode){//元のクラス名と、追加or削除するクラス名(配列)を受け取る。modeは追加or削除orトグル。 var change_class_arr = change_classes.split(" ");//スペース繋ぎのクラス名たちを配列に格納。 var classList_arr = []; if(moto_className){ classList_arr = moto_className.split(" ");//元のクラス名たちを配列に格納。 } forEach.call(change_class_arr,function(elm, i, array){//追加or削除するクラス名(配列)を一つずつ足していく。 var index = classList_arr.indexOf(elm);//現在のクラス名配列の中に、追加or削除したいクラス名1があるかどうかを格納。(1回に1個しか探せない) if(index < 0 && (mode === "add" || mode === "toggle")){//現在のクラス名配列の中に、追加したいクラス名1がなければ、 classList_arr.push(elm);//そのクラス名を追加する。 } while(index >= 0 && (mode === "remove" || mode === "toggle")){//現在のクラス名配列の中に、消したいクラス名1があれば、 classList_arr.splice(index, 1);//そのクラス名を取る。 index = classList_arr.indexOf(elm);//そのクラス名が無くなるまで取り続けるためにindexOfをする。 } }); //console.log(classList_arr); return classList_arr.join(" ");//元のクラス名配列を文字列に結合して返す。 } function id_or_not(selector) { //idかどうかチェックする関数。 var id = new RegExp("^#[a-zA-Z]{1}[a-zA-Z0-9_-]*$"); return (id.test(selector)); } function obj_or_not(obj_or_some) { if (typeof obj_or_some == "object" && obj_or_some != null) { return true; } else { return false; } } function qsa(selector) { //querySelectorAllの短縮版。 return l.qsa(selector); } function qs(selector) { //querySelectorの短縮版。 return l.qs(selector); } function rect(elm) { //getBoundingClientRectの短縮版。 return l.rect(elm); } function getCss(elm) { //getComputedStyleの短縮版。 return l.getCss(elm); } var rtn = new main(); //mainクラスから実体を生成。これを戻り値として返す。 return rtn; } l.qsa = function(selector){ //querySelectorAllの短縮版。 return document.querySelectorAll(selector); }; l.qs = function (selector) { //querySelectorの短縮版。 return document.querySelector(selector); }; l.id = function (id) { //querySelectorの短縮版。 return document.getElementById(id); }; l.rect = function (elm) { //getBoundingClientRectの短縮版。 return elm.getBoundingClientRect(); }; l.getCss = function (elm) { //getComputedStyleの短縮版。 return window.getComputedStyle(elm); };