16種類の本当に便利なJavaScriptソリューション

© 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つは空)のセットです。 AJAXPathAJAXPatternsによって提案されたいくつかのオプションの中で私はこれを選択しました。その理由は、同時のわかりやすさと実行速度の速さであり、個別に宣言されたプロパティが静的定数として認識されるように少し変更しました。

関数クラス(){};



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;



forvar 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 = {};

forvar 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();

forvar 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 == nullreturn ;

mapFunction(ノード、dataPackage);

forvar i = 0; i <node.childNodes.length; i ++){

walkTree(node.childNodes [i]、mapFunction、dataPackage);

}

}



関数 searchTree(ノード、searchFunction、dataPackage){

if (node == nullreturn ;

var funcResult = searchFunction(node、dataPackage);

if (funcResult) return funcResult;

forvar 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:ソースコードハイライターへのリンクを修正、ありがとう。



All Articles