1

I have a partial view created for re-use purposes. This partial view has a dropdownlist which uses Chosen plugin. Therefore, on the partial view I reference the chosen js/css file along with some javascript code to for document ready.

It works as intended. However, now I have a page which I render the partial view upon a button click event. Users can click as many times as they want.

My concern is that duplicate js will load each time they click the button. This, perhaps, is the reason why people don't recommend adding js to Partial View directly. In my case, it needs to be there for the plug-in and manipulation within the Partial View itself. Is there a good way to check for loaded js and prevent it from loading it again in subsequent click event?

NKD
  • 1,039
  • 1
  • 13
  • 24
  • 1
    You can create a wrapper of your library, when it will load itself it will check if the library you need is loaded (there are probably some global variables from the library), if they are not present you will dynamically inject the script tag to your page, otherwise not – Vsevolod Goloviznin Dec 10 '14 at 20:40
  • @VsevolodGoloviznin: This is the best answer the OP is going to get. You should just go ahead and actually add it as answer. – Chris Pratt Dec 10 '14 at 21:33
  • @NKD: To implement what Vsevolod suggests look into libraries like Require.js or Modernizr's `load` functionality. – Chris Pratt Dec 10 '14 at 21:34
  • @NKD In fact I would get rid of scripts in partials and just put them into the bundle and forget about this problem at all – Vsevolod Goloviznin Dec 10 '14 at 21:55
  • @VsevolodGoloviznin I like your suggestion and was trying to implement it by putting it in a seperate js and load thing dynamically with $.getScript. Then I realize $.getScript doesn't work the way I expected it. Did some googling and it seems to be a known issue. Let me think about bundling a little bit. My burden is the plugin on the page. – NKD Dec 10 '14 at 22:13
  • @NKD check out my answer, it uses vanilla JS to load script element and shouldn't cause any problems – Vsevolod Goloviznin Dec 10 '14 at 22:28
  • @VsevolodGoloviznin Sorry, i was too focus on $.getScript problem and multi-tasking at the same time. I didn't even notice you posted the answer. I'll take a look and get back with you. Thanks again for your help. – NKD Dec 10 '14 at 22:44
  • @VsevolodGoloviznin It doesn't seem to trigger chosen properly. I even tried var len = $('script[src="~/Scripts/chosen_v1.2.0/chosen.jquery.min.js"]').length then do if(len === 0) to check for it. I also try to check the wrapper like this as well if (typeof window.partialJS == 'undefined') then $.getScript. I have to leave for the day. I will come back tomorrow to tackle this problem and post my findings if any. – NKD Dec 10 '14 at 23:03
  • @NKD what do you mean by 'trigger chosen properly'? – Vsevolod Goloviznin Dec 11 '14 at 08:32
  • @VsevolodGoloviznin Sorry for not able to get back to this yesterday. "trigger chosen properly" meant the chosen plugin does not get initialized. $(".chosen-select).chosen() seems to take no affect. My dropdown appears as a multiselect list box instead of a chosen multi-select dropdown. – NKD Dec 12 '14 at 16:56

2 Answers2

0

The JavaScript and CSS files for Chosen should be included on the page when the page first loads. When the user clicks the button, make an Ajax call to include the partial. In the success callback for the AJAX request, initialize the Chosen plugin code for the dropdown lists that were just injected in the page.

Your are correct that duplicate JS and CSS files will get loaded, which is definitely something you don't want.

$.ajax(...)
    .done(function(data) {
        $("#foo")
            .html(data)
            .find("select")
            .each(function() {
                $(this).chosen({...});
            });
    });
Greg Burghardt
  • 17,900
  • 9
  • 49
  • 92
  • thank you for the suggestion. I also have documentready code on the partial page to manipulate the chosen dropdown. If I do it this way, I would end up with a long callback function (code injected after the chosen initialization). – NKD Dec 10 '14 at 22:17
  • You don't need code injected after the callback function. This code should be run _as part of the callback function_. – Greg Burghardt Dec 11 '14 at 15:15
  • I was literately referring to code entered right after the chosen initialization line within the call back function. – NKD Dec 12 '14 at 16:53
  • it looks like your method is the only way I can get chosen to work. I guess I better off living with a long .ajax callback code than loading a bunch of references multiple times. I have one quick question tho. I have a $("select[id^='MyDropdown']").change(function () {...}); added after the $(this).chosen({..}); line. I don't understand why it doesn't work when I place it outside of the $.ajax call. – NKD Dec 12 '14 at 23:53
0

Extending my comment with the answer.

You can leave multiple css files, I don't think it will do any harm. As for JS files, at first you should create a wrapper file

wrapper.js

$(function() {
      if (!$().chosen) { //we do this only if chosen is not present
         var script = document.createElement('script');
         script.type = 'text/javascript';
         script.src = 'url to yor chosen library';

         $("body").append(script);
      }     
});

And then in your view you will reference this wrapper.js file instead of your chosen library path.

Vsevolod Goloviznin
  • 12,074
  • 1
  • 49
  • 50