1

WebアプリでhtmlイベントハンドラーとjQueryイベントハンドラーを分離しようとしています。これが私のコンテキストです:私のウェブアプリは、ajaxがロードされたコンテンツを持つタブで動作します。各タブのコンテンツは、一意のIDで識別されます。各タブにテーブルがあります。2つ以上のタブのコンテンツを同じにすることができます(たとえば、Chromeのように、同じWebサイトを2つのタブにロードできます)。タブでは、jQueryで初期化されたボタンをクリックして各テーブル行を編集できます。

これが現在どのように機能するかの簡単な例です:

SMARTYテンプレート

<div id="tabContent_{$uniqueId}">
  <table>
    {foreach $operations as $op}
       <tr><td><button id="buttonEditOperation_${op}" /></td></tr>
    {/foreach}
  </table>
</div>

<script>           
     $('#tabContent_{$uniqueId} [id^="buttonEditOperation_"]')
       .click( function() { alert('CLICK !'); })
       .button(blabla);
</script>

#tabContent_{$uniqueId}同じコンテンツで新しいタブをロードすると、セレクターが原因で、この新しいコンテンツのボタンのみが初期化されます

JSとSMARTYTEMPLATEを分離するJavaScriptファイルを作成したいのですが、新しくロードされたタブのコンテンツのみを選択する方法がわかりません。私はこのようなものが欲しいです:

SMARTYテンプレート

<script type="text/javascript" src="./js/buttonInit.js"></script>
<div id="tabContent_{$uniqueId}">
  <table>
     {foreach $operations as $op}
       <tr><td><button id="buttonEditOperation_${op}" /></td></tr>
    {/foreach}
  </table>
</div>

JSファイル

<script> 
     $('#tabContent_?????? [id^="buttonEditOperation_"]')  // HERE IS MY PROBLEM
       .click( function() { alert('CLICK !'); })
       .button(blabla);
</script>

いくつかのアイデア(HTML5データプロパティ、初期化関数、グローバル変数など)がありますが、この問題の最善の解決策を知りたいです。

ご意見ありがとうございます !

4

2 に答える 2

0

HTMLとJavascriptを分離することは良い考えですが、Javascriptファイルを生成することは、これを達成するのにやり過ぎであり、また、本来あるべきよりも維持するのが非常に難しいかもしれません。

私が見つけた最善の方法は、Smartyに単純なプラグイン関数を追加して、サイト全体に何度も表示される「ウィジェット」に関連付けられたすべてのHTMLおよびJavascriptを生成できるようにすることです。

これらのプラグイン関数は次のようにする必要があります。

  • ウィジェットのすべてのHTMLを生成して、異なるSmartyテンプレート間でHTMLを繰り返す必要がないようにします。
  • ウィジェットに必要なすべてのJavascriptを生成して、SmartyテンプレートでJavascriptを記述する必要がないようにします(これはほとんどの場合悪い考えです。関数を呼び出すだけです)。
  • Javascriptの生成をページでの実際の出力から分離し、Javascriptが実際に配置される場所を制御できるようにします。

Smartyに関数を追加するためのPHPコード

$GLOBALS['pageJavascript'] = array();

$smarty->registerPlugin("function", "addButton", "addButtonSmarty");
$smarty->registerPlugin("function", "displayPageJavascript", "displayPageJavascript");

//Outputs the HTML for a button, generates the associated Javascript and either 
//outputs that Javascript or saves it for later.
function    addButtonSmarty($params, &$smarty){

    if(isset($params['operation']) == FALSE){
        return "operation not set.";
    }

    if(isset($params['tabID']) == FALSE){
        return "tabID not set.";
    }

    $tabID = $params['tabID']
    $operation = $params['operation'];

    $uniqueID = "buttonEditOperation_".$operation;


    addButtonJavascript($tabID, $operation);

    echo "<button id='buttonEditOperation_".$operation."' />";
}

function addButtonJavascript($tabID, $operation){

    $javascript = "
        $('#tabContent_".$tabID." [id^=\"buttonEditOperation_".$operation."\"]')
        .click( function() { alert('CLICK !'); })
        .button(blabla);";

    if(FALSE){
    //You can just add the Javascript directly to the web page, however in this case
    //it may throw an error if the user clicks on something before jQuery is
    //fully loaded.
        echo "<script type="text/javascript">";
        echo $javascript;
        echo "</script>";
    }
    else{
        //Much better is to save the Javascript to be included later.
        $GLOBALS['pageJavascript'][] = $javascript;
    }
}

