Question

I'm slowly getting a better understanding of JavaScript but I'm stuck on how best to tackle this particular organization/execution scenario.

I come from a C# background and am used to working with namespaces so I've been reading up on how to achieve this with JavaScript. I've taken what was already starting to become a large JavaScript file and split it out into more logical parts.

I've decided on a single file per page for page specific JavaScript with anything common to two or more pages, like reusable utility functions, in another namespace and file.

This makes sense to me at the moment and seems to be a popular choice, at least during the development process. I'm going to use a bundling tool to combine these disparate files for deployment to production anyway so anything that makes development more logical and easier to find code the better.

As a result of my inexperience in dealing with lots of custom JavaScript I had a function defined in the common JavaScript file like this:

common.js

$(document).ready(function () {
    var historyUrl = '/history/GetHistory/';
    $.getJSON(historyUrl, null, function (data) {
        $.each(data, function (index, d) {
            $('#history-list').append('<li>' + d.Text + '</li>');
        });
    });
});

This is obviously far from ideal as it is specific to a single page in the application but was being executed on every page request which is utterly pointless and insanely inefficient if not outright stupid. So that led me to start reading up on namespaces first.

After a bit of a read I have now moved this to a page specific file and re-written it like this:

Moved from common.js to historyPage.js

(function(historyPage, $, undefined) {

    historyPage.GetHistory = function () {
        var historyUrl = '/history/GetHistory/';
        $.getJSON(historyUrl, null, function (data) {
            $.each(data, function (index, d) {
                $('#history-list').append('<li>' + d.Text + '</li>');
            });
        });
    };
    }( window.historyPage = window.historyPage || {}, jQuery ));

I found this pattern on the jQuery Enterprise page. I'm not going to pretend to fully understand it yet but it seems to be a very popular and the most flexible way of organizing and executing JavaScript with various different scopes whist keeping things out of the global scope.

However what I'm now struggling with is how to properly make use of this pattern from an execution point of view. I'm also trying to keep any JavaScript out of my HTML Razor views and work in an unobtrusive way.

So how would I now call the historyPage.GetHistory function only when it should actually execute ie: only when a user navigates to the History page on the web site and the results of the function are required?

Was it helpful?

Solution 2

Using the code I have detailed above in the question I have gotten it working by doing the following:

In _Layout.cshtml

    @if (IsSectionDefined("History"))
    {
      <script type="text/javascript">
          $(document).ready(function () {
            @RenderSection("History", required: false)
        });
      </script>
    }

In History.cshtml

@section History
{
  historyPage.GetHistory();
}

The code is executing as required only when the user requests the History page on the web site. Although the comment from @Dagg Nabbit above has thrown me a curve ball in that I thought I was on the right track ... Hmm ...

OTHER TIPS

From looking at the code, it would seem that the easiest test would be to check if the page you are on contains an element with an id of history-list. Something like this:

var $histList = $('#history-list');

if($histList.length > 0){
    // EXECUTE THE CODE
}

Though if it really only ever needs to run on one given page, maybe it's just not a good candidate for a shared javascript file.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top