© 
shamansir.wordpress.com別のutils.jsファイルにある関数のセットを紹介します-これらは、私が最も頻繁に使用する関数です。 これらはクロスブラウザになろうとし、IE6 / 7、FF2、Safari 2、および戦闘、複雑なシステム、XHTMLドキュメントでテストされています。 理論的には、他のブラウザでも動作しますが、非常に古いバージョンのブラウザでは動作しません。例外的な場合にのみブラウザ検証を使用しました。 もちろん、それらのいくつかは、インターネット上で掘り出され(通常は示されている)、開放性のために借りられており、それらのほとんどは、多くのリソースとそのアイデア(および同僚のアドバイス)から構築されており、スクリプトはさまざまな微妙な点を考慮に入れていませんが、それでもなお、綿密に調べてみると、コミュニティであることがわかります:)、まあ、かなり読みやすいです。
機能はテーマ別に分類されています。
OOP - 
JavaScriptでOOP原則を使用する機能を提供(またはエミュレーション)JSオブジェクトモデル -JS埋め込みオブジェクトの使用と拡張ブラウザー定義 - 
それが必然的に必要であるようなまれなケースで使用する座標/ポジショニング - 
座標の計算とオブジェクトの ポジショニング - 
これは非常に難しいことが多いためですDOM- ドキュメントオブジェクトモデルを操作するAJAX - 
AJAXの ヘルパー関数-このツールはしばしば適用されるためロギング - 
時にはそれなしではできない1.最初のブロックは、 
JavaScriptの 3つの
OOP原則すべてを適用(エミュレート?)できる3つの関数(2つは空)のセットです。 
AJAXPathと
AJAXPatternsによって提案されたいくつかのオプションの中で
、私はこれを選択しました。その理由は、同時のわかりやすさと実行速度の速さであり、個別に宣言されたプロパティが静的定数として認識されるように少し変更しました。
関数クラス(){}; 
Class.prototype.construct = function (){}; 
Class.extend = function (def){ 
var classDef = function (){ 
if (arguments [0]!== Class){ 
this .construct.apply( this 、arguments); 
} 
}; 
var proto = new this (クラス); 
var superClass = this .prototype; 
for ( var n in def){ 
var item = def [n]; 
if (item instanceof Function)item。$ = superClass; 
else classDef [n] = item; 
proto [n] =アイテム。 
} 
classDef.prototype = proto; 
classDef.extend = this .extend; 
return classDef; 
}; *このソースコードは、 ソースコードハイライターで強調表示されました。
2.次の関数-シンプルだがエレガント-は前のセットとの組み合わせで便利です- 
メソッドへの関数リンクを作成します :
function createMethodReference( object 、methodName){ 
return 関数 (){ 
return object [methodName] .apply( object 、arguments); 
}; 
} *このソースコードは、 ソースコードハイライターで強調表示されています。
これで、たとえば次のことができます。
var ScrollingHandler = Class.extend({ 
構成する: 
関数 (elementId){ 
this ._elementId = elementId; 
this .assignListener(); 
}、 
assignListener: 
関数 (){ 
var scrollControlElem = 
document .getElementById( this ._elementId); 
if (scrollControlElem){ 
scrollControlElem.onscroll = 
createMethodReference( this 、 "_onElementScroll" ); 
} 
}、 
_onElementScroll: 
関数 (ev){ 
ev = ev || ウィンドウ。 イベント ; 
アラート( 「スクロールを停止してください。 
既にイベントを開催しています:„ + ev); 
} 
}); 
var elmScrollHandler = new ScrollHandler( 'SomeElmId' ); *このソースコードは、 ソースコードハイライターで強調表示されました。
このクラスのオブジェクトは、指定されたIDで要素をスクロールするイベントに関連付けられ、この場合に何かを行うことができます。
JSオブジェクトモデル
3.次の関数は、すべてのプロパティを持つ
オブジェクトを
複製します。
関数 cloneObj(objToClone){ 
var clone = []; 
for (objToCloneのi){ 
clone [i] = objToClone [i]; 
} 
クローンを返します。 
} *このソースコードは、 ソースコードハイライターで強調表示されています。
使用-不可能に最も簡単な:
var cloneObj = cloneObj(objToClone); *このソースコードは、 ソースコードハイライターで強調表示されました。
4.次の機能である
オブジェクトコンバーターを使用すると、フォームのあらゆる種類の条件付き(およびそのふりをする)構造を便利に使用できます。
if (tablet.toLowerCase() in oc([ ' cialis' 、 'mevacor' 、 'zocor' ])){alert( 'I will not!')}; *このソースコードは、 ソースコードハイライターで強調表示されました。
コードは
ここから借り
ています 。
関数 oc(a){ 
var o = {}; 
for ( var i = 0; i <a.length; i ++){ 
o [a [i]] =”; 
} 
return o; 
} 
*このソースコードは、 ソースコードハイライターで強調表示されました。
例として、オブジェクトが単一のオブジェクトのセットに含まれているかどうかを最初に判断し、次に、別のオブジェクトと組み合わせて別のオブジェクトのペアのセットに含まれるかどうかを判断する必要がある状況を考えてみましょう。 特定の名前のシングルのみがパーティーに許可されている、または名前の組み合わせが許可されているリストのペアのみ許可されているとします。
関数 isPersonAllowed(maleName、femaleName){ 
var pairsAllowed = new Array([ “ John” 、 “ Yoko” ]、 
[ "Bill" 、 "Monica" ]、[ "Phil" 、 "Sue" ]、 
[ 「ジェイソン」 、 「ハリソン」 ]、[ 「アダム」 、 「イブ」 )); 
var singlesAllowed = new Array( "Michael"、 "Pete"、 "John"、 
「デイブ」、「マシュー」); 
return (femaleName 
? (ocの[maleName、femaleName](pairsAllowed)) 
:(ocのmaleName(singlesAllowed))); 
} 
アラート(isPersonAllowed(「ジャック」)); // false 
アラート(isPersonAllowed(“ Adam”)); // false 
アラート(isPersonAllowed(“ John”)); // true 
アラート(isPersonAllowed(「Phil」、「Marlo」)); // false 
アラート(isPersonAllowed(「Jason」、「Harrison」)); // true 
アラート(isPersonAllowed(「Martin」、「Luther」)); // false *このソースコードは、 ソースコードハイライターで強調表示されました。
5.最初に
ハッシュを作成できる関数は少し冗長に見えます。JavaScriptのオブジェクトは同じハッシュですが、変数の値をプロパティ/キーの名前として設定する必要がある場合があり、その後ハッシュ関数が役立ちます。 (はい、もちろん組み込みの機能がありますが、おそらくもう少し明白です-必要に応じて、便利な機能からこの機能を除外できます
関数ハッシュ() 
{ 
this .length = 0; 
this .items = new Array(); 
for ( var i = 0; i <arguments.length; i ++){ 
this .items [arguments [i] [0]] = arguments [i] [1]; 
} 
} *このソースコードは、 ソースコードハイライターで強調表示されています。
要素へのアクセスは、 
itemsプロパティを介して行われます(ところで、より重いバージョンでは
keysを追加する必要があり
keys )。
var Game = Class.extend({ 
STG_STOP:0、 
STG_START:1、 
STG_LOADING:2 
STG_MENU:3、 
STG_PROCESS:4、 
構成する: 
function (){ this ._stage = Game.STG_LOADING; }、 
getStage: 
function (){ この ._stageを返します。 } 
}); 
var stateMap = new Hash( 
[Game.STG_START、 「開始」 ]、 
[Game.STG_LOADING、 "loading" ]、 
[Game.STG_MENU、 "menu" ]、 
[Game.STG_PROCESS、 「プロセス」 ]、 
[Game.STG_STOP、 "stopping" ]); 
var someGame = new Game(); 
alert(「あなたは「+ stateMap.items [someGame.getStage()] +」stage!」にいます); *このソースコードは、 ソースコードハイライターで強調表示されました。
6.他の3つの関数は、単純化および/またはいくつかの操作をより明確にします: 
getTimeを11文字使用すると、 
現在の時間を取得するアクセスが減少します。最後の関数は、 
Numberオブジェクトのプロパティを拡張し
て 、 
NaN値で少し速くなるようにします。
関数 getTime(){ 
新しい日付を返す ()。getTime(); 
} 
関数 getTimeDelta(timeBegin、timeEnd){ 
timeEnd = timeEnd || getTime(); 
return timeEnd-timeBegin; 
} 
Number.prototype.NaN0 = function (){ return isNaN( this )? 0: これ ; } *このソースコードは、 ソースコードハイライターで強調表示されています。
ブラウザー定義
7.プロパティがブラウザの名前に従って命名された小さなオブジェクト-条件の本質。 これにより、 
ほとんどの種類のブラウザのより読みやすい(ただし、厳密ではない) 
定義が実現します 。 このオブジェクトは私が参加したプロジェクトから借りたもので、どういうわけか定着しましたが、本当の作者はまだネットワーク上のどこかにあり、コードはそれほどふさわしくなく、強くふりをすることはできません:) 。 さらに、それは確かに完全に信頼できるわけではありません(そして、一部の人はそれがまったく信頼できないと言います)が、これまでのところリストされたブラウザーでは決して失敗しませんでした:)。 この状況に慣れていない場合は、 
HowToCreateで同様のものを使用できます。 そして、私は繰り返します:私はこの定義を(たとえば、参照によって言われたように) 
「特定のバグが特定のブラウザーで既知であり、バイパスする必要がある場合のみ」使用しようとします。 また、実行速度を下げるために、このオブジェクトを1つの長い状態に簡単に再構築できます( 
リンクを参照 )。
var USER_DATA = { 
ブラウザ:{ 
KHTML:/Konqueror|KHTML/.test(navigator.userAgent)&& 
!/Apple/.test(navigator.userAgent)、 
Safari:/KHTML/.test(navigator.userAgent)&& 
/Apple/.test(navigator.userAgent)、 
Opera:!! window.opera、 
MSIE:!!(window.attachEvent &&!Window.opera)、 
Gecko:/Gecko/.test(navigator.userAgent)&& 
!/ Konqueror | KHTML / .test(navigator.userAgent) 
}、 
OS:{ 
Windows:navigator.platform.indexOf( "Win" )> -1 
Mac:navigator.platform.indexOf( "Mac" )> -1 
Linux:navigator.platform.indexOf( "Linux" )> -1 
} 
} *このソースコードは、 ソースコードハイライターで強調表示されています。
座標/位置決め
8.ユーザーの画面上の
要素の
座標を取得できる一連の関数。 文書がウィンドウに対して静的であり、スクロールバーがない場合
getPosition関数を使用する方がよい-これは高速です。 それ以外の場合、 
getAlignedPosition使用し
getAlignedPosition -スクロールバーの位置を考慮します。 ただ注意してください:要素がウィンドウの外側の上部にある場合、要素の
top値は指標となる可能性があります-マウスカーソルと同期するために高さをゼロにする必要がある場合があります。 メインスクリプトは
1つのブログから借用しており、Alignedバージョンはギミックで検索し、 
2つの 記事の情報と組み合わせた結果です( 
DOCTYPE検出されると、IEは独自の予測不可能なモードに入ります)。 また、このメソッドは、 
Drag'n'Drop マニュアルの ソースから位置を取得することと組み合わされ
ます 。 注:ここでは、ポイント
6からの
NaN0関数
が使用されます。 
NaN0機能
させるために、スクリプトに追加する必要があります(ありがとう、 
Homer )。
var IS_IE = USER_DATA [ 'Browser' ] .MSIE; 
関数 getPosition(e){ 
var left = 0; 
var top = 0; 
while (e.offsetParent){ 
left + = e.offsetLeft +(e.currentStyle? 
(parseInt(e.currentStyle.borderLeftWidth))。NaN0():0); 
top + = e.offsetTop +(e.currentStyle? 
(parseInt(e.currentStyle.borderTopWidth))。NaN0():0); 
e = e.offsetParent; 
} 
left + = e.offsetLeft +(e.currentStyle? 
(parseInt(e.currentStyle.borderLeftWidth))。NaN0():0); 
top + = e.offsetTop +(e.currentStyle? 
(parseInt(e.currentStyle.borderTopWidth))。NaN0():0); 
return {x:左、y:上}; 
} 
関数 getAlignedPosition(e){ 
var left = 0; 
var top = 0; 
while (e.offsetParent){ 
left + = e.offsetLeft +(e.currentStyle? 
(parseInt(e.currentStyle.borderLeftWidth))。NaN0():0); 
top + = e.offsetTop +(e.currentStyle? 
(parseInt(e.currentStyle.borderTopWidth))。NaN0():0); 
e = e.offsetParent; 
if (e.scrollLeft){left-= e.scrollLeft; } 
if (e.scrollTop){top-= e.scrollTop; } 
} 
var docBody = document .documentElement? 
document .documentElement: document .body; 
左+ = e.offsetLeft + 
(e.currentStyle? 
(parseInt(e.currentStyle.borderLeftWidth))。NaN0() 
:0)+ 
(IS_IE?(ParseInt(docBody.scrollLeft))。NaN0():0)-(parseInt(docBody.clientLeft))。NaN0(); 
top + = e.offsetTop + 
(e.currentStyle? 
(parseInt(e.currentStyle.borderTopWidth))。NaN0() 
:0)+ 
(IS_IE?(ParseInt(docBody.scrollTop))。NaN0():0)-(parseInt(docBody.clientTop))。NaN0(); 
return {x:左、y:上}; 
} *このソースコードは、 ソースコードハイライターで強調表示されています。
9.適切な機能を使用すれば
、マウス
カーソルの現在の
座標と、カーソル に対する要素の
オフセットを簡単に決定できます。
関数 mouseCoords(ev){ 
if (ev.pageX || ev.pageY){ 
return {x:ev.pageX、y:ev.pageY}; 
} 
var docBody = document .documentElement 
? document .documentElement 
: document .body; 
return { 
x:ev.clientX + docBody.scrollLeft-docBody.clientLeft、 
y:ev.clientY + docBody.scrollTop-docBody.clientTop 
}; 
} 
関数 getMouseOffset(target、ev、aligned){ 
ev = ev || ウィンドウ。 イベント ; 
if (aligned == null )alignment = false ; 
var docPos = alignment 
? getAlignedPosition(ターゲット) 
:getPosition(ターゲット); 
var mousePos = mouseCoords(ev); 
return { 
x:mousePos.x-docPos.x、 
y:mousePos.y-docPos.y 
}; 
} 
*このソースコードは、 ソースコードハイライターで強調表示されました。
後者の関数は、 
aligned属性により2つのモードで使用することもでき、たとえば次のようなイベントハンドラーでの便利な使用を目的としています。
関数 onMouseMove(elm、ev){ 
var mouseOffset = getMouseOffset(elm、ev); 
console.log( "x:%d; y:%d" 、mouseOffset.x、mouseOffset.y); 
} 
... 
<div id = "someId" onmousemove = "onMouseMove(this、event); 
return false; " > </ div> *このソースコードは、 ソースコードハイライターで強調表示されました。
10. エレメントの
高さを決定すること
は 、他のパラメーターを決定するよりも難しい場合
がありますが、次の2つの機能が役立ちます。
関数 findOffsetHeight(e){ 
var res = 0; 
while ((res == 0)&& e.parentNode){ 
e = e.parentNode; 
res = e.offsetHeight; 
} 
解像度を返す ; 
} 
関数 getOffsetHeight(e){ 
この .element.offsetHeight ||を返し ます 
この .element.style.pixelHeight || 
findOffsetHeight(e); 
} *このソースコードは、 ソースコードハイライターで強調表示されています。
ドム
11.場合
によっては、DOMツリーを再帰的に歩いて、いくつかの要素から始めて、各子孫で何らかの機能を実行し、非常に奥深くに登る必要があります。 
TreeWalkerには
TreeWalkerオブジェクトがあり
TreeWalkerが、IEでは機能せず、常に便利で使いやすいとは限りません。 
walkTree関数を使用
walkTreeと、各要素に対して他の機能を実行したり、データパケットを転送したりできます。 
searchTree関数は、最初の成功した結果でツリーの通過を停止し、コールポイントに結果を返すという点で、それと異なります。
関数 walkTree(ノード、mapFunction、dataPackage){ 
if (node == null ) return ; 
mapFunction(ノード、dataPackage); 
for ( var i = 0; i <node.childNodes.length; i ++){ 
walkTree(node.childNodes [i]、mapFunction、dataPackage); 
} 
} 
関数 searchTree(ノード、searchFunction、dataPackage){ 
if (node == null ) return ; 
var funcResult = searchFunction(node、dataPackage); 
if (funcResult) return funcResult; 
for ( var i = 0; i <node.childNodes.length; i ++){ 
var searchResult = searchTree(node.childNodes [i]、 
searchFunction、dataPackage); 
if (searchResult) return searchResult; 
} 
} *このソースコードは、 ソースコードハイライターで強調表示されています。
この例では、 
setElmAttrおよび
getElmAttr関数が使用されています。これについては、段落
13で後述します。 基本的に、これらは
getAttributeおよび
setAttributeと同じことを行い
setAttribute 。 使用される
oc関数の説明については、段落
4を参照してください。 この例の最初の部分では、ルート要素属性は「ルート」では「nodeType」に設定され、「子」ではそのすべての子孫に設定されています。 2番目の部分は、データパケットの送信も示しています。パッケージにリストされている名前の1つに等しい「class」属性を持つ最初の要素が見つかると、「isTarget」属性は「true」に設定されます。
var rootElement = document .getElementById( 'rootElm' ); 
setElmAttr(rootElement、 "nodeType" 、 "root" ); 
var childNodeFunc = function (node){ 
if (node.nodeName &&(node.nodeName!== '#text' ) 
&&(node.nodeName!== '#comment' )){ 
setElmAttr(node、 "nodeType" 、 "child" ); 
} 
} 
walkTree(rootElement、childNodeFunc); 
var findTargetNode = function (node、classList){ 
if ((node.nodeName &&(node.nodeName!== '#text' ) 
&&(node.nodeName!== '#comment' ))&& 
(getElmAttr(node、 "class" ) in oc(classList))){ 
戻りノード。 
} 
} 
var targetNode = searchTree(rootElement、findTargetNode、 
[ 'headingClass' 、 'footerClass' 、 'tableClass' ]); 
setElmAttr(targetNode、“ isTarget”、 true ); *このソースコードは、 ソースコードハイライターで強調表示されました。
NB! (これらの関数を使用するときは注意し、中程度のブランチツリーでも頻繁に(1秒に1回以上)呼び出されないようにしてください-多くのリソースを消費するか、少なくとも
setTimeoutを介してバックグラウンドで呼び出します)
12. ノードの削除が必要な場合があります。 ノード自体を削除する必要がある場合と、その子孫のみを削除する必要がある場合があります。 
removeChildrenRecursively関数は、もちろん、それ自体に影響を与えることなく、指定されたノードのすべての子孫を再帰的に削除します。 
removeElementById関数は、名前が示すように、その
idノードを削除します-タスクのすべての単純さのために、メソッドは比較的トリッキーです:
関数 removeChildrenRecursively(ノード) 
{ 
if (!node) return ; 
while (node.hasChildNodes()){ 
removeChildrenRecursively(node.firstChild); 
node.removeChild(node.firstChild); 
} 
} 
関数 removeElementById(nodeId){ 
document .getElementById(nodeId).parentNode.removeChild( 
document .getElementById(nodeId)); 
} 
*このソースコードは、 ソースコードハイライターで強調表示されました。
13. 要素属性を
扱う基本的なタスク-時々、まったく予期しない問題が発生することがあります。たとえば、 
table要素の高さ/幅属性にアクセスしようとするとIEが例外をスローし、Safariには名前空間の属性にアクセスする別の方法があります。 以下の関数は、実行速度に深刻な影響を与えることなく、私が遭遇したすべての問題を回避します(もちろん、標準の場合、組み込み関数を使用する方が良いです):
var IS_SAFARI = USER_DATA [ 'Browser' ] .Safari; 
関数 getElmAttr(elm、attrName、ns){ 
// IE6は、テーブル要素で使用するとgetAttributeに失敗します 
var elmValue = null ; 
{ 
elmValue =(elm.getAttribute 
? elm.getAttribute((ns?(ns + NS_SYMB):”) 
+ attrName): null ); 
} catch (e){ nullを 返す 。 } 
if (!elmValue && IS_SAFARI){ 
elmValue =(elm.getAttributeNS 
? elm.getAttributeNS(ns、attrName) 
: null ); 
} 
return elmValue; 
} 
関数 setElmAttr(elm、attrName、value、ns){ 
if (!IS_SAFARI ||!ns){ 
return (elm.setAttribute 
? elm.setAttribute((ns?(ns + NS_SYMB):”) 
+ attrName、value): null ); 
} else { 
return (elm.setAttributeNS 
? elm.setAttributeNS(ns、attrName、value) 
: null ); 
} 
} 
関数 remElmAttr(elm、attrName、ns){ 
if (!IS_SAFARI ||!ns){ 
return (elm.removeAttribute 
? elm.removeAttribute((ns?(ns + NS_SYMB):”) 
+ attrName): null ); 
} else { 
return (elm.removeAttributeNS 
? elm.removeAttributeNS(ns、attrName) 
: null ); 
} 
} *このソースコードは、 ソースコードハイライターで強調表示されています。
ロギング
14. ロギングを支援する以下の機能
は非常に簡単です。ドキュメント内の目的の場所に
<div id="LOG_DIV"></div>要素を追加し、必要な高さを設定すると、情報がダンプされ、スクロールが提供されます。
関数 LOG(informerName、text){ 
var logElement = document .getElementById( 'LOG_DIV' ); 
if (logElement){ 
logElement.appendChild( document .createTextNode( 
informerName + ':' + text)); 
logElement.appendChild( document .createElement( 'br' )); 
logElement.scrollTop + = 50; 
} 
} *このソースコードは、 ソースコードハイライターで強調表示されています。
15. Firefoxブラウザ用のすばらしい
Firebugプラグインには、幅広い機能で
ログインできるすばらしい
コンソールがあります。 ただし、他のブラウザーでコードを並行してデバッグする場合、アクセスするとエラーが発生する可能性があります。 毎回ログからコードをクリアしないようにするには、次のスタブを使用できます。
var Console = Class.extend({ 
//ブラウザーにコンソールがある場合にコンソールの使用を許可するスタブクラス、 
//そうでない場合-すべての呼び出しを渡す 
構成: 関数 (){}、 
ログ: 関数 (){}、 
情報: 関数 (){}、 
警告: 関数 (){}、 
エラー: 関数 (){} 
}); 
if (!window.console){ 
console = new Console(); 
} *このソースコードは、 ソースコードハイライターで強調表示されています。
UPD:ソースコードハイライターへのリンクを修正、ありがとう。