1

Прошло довольно много времени с тех пор, как я много сделал с jQuery (или javascript вообще). Я пытаюсь принять наше приложение от всех методов в глобальной области, до точки, где все находится в собственном пространстве имен.Настройка прослушивателей jQuery вне глобальной области

Подход, который я принимаю, заключается в использовании гибрида шаблона раскрывающего модуля и шаблона объектного литерала.

Я использую объект буквального шаблон на каждой отдельной странице, и я использую его, чтобы просто параметры настройки, которые приходят с сервера (ASP.NET MVC Razor)

var st = st || {}; 
st.SharedContextMenuCommon = { 
    ContextMenuControllerName: '@Model.ControllerName', 
    BindingTargetName: '@Model.TargetName', 
    StratosphereGlobalImageUrl: '@Web_Helpers.StratosphereImageUrl("")' // yes this is empty since we only need the root. we can't pass a JS variable to Razor 
}; 

Отсюда, я есть внешний файл, который делает весь тяжелый подъем. В этом конкретном случае у меня есть Kendo ContextMenu, и мне нужно его инициализировать его слушателей (jQuery) изнутри вложенного пространства имен.

Если я удалю все биты пространства имен, этот код работает так, как ожидалось, однако, когда я использую шаблон раскрывающегося модуля, слушатель не запускается в событии 'click'.

var st = st || {}; 
st.SharedContextMenu = (function() { 
    // check to see if menu exists 
    var menu = $("#contextMenu"); 

    var initMenu = function() { 
     menu = $("#contextMenu").kendoContextMenu({ 
      orientation: 'vertical', 
      alignToAnchor: true, 
      filter: ".contextMenu", 
      showOn: "click", 
      animation: { 
       open: { 
        effects: "fadeIn" 
       }, 
       duration: 250 
      }, 
      select: function(e) { 
       this.close(); // close the context menu 
       var action = $(e.item).find("[data-action]").data("action"); // extract the javascript string that is to be actioned on 
       var id1 = e.target.dataset.recordid; // extract the specific record ID (typically a GUID) 
       var id2 = e.target.dataset.recordidalt; // extract the specific alt record ID (typically a GUID) 
       var func = new Function(String.format(action, id1, id2)); // format the action (if the string is a formattable) 
       return (func()); // execute the string. This is essentially like EVAL, but since this is an internal app, it should be safe. 
      } 
     }); 
    }; 

    // only init the menu if it exists. 
    if (menu) { 
     initMenu(); 
     $('#' + st.SharedContextMenuCommon.BindingTargetName).on('click', '.contextMenu', function() { 
      var recordId = $(this).data('recordid'); 
      $.getJSON(st.SharedContextMenuCommon.ContextMenuControllerName + '/?recordId=' + recordId, function(data) { 
       var contextMenu = $('#contextMenu').data('kendoContextMenu'); 
       var items = []; 
       $.each(data, function(key, value) { 
        items.push({ 
         text: '<span data-action="' + value.OnClickJavascript + '">' + value.Text + '</span>', 
         encoded: false, 
         imageUrl: st.SharedContextMenuCommon.StratosphereGlobalImageUrl + value.Image 
        }); 
       }); 

       contextMenu.setOptions({ 
        dataSource: items 
       }); 
      }); 
     }); 
    } 
})(); 

Может кто-то указать мне на кусок, который мне не хватает?

+0

Вы понимаете, что 'новая функция' на самом деле не создает функцию, которая может быть вызвана позже, она вызывает конструктор функции и сразу же запускает новую функцию. Похоже, вы должны отказаться от ключевого слова 'new'. – adeneo

+0

@adeneo, Вероятно, вы правы в обоих случаях для этого случая. В других областях, используя тот же шаблон, я возвращаю 'st' так, чтобы публичные методы могли быть вызваны. В этом случае я ничего не звоню, а просто слушаю события. 'новый function' позволяет' st.something.publicMethod() 'вместо' st.something(). publicMethod() '... снова, так как я не подвергая публичные методы, это спорный вопрос, просто предпочтение вещь. –

ответ

0

Хорошо, поэтому у меня это было почти правильно ... оказалось, что все еще нужно вложить в готовый вызов документа.

"USE STRICT"; 

var st = st || {}; 
$(document).ready(function() { 
    setTimeout(function() { 
     st.SharedContextMenu = (function() { 
      // check to see if menu exists 
      var menu = $("#stratosphereContextMenu"); 

      var onMenuItemSelected = function (e) { 
       this.close(); // close the context menu 
       var action = $(e.item).find("[data-action]").data("action"); // extract the javascript string that is to be actioned on 
       var id1 = e.target.dataset.recordid; // extract the specific record ID (typically a GUID) 
       var id2 = e.target.dataset.recordidalt; // extract the specific alt record ID (typically a GUID) 
       var func = new Function(String.format(action, id1, id2)); // format the action (if the string is a formattable) 
       return (func()); // execute the string. This is essentially like EVAL, but since this is an internal app, it should be safe. 
      }; 

      var initMenu = function() { 
       menu = $("#stratosphereContextMenu").kendoContextMenu({ 
        orientation: 'vertical', 
        alignToAnchor: true, 
        filter: ".contextMenu", 
        showOn: "click", 
        animation: { 
         open: { 
          effects: "fadeIn" 
         }, 
         duration: 250 
        }, 
        select: onMenuItemSelected 
       }); 
      }; 

      // only init the menu if it exists. 
      if (menu) { 
       initMenu(); 
       $('#' + st.SharedContextMenuCommon.BindingTargetName).on('click', '.contextMenu', function() { 
        var recordId = $(this).data('recordid'); 
        $.getJSON(st.SharedContextMenuCommon.ContextMenuControllerName + '/?recordId=' + recordId, function (data) { 
         var contextMenu = $('#stratosphereContextMenu').data('kendoContextMenu'); 
         var items = []; 
         $.each(data, function (key, value) { 
          items.push({ 
           text: '<span data-action="' + value.OnClickJavascript + '">' + value.Text + '</span>', 
           encoded: false, 
           imageUrl: st.SharedContextMenuCommon.StratosphereGlobalImageUrl + value.Image 
          }); 
         }); 

         contextMenu.setOptions({ 
          dataSource: items 
         }); 
        }); 
       }); 
      } 
     })(); 
    }, 0); 
}); 
Смежные вопросы