呼び出される度にクロージャを作るのは効率悪いよね、ってことでリファクタリング。
この変更で
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();
}
}
// }}}