function    displayPageJavascript(){

    echo "<script type="text/javascript">";
    foreach($GLOBALS['pageJavascript'] as $pageJavascript){
        echo $pageJavascript;
        echo "\n";
    }

    echo "</script>";

}

ボタンを直接追加するのではなく、追加する場合は常に、次のようにします。{addButton tabID = $ uniqueId operation = $ op}

したがって、Smartyテンプレートは次のようになります。

Smartyテンプレート

<script type="text/javascript" src="./js/buttonInit.js"></script>
<div id="tabContent_{$uniqueId}">
  <table>
     {foreach $operations as $op}
       <tr><td>{addButton tabID=$uniqueId operation=$op}</td></tr>
    {/foreach}
  </table>
</div>

...
...
...
<!-- bottom of smarty template -->
{displayPageJavascript}

誰かが飛び込んで、PHPでHTMLとJavascriptを書くのは醜いので、やるべきではないと言う前に、私は完全に同意します!

ただし、この場合、Smartyでプラグインとしてウィジェットを作成することの利点は、醜さを上回ります。

  • これにより、ウィジェットを操作するためのJavascriptがウィジェットのHTMLの数行以内に収まるようになります。これにより、ウィジェットを個別のファイルに配置する場合に比べて、ウィジェットの作成とデバッグがはるかに簡単になります。
  • ウィジェットの実装をSmartテンプレートから非表示にすることは、その実装を1か所で一度変更できることを意味し、そのウィジェットのすべての使用が更新されることを確認します。
  • テンプレート編集者が追加するウィジェットにJavascriptを個別に追加することを覚えておく必要がないため、コードの信頼性が大幅に向上します。そのため、テンプレートの編集でのミスが大幅に少なくなります。
于 2013-01-24T03:19:27.630 に答える
0

私が見つけた最良の解決策を以下に示します!私が何か間違ったことをしているのかどうか私に言うことを躊躇しないでください...

SMARTYテンプレート

<script type="text/javascript" src="./js/object.Module.js"></script>
<script type="text/javascript" src="./js/object.Operation.js"></script>
<div id="tabContent_{$uniqueId}">
  <table>
     {foreach $operations as $op}
       <tr><td>
          <button id="buttonEditOperation_${op}" />
          <span class="tooltip" title="Tooltip content">Show tooltip</span>
       </td></tr>
    {/foreach}
  </table>
</div>

<script>
    // Create a new object "Operation" which inherit from "Module"
    var currentModule_{$uniqueId} = new Operation( {$uniqueId} );

    // Use a method from main object "Module"
    currentModule_{$uniqueId}.init_tooltips();

    // Use a method from specific object "Operation"
    currentModule_{$uniqueId}.init_buttonEditOperation('CLICK !');
</script>

メインJSファイル: "object.Module.js"

var Module = function(_uniqueId) {
    // Store the value of this in a different variable because jQuery
    // override it when handling events
    // (http://stackoverflow.com/questions/10596727/this-keyword-overriden-in-javascript-class-when-handling-jquery-events)
    var self = this;


    /* ========================================= */
    /* PRIVATE ATTRIBUTE */   
    /* ========================================= */
    // Initialized w/ arguments values when creating "object"
    // (e.g. : var myVar = new Module("35d98q452e");
    self.uniqueId = _uniqueId; // e.g. : "35d98q452e"


    /* ========================================= */
    /* PUBLIC METHODS */   
    /* ========================================= */    
    /*-------------------------------------
    /* ---> Initialize tooltips */
    self.constructor.prototype.init_tooltips = function() {
         $( "#tabContent_" + self.uniqueId + " .tooltip" ).each(function(index) {
            $(this).tooltip();
        }); 
    }

};

モジュール「操作」固有のJSファイル「object.Operation.js」

var Operation = function(_uniqueId) {
    var self = this;

    /* ========================================= */
    /* INHERIT FROM PARENT OBJECT "Module" */   
    /* ========================================= */
    Module.call(self, _uniqueId);


    /* ========================================= */
    /* PUBLIC METHODS */   
    /* ========================================= */ 
    /*-------------------------------------
    /* ---> Initialize button "Edit operation" */
    self.init_buttonEditOperation = function(_msg) {
       $('#tabContent_' + self.uniqueId + ' [id^="buttonEditOperation_"]')
         .click( function() { alert(_msg); })
         .button(blabla);
    }
};
于 2013-03-04T12:45:15.037 に答える