呼び出される度にクロージャを作るのは効率悪いよね、ってことでリファクタリング。
この変更で
Rounder.roundAndPad.mapToElementsBySelector('selector');
というのはできなくなって、
(function(e){Rounder.roundAndPad(e)}).mapToElementsBySelector('selector');
と書かないといけなくなりました。
また、getElementsBySelector()
は :(first|last)-child
疑似クラスに対応しました。
NiftyCorner.js
/* 基本オブジェクトを拡張 */ if (!String.trim) { String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }} if (!String.ltrim) { String.prototype.ltrim = function() { return this.replace(/^\s+/, ''); }} if (!String.rtrim) { String.prototype.rtrim = function() { return this.replace(/\s+$/, ''); }} if (!Number.square) { Number.prototype.square = function() { return Math.pow(this, 2); }} if (!Number.cube) { Number.prototype.cube = function() { return Math.pow(this, 3); }} if (!Number.sqrt) { Number.prototype.sqrt = function() { return Math.sqrt(this); }} if (!Number.round) { Number.prototype.round = function() { return Math.round(this); }} if (!Number.floor) { Number.prototype.floor = function() { return Math.floor(this); }} if (!Number.ceil) { Number.prototype.ceil = function() { return Math.ceil(this); }} if (!Math.hypot) { Math.hypot = function(x, y) { return (x.square() + y.square()).sqrt(); }} if (!Math.base) { Math.base = function(z, y) { return (z.square() - y.square()).sqrt(); }} /* スタイルシート */ var NiftyStyle = '<style type="text/css">' + 'span.NiftyElement {' + 'display:block;' + 'margin:0;' + 'padding:0;' + 'overflow:hidden;' + 'overflow-x:hidden;' + 'overflow-y:hidden;' + '}' + '</style>'; document.write(NiftyStyle); /** * 角丸化オブジェクト本体 */ function NiftyCorner() { // {{{ 初期化 var mode = 'round'; if (arguments.length > 0) { mode = arguments[0].toString(); switch (arguments[0]) { case 0: mode = 'linear'; break; case -1: mode = 'flipped'; break; } } this._bgcolor = (arguments.length > 1) ? arguments[1].toString() : '#fff'; this._color = (arguments.length > 2) ? arguments[2].toString() : '#ccc'; this._size = (arguments.length > 3 && parseInt(arguments[3]) > 0) ? parseInt(arguments[3]) : 5; this._step = (arguments.length > 4 && parseInt(arguments[4]) > 0) ? parseInt(arguments[4]) : 1; this._size = Math.max(this._size, this._step); this._bdcolor = (arguments.length > 5) ? arguments[5].toString() : null; this._bdwidth = (arguments.length > 6 && parseInt(arguments[6]) > 0) ? parseInt(arguments[6]) : 1; this._bdwidth = Math.min(Math.floor(this._size / this._step), this._bdwidth); this._default = [this._bgcolor, this._color, this._size, this._step, this._bdcolor, this._bdwidth]; this._defaultId = this._default.join(); this._defaultTop = null; this._defaultBottom = null; // }}} // {{{ モードに適したマージン計算メソッドを設定 switch (mode) { case 'flip': case 'flipped': case 'eclipse': this.calcMargin = this.calcFlippedMargin; this.calcMargin2 = this.calcFlippedMargin2; break; case 'line': case 'linear': case 'straight': this.calcMargin = this.calcLinearMargin; this.calcMargin2 = this.calcLinearMargin2; break; case 'round': default: this.calcMargin = this.calcRoundMargin; this.calcMargin2 = this.calcRoundMargin2; } // }}} // {{{ デフォルト値で作成した要素をキャッシュ this._defaultTop = this.createTop(this._default); this._defaultBottom = this.createBottom(this._default); // }}} } // }}} /* 共通処理はプロトタイプに定義 */ // {{{ 角丸化メソッド /** * 四隅を丸くする */ NiftyCorner.prototype.round = function() { var params = this.parseArguments(arguments); var target = params.shift(); var top = target.insertBefore(this.createTop(params), target.firstChild); var bottom = target.appendChild(this.createBottom(params)); return [top, bottom]; } /** * 上の角を丸くする */ NiftyCorner.prototype.roundTop = function() { var params = this.parseArguments(arguments); var target = params.shift(); return target.insertBefore(this.createTop(params), target.firstChild); } /** * 下の角を丸くする */ NiftyCorner.prototype.roundBottom = function() { var params = this.parseArguments(arguments); var target = params.shift(); return target.appendChild(this.createBottom(params)); } /** * 四隅を丸くし、内容を自動でパディングする */ NiftyCorner.prototype.roundAndPad = function() { var params = this.parseArguments(arguments); var target = params.shift(); var bgcolor = params[0]; var color = params[1]; var size = params[2]; var step = params[3]; var bdcolor = params[4]; var bdwidth = params[5]; var container = document.createElement('div'); container.style.backgroundColor = bgcolor; container.style.margin = '0'; if (bdcolor) { var bdsize = step * bdwidth; container.style.padding = this.intToPixelsHorizontal(size - bdsize); container.style.borderColor = bdcolor; container.style.borderStyle = 'solid'; container.style.borderWidth = this.intToPixelsHorizontal(bdsize); } else { container.style.padding = this.intToPixelsHorizontal(size); } if (target.childNodes) { while (target.childNodes.length) { container.appendChild(target.removeChild(target.firstChild)); } } target.appendChild(container); var top = target.insertBefore(this.createTop(params), target.firstChild); var bottom = target.appendChild(this.createBottom(params)); return [top, bottom, container]; } /** * 上の角を丸くし、内容を自動でパディングする */ NiftyCorner.prototype.roundAndPadTop = function() { var params = this.parseArguments(arguments); var target = params.shift(); var bgcolor = params[0]; var color = params[1]; var size = params[2]; var step = params[3]; var bdcolor = params[4]; var bdwidth = params[5]; var container = document.createElement('div'); container.style.backgroundColor = bgcolor; container.style.margin = '0'; if (bdcolor) { var bdsize = step * bdwidth; var p = ' ' + this.intToPixels(size - bdsize); var b = ' ' + this.intToPixels(bdsize); container.style.padding = '0' + p + p + p; container.style.borderColor = bdcolor; container.style.borderStyle = 'solid'; container.style.borderWidth = '0' + b + b + b; } else { var p = ' ' + this.intToPixels(size); container.style.padding = '0' + p + p + p; } if (target.childNodes) { while (target.childNodes.length) { container.appendChild(target.removeChild(target.firstChild)); } } target.appendChild(container); var top = target.insertBefore(this.createTop(params), target.firstChild); return [top, container]; } /** * 下の角を丸くし、内容を自動でパディングする */ NiftyCorner.prototype.roundAndPadBottom = function() { var params = this.parseArguments(arguments); var target = params.shift(); var bgcolor = params[0]; var color = params[1]; var size = params[2]; var step = params[3]; var bdcolor = params[4]; var bdwidth = params[5]; var container = document.createElement('div'); container.style.backgroundColor = bgcolor; container.style.margin = '0'; if (bdcolor) { var bdsize = step * bdwidth; var p = ' ' + this.intToPixels(size - bdsize); var b = ' ' + this.intToPixels(bdsize); container.style.padding = (p + p + ' 0' + p).ltrim(); container.style.borderColor = bdcolor; container.style.borderStyle = 'solid'; container.style.borderWidth = (b + b + ' 0' + b).ltrim(); } else { var p = ' ' + this.intToPixels(size - bdsize); container.style.padding = (p + p + ' 0' + p).ltrim(); } if (target.childNodes) { while (target.childNodes.length) { container.appendChild(target.removeChild(target.firstChild)); } } target.appendChild(container); var bottom = target.appendChild(this.createBottom(params)); return [bottom, container]; } // }}} // {{{ 要素作成メソッド /** * 上の角を作成する */ NiftyCorner.prototype.createTop = function(p) { if (this._defaultTop && p.join() == this._defaultId) { return this._defaultTop.cloneNode(true); } var corner = this.createCorner(p[1], p[2]); corner.appendChild = function(newChild) { return this.insertBefore(newChild, this.firstChild); } if (p[4] == null) { this._appendLines(corner, p[0], p[2], p[3]); } else if (p[5] <= 1) { this._appendLinesBordered(corner, p[0], p[2], p[3], p[4]); } else { this._appendLinesBordered2(corner, p[0], p[2], p[3], p[4], p[5]); } return corner; } /** * 下の角を作成する */ NiftyCorner.prototype.createBottom = function(p) { if (this._defaultBottom && p.join() == this._defaultId) { return this._defaultBottom.cloneNode(true); } var corner = this.createCorner(p[1], p[2]); if (p[4] == null) { this._appendLines(corner, p[0], p[2], p[3]); } else if (p[5] <= 1) { this._appendLinesBordered(corner, p[0], p[2], p[3], p[4]); } else { this._appendLinesBordered2(corner, p[0], p[2], p[3], p[4], p[5]); } return corner; } /** * 角のコンテナを作成する */ NiftyCorner.prototype.createCorner = function(bgcolor, height) { var corner = document.createElement('span'); corner.className = 'NiftyElement'; corner.style.backgroundColor = bgcolor; corner.style.height = this.intToPixels(height); return corner; } /** * 角の実体を作成する */ NiftyCorner.prototype.createLine = function(bgcolor, height, margin) { var line = document.createElement('span'); line.className = 'NiftyElement'; line.style.backgroundColor = bgcolor; line.style.height = this.intToPixels(height); line.style.margin = this.intToPixelsHorizontal(margin); return line; } /** * 境界線つきの角の実体を作成する */ NiftyCorner.prototype.createLineBordered = function(bgcolor, height, margin, bdcolor, bdwidth) { var line = document.createElement('span'); line.className = 'NiftyElement'; line.style.backgroundColor = bgcolor; line.style.height = this.intToPixels(height); line.style.margin = this.intToPixelsHorizontal(margin); line.style.borderColor = bdcolor; line.style.borderStyle = 'solid'; line.style.borderWidth = this.intToPixelsHorizontal(bdwidth); return line; } // }}} // {{{ コーナー描画メソッド /** * コンテナに線を追加し、角を描画する */ NiftyCorner.prototype._appendLines = function(corner, bgcolor, size, step) { var i, line; for (i = 0; i < size; i += step) { line = this.createLine(bgcolor, step, this.calcMargin(size, i, step)); corner.appendChild(line); } } /** * コンテナに線を追加し、線の高さと同じ幅の境界線をもった角を描画する */ NiftyCorner.prototype._appendLinesBordered = function(corner, bgcolor, size, step, bdcolor) { var i, line, margin, bdsize; for (i = 0; i < size - step; i += step) { margin = this.calcMargin(size, i, step); bdsize = Math.max(step, this.calcMargin(size, i + step, step) - margin); line = this.createLineBordered(bgcolor, step, margin, bdcolor, bdsize); corner.appendChild(line); } line = this.createLine(bdcolor, step, this.calcMargin(size, i, step)); corner.appendChild(line); } /** * コンテナに線を追加し、任意の幅の境界線をもった角を描画する */ NiftyCorner.prototype._appendLinesBordered2 = function(corner, bgcolor, size, step, bdcolor, bdwidth) { var bdsize = step * bdwidth; var insize = size - bdsize ; var i, line, margins; for (i = 0; i < insize; i += step) { margins = this.calcMargin2(size, insize, bdsize, i, step); line = this.createLineBordered(bgcolor, step, margins[0], bdcolor, margins[1]); corner.appendChild(line); } while (i < size) { line = this.createLine(bdcolor, step, this.calcMargin2(size, insize, bdsize, i, step)[0]); corner.appendChild(line); i += step; } } // }}} // {{{ マージン計算メソッド /** * 角丸のマージンを計算する */ NiftyCorner.prototype.calcRoundMargin = function(size, level, step) { return size - Math.floor(Math.base(size, level + step) / step) * step; } /** * 角丸のマージンと境界線の横幅を計算する */ NiftyCorner.prototype.calcRoundMargin2 = function(size, insize, bdsize, level, step) { var m0 = 0, m1 = 0; m0 = this.calcRoundMargin(size, level, step); if (level < insize) { m1 = Math.max(this.calcRoundMargin(insize, level, step), this.calcRoundMargin(size, level + bdsize, step)); } return [m0, Math.max(bdsize, m1 - m0)]; } /** * 面取りのマージンを計算する */ NiftyCorner.prototype.calcLinearMargin = function(size, level, step) { return level; } /** * 面取りのマージンと境界線の横幅を計算する */ NiftyCorner.prototype.calcLinearMargin2 = function(size, insize, bdsize, level, step) { var x = Math.round(bdsize * (Math.SQRT2 - 1)); return [level - x, bdsize + x]; } /** * 切り欠きのマージンを計算する */ NiftyCorner.prototype.calcFlippedMargin = function(size, level, step) { return Math.floor(Math.base(size, size - level) / step) * step; } /** * 切り欠きのマージンと境界線の横幅を計算する */ NiftyCorner.prototype.calcFlippedMargin2 = function(size, insize, bdsize, level, step) { var m0 = 0, m1 = 0; if (level >= bdsize) { m0 = this.calcFlippedMargin(insize, level - bdsize, step); } if (level < insize) { m1 = Math.max(this.calcFlippedMargin(size, level, step), this.calcFlippedMargin(insize, level, step)); } return [m0, Math.max(bdsize, m1 - m0)]; } // }}} // {{{ ユーティリティメソッド /** * 引数をパースし、適切な値を設定する */ NiftyCorner.prototype.parseArguments = function(args) { var params = []; if (args.lengs == 0) { window.alert('argument #1 is required.'); return []; } params[0] = (typeof args[0] == 'string') ? document.getElementById(args[0]) : args[0]; if (!params[0] || !params[0].appendChild) { window.alert('argument #1 must be a DOM Element or an existing Element ID.'); return []; } params[1] = (args.length > 1) ? args[1].toString() : this._bgcolor; params[2] = (args.length > 2) ? args[2].toString() : this._color; params[3] = (args.length > 3 && parseInt(args[3]) > 0) ? parseInt(args[3]) : this._size; params[4] = (args.length > 4 && parseInt(args[4]) > 0) ? parseInt(args[4]) : this._step; params[5] = (args.length > 5) ? args[5].toString() : this._bdcolor; params[6] = (args.length > 6 && parseInt(args[6]) > 0) ? parseInt(args[6]) : this._bdwidth; params[3] = Math.max(params[3], params[4]); params[6] = Math.min(Math.floor(params[3] / params[4]), params[6]); return params; } /** * 数値をスタイルシート用のピクセル表記に変換する */ NiftyCorner.prototype.intToPixels = function(num) { return parseInt(num).toString() + 'px'; } /** * 数値をスタイルシート用のピクセル表記に変換する(上下は指定された数値、左右はゼロ) */ NiftyCorner.prototype.intToPixelsVertical = function(num) { return this.intToPixels(num) + ' 0'; } /** * 数値をスタイルシート用のピクセル表記に変換する(左右は指定された数値、上下はゼロ) */ NiftyCorner.prototype.intToPixelsHorizontal = function(num) { return '0 ' + this.intToPixels(num); } // }}}
getElementsBySelector.js
// {{{ document.getElementsBySelector() /** * CSS2 のセレクタで DOM Element を取得するメソッド * document オブジェクトを拡張 */ document.getElementsBySelector = function(selector) { // {{{ 変数の初期化 // myself var self = document.getElementsBySelector; // valid characters var c = '[A-Za-z_][0-9A-Za-z_\\-]*'; // valid characters with namaspace var ns = '(?:'+c+'\\\\:)?'+c; // regular expression object of valid characters var re = new RegExp('^'+c+'$'); // regular expression of valid selector var slctr_pat = '(\\*|'+ns+')((?:\\['+ns+'(?:[~|]?=".*?")?\\]|[#.:]'+c+')*)'; // regular expression of non-element (pseudo,id,class,attribute) selector var picas_pat = '\\[('+ns+')(?:([~|]?=)"(.*?)")?\\]|([#.:])('+c+')'; // regular expression object of valid selector var slctr_re = new RegExp(slctr_pat, 'g'); // regular expression object of non-element selector var picas_re = new RegExp(); // last match position of selector var slctr_pos = 0; // offset from last match position of selector var slctr_off = 0; // last match position of non-element selector var picas_pos = 0; // offset from last match position of non-element selector var picas_off = 0; // list of elements var roots = [document]; // variables for scanning var slctr, dvsr, elems, i, j, m, n, o, p; // }}} // {{{ セレクタをパースし、要素を走査 while (m = slctr_re.exec(selector)) { // {{{ 前処理 /* 前回の検索終了位置と今回の検索開始位置の差分 */ slctr_off = slctr_re.lastIndex - m[0].length - slctr_pos; /* セレクタ間の区切りを検証 */ if (slctr_pos > 0 && slctr_off == 0) { self.warn(selector, slctr_pos, 'Bad selector given.'); return []; } else if (slctr_off != 0) { dvsr = selector.substr(slctr_pos, slctr_off).replace(/^[\t\r\n ]+|[\t\r\n ]+$/g, ''); if (!self.in_array(dvsr, ['', '+', '>'])) { self.warn(selector, slctr_pos, 'Bad selector given.'); return []; } } else { dvsr = ''; } /* セレクタ・オブジェクトを作成、タグ名 or ワイルドカード (アスタリスク) を設定 */ slctr = {tag:m[1].replace('\\:', ':')}; // }}} // {{{ 属性,ID,クラス,疑似クラス,疑似要素をパース if (m[2]) { //picas_re.compile(picas_pat, 'g'); // RegExp.compile() is not implemented in Safari. picas_re = new RegExp(picas_pat, 'g'); picas_pos = 0; p = slctr_re.lastIndex - m[2].length; while (n = picas_re.exec(m[2])) { /* 全体の先頭から今回の検索開始位置へのオフセット */ o = p + picas_pos; /* 前回の検索終了位置と今回の検索開始位置の差分 */ picas_off = picas_re.lastIndex - n[0].length - picas_pos; if (picas_off != 0) { self.warn(selector, o, 'Bad selector given.'); return []; } /* 属性 */ if (n[1]) { o += 1 + n[1].length + n[2].length + 1; // '[' + attribute + operator + '"' if (!slctr.attributes) { slctr.attributes = []; } j = slctr.attributes.length; slctr.attributes[j] = {name:n[1].replace('\\:', ':')}; switch (n[2]) { case '=': slctr.attributes[j].value = n[3]; break; case '~=': slctr.attributes[j].list = n[3].split(' '); break; case '|=': if (!re.test(n[3])) { self.warn(selector, o, 'Only ' + c + ' can be used with "|=" attribute operator.'); return[]; } slctr.attributes[j].re = new RegExp('^' + n[3] + '(-|$)'); break; } /* ID,クラス,疑似クラス,疑似要素 */ /* 疑似要素は最後のセレクタにしか指定できない (そもそもこの関数では非対応) */ } else { sw: // break label switch (n[4]) { case '#': if (slctr.id) { self.warn(selector, o, 'Only 1 id is allowed.'); return []; } slctr.id = n[5]; break; case '.': if (!slctr.classes) { slctr.classes = []; } slctr.classes.push(new RegExp('\\b' + n[5] + '\\b')); break; case ':': switch (n[5]) { case 'first-child': slctr.firstChild = true; break sw; case 'last-child': slctr.lastChild = true; break sw; default: self.warn(selector, o, 'Pseudo classes/elements, excluding "(first|last)-child" are not supported.'); return []; } //break; } } /* 検索終了位置を記録 */ picas_pos = picas_re.lastIndex; } } // }}} // {{{ 要素を走査 elems = []; for (i = 0; i < roots.length; i++) { elems = elems.concat(self.scanElements(roots[i], slctr, dvsr)); } if (elems.length == 0) { return []; } roots = self.array_unique(elems); /* 検索終了位置を記録 */ slctr_pos = slctr_re.lastIndex; // }}} } // }}} // {{{ 最終チェック if (slctr_pos == 0) { self.warn(selector, 0, 'Bad selector given.'); return []; } else if (slctr_pos != selector.length) { if (selector.substring(slctr_pos, selector.length).replace(/[\t\r\n ]+$/, '') != '') { self.warn(selector, slctr_pos, 'Bad selector given.'); return []; } } // }}} return roots; } // }}} /* document.getElementsBySelector から呼び出されるユーティリティメソッド群 */ // {{{ document.getElementsBySelector.in_array() /** * 変数 v が配列 a に含まれるか確認するメソッド */ document.getElementsBySelector.in_array = function(v, a) { for (var i = 0; i < a.length; i++) { if (v == a[i]) { return true; } } return false; } // }}} // {{{ document.getElementsBySelector.array_unique() /** * 配列 a からユニークな値を取り出すメソッド */ document.getElementsBySelector.array_unique = function(a) { var A = []; for (var i = 0; i < a.length; i++) { if (!document.getElementsBySelector.in_array(a[i], A)) { A.push(a[i]); } } return A; } // }}} // {{{ document.getElementsBySelector.scanElements() /** * 要素を走査するメソッド */ document.getElementsBySelector.scanElements = function(root, slctr, dvsr) { var self = document.getElementsBySelector.scanElements; var tag = slctr.tag.toLowerCase(); var items = [], elems = []; // {{{ 対象要素の候補を取得 if (slctr.id) { var item = root.getElementById(slctr.id); if (item && self.checkTagName(item, tag)) { items.push(item); } } else if (dvsr == '+') { if (root.nextSibling && self.checkTagName(root.nextSibling, tag)) { items.push(root.nextSibling); } } else if (dvsr == '>') { for (var i = 0; i < root.childNodes.length; i++) { if (self.checkTagName(root.childNodes[i], tag)) { items.push(root.childNodes[i]); } } } else { items = root.getElementsByTagName(tag); } if (items.length == 0) { return []; } // }}} // {{{ 属性・クラスで対象要素を絞り込む for (var j = 0; j < items.length; j++) { if (slctr.attributes && !self.checkAttributes(items[j], slctr.attributes)) { continue; } if (slctr.classes && !self.checkClasses(items[j], slctr.classes)) { continue; } elems.push(items[j]); } // }}} if (!(slctr.firstChild || slctr.lastChild)) { return elems; } // {{{ 疑似クラスが指定されているとき var pseudoes = []; for (var k = 0; k < elems.length; k++) { if (!elems[k].childNodes || !elems[k].childNodes.length) { continue; } if (slctr.firstChild && slctr.lastChild) { if (!elems[k].childNodes.length != 1 || elems[k].firstChild.nodeType != 1) { continue; } pseudoes.push(elems[k].firstChild); } else if (slctr.firstChild) { if (elems[k].firstChild.nodeType != 1) { continue; } pseudoes.push(elems[k].firstChild); } else if (slctr.lastChild) { if (elems[k].lastChild.nodeType != 1) { continue; } pseudoes.push(elems[k].lastChild); } } return pseudoes; // }}} } // }}} // {{{ document.getElementsBySelector.scanElements.checkAttributes() /** * 属性をチェックするメソッド */ document.getElementsBySelector.scanElements.checkAttributes = function(elem, attrs) { var attr, val; for (var i = 0; i < attrs.length; i++) { if ((attr = elem.getAttribute(attrs[i].name)) === null) { return false; } val = attr.toString(); if (attrs[i].value) { if (attrs[i].value != val) { return false; } } else if (attrs[i].list) { if (!document.getElementsBySelector.in_array(val, attrs[i].list)) { return false; } } else if (attrs[i].re) { if (!attrs[i].re.test(val)) { return false; } } } return true; } // }}} // {{{ document.getElementsBySelector.scanElements.checkClasses() /** * クラスをチェックするメソッド */ document.getElementsBySelector.scanElements.checkClasses = function(elem, classes) { if (!elem.className) { return false; } for (var i = 0; i < classes.length; i++) { if (!classes[i].test(elem.className)) { return false; } } return true; } // }}} // {{{ document.getElementsBySelector.scanElements.checkTagName() /** * タグ名をチェックするメソッド * 本当は大文字小文字も比較したいが、ブラウザによっては DOMElement.tagName() が * タグ名を大文字で返すようなのでケースインセンシティブにする */ document.getElementsBySelector.scanElements.checkTagName = function(elem, tag) { if (!elem.nodeType || elem.nodeType != 1) { return false; } if (tag == '*' || elem.tagName.toLowerCase() == tag) { return true; } return false; } // }}} // {{{ document.getElementsBySelector.warn() /** * エラー情報を表示するメソッド */ document.getElementsBySelector.warn = function(selector, offset) { var i, errmsg = []; for (i = 2; i < arguments.length; i++) { errmsg.push(arguments[i]); } errmsg.push('The given selectors are "' + selector + '".'); errmsg.push('An error found at offset ' + offset.toString() + ', near "' + selector.substr(offset, 5) + '".'); window.alert(errmsg.join('\n')); } // }}} // {{{ Function.prototype.mapToElementsBySelector() /** * CSS2 のセレクタによって DOM Element を取得し、一つずつ * それを第一引数にとる関数に適用するメソッド * 任意の個数の追加の引数を指定することも可能 * Function オブジェクトのプロトタイプを拡張 */ Function.prototype.mapToElementsBySelector = function(selector) { var elements = document.getElementsBySelector(selector); var params = []; for (var i = 1; i < arguments.length; i++) { params.push(arguments[i]); } for (var j = 0; j < elements.length; j++) { params.unshift(elements[j]); this.apply(this, params); params.shift(); } } // }}}