Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 6 of 6
  1. #1
    New Coder
    Join Date
    Jan 2013
    Posts
    10
    Thanks
    3
    Thanked 1 Time in 1 Post

    Loading Javascript Modules through Ajax

    Disclaimer, I posted this here, but was told it wasn't the place since it was more of a question of approach than non-working code. In hindsight I agree, SO isn't really the place for discussing things.

    Apologies for the long post, I've tried to only include the relevant bits and the code works, I'm just looking for a better/more accepted method.

    I'm really just beginning in Javascript, and despite much googling I can't find the preferred method of doing what I'm attempting to do.

    I'm creating a desktop style web page which will have a lot of small self contained applications that I want to load in as required through Ajax. Some of these may take a while to load, so I don't want to load them all at once and many of them will not be required for all users. I'm also trying to limit the scope of the variables since a lot of the "widgets" will use the same libraries so I'm trying to create self contained javascript modules (keeping them separate to make them easier to work on in isolation) that "plug in" to the desktop module. I'm currently using a model like the below (simplified) and to be honest, I'm not really sure whether I'm committing some fundamental errors since I've never used js in this way before.

    I've used this as the base of what I'm doing: http://sonspring.com/journal/jquery-desktop

    I've got a main page that lays out the desktop environment, each widget will be called by clicking on a link like this:
    PHP Code:
        <class="abs icon ui-draggable active" style="left:20px;top:100px;" href="#icon_dock_admin" rel="targets">
              <
    img src="/images/desktop/icons/icon_32_drive.png">
              
    Targets
        
    </a
    Which chains to (in the taskbar):
    PHP Code:
          <li id="icon_dock_targets">
            <
    a href="#window_targets">
                  <
    img src="/images/desktop/icons/icon_22_admin.png">
                  
    Admin
           
    </a>
          </
    li
    The base js looks something like:
    PHP Code:
        var DSK = (function($, windowundefined) {
          return {
            
    go: function() {
              for (var 
    i in DSK.init) {
                
    DSK.init[i]();
              }
            },
            
    init: {
                
    desktop: {
                 var 
    = $(document);
                 
    d.on('dblclick''a.icon', function() {
                  
    // Get the target.
                  
    var winsrc = $(this).attr('rel');
                  
    //check rel exists
                  
    if(typeof winsrc !== 'undefined' && winsrc !== false) {
                  
                      var 
    = $(this).attr('href');
                      var 
    = $(x).find('a').attr('href');
        
                      
    // Load the window if it doesn't exist in the page.
                      
    if($(y).length==0) {
                         $.
    get('/'+winsrc, function(data) {
                           $(
    "#desktop").append(data);
                           
    DSK.apps[winsrc].go();
                         });
                      } else { 
                        
    //show window
                      
    }
                } else {
                    
    alert('application not found');
                }});
                }
            },
            
    apps: {}    
          }
        })(
    jQuerythisthis.document); 
    The page (widget) that it calls is structured like this:
    PHP Code:
        <div id="window_targets" class="abs window">
          
    //some stuff
        
    </div>
        <
    script src="/js/desktopApps/targets.js"></script> 
    The js for each widget is structured like this:

    PHP Code:
        DSK.apps.targets = (function($, undefined) {
          return {
            
    go: function() {
              var 
    tgts DSK.apps.targets;
              for (var 
    i in tgts.init) {
                
    tgts.init[i]();
              }
            },
            
    init: {
                
    //Loading code
                
    logIt: function() {
                    
    //some code
                
    }
            }
          }
        })(
    jQuerythis); 
    All the code works and works for multiple widgets, but I'm thinking there's probably a better way of doing all this. So are there any major issues with my approach? and are there any frameworks/guidelines out there on how to load self contained js widgets into and existing page? The widgets will have a lot of html in them, so it's useful to be able to edit this directly rather than import the whole lot as javascript, it's also generated by PHP - I'm using codeigniter.

    Any advice/pointers would be very much appreciated, thanks in advance.

  • #2
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,296
    Thanks
    10
    Thanked 583 Times in 564 Posts
    it's a neat idea, but it seems a bit complicated to me.
    i have some bones about the markup:
    i prefer data-attribs to trying to re-jigger existing attribs.
    inline styles are harder to maintain and adjust than CSS.
    the init routines look a little too boilerplate-heavy to me.

    But, don't think that i am typical at all.
    If it works for you and you can build and expand it, go for it.


    a widgets is typically a combo of html, css, and js, not just JS.
    you CAN use pure JS to build the widgets ui, but it would be a lot more code and harder to maintain than adding behavior to pre-styled HTML chunks.

    if you don't need firefox compat, you can store raw html and css in a function's comment block. this lets you keep all three formats in one place and without escaping. Still, most people need firefox, so it gets complicated, and there's no "right" way".

    one the one hand, you want all code unescaped for long-term maintenance, greater readability, and text editor suggestions. These assets are usually store together by type, in folders such as /css/ and /js/... On the other hand, you don't want to have to create several files, especially in several different places, each time you add a widget.

    Lastly, you don't want to repeat yourself and make each widget a lot heavier than it needs to be. For example, Tabs and Accordions are 90% the same thing, just some behavior adjustments and some different css. It would be nice to be able to add capabilities like "between visit selection persistence" to both widgets from one place. If you had ten widgets in 38 different files, that simple upgrade can be a real chore...

    i don't have a perfect solution for you. i would try to build two or three master scripts that provide a framework for making the widgets i need. I think this is how YUI works.

    you may want to look into newer copies of dojo: they have a lot of self-contained interaction widgets, and they are now famous for self-loading self-contained widget architecture. I must warn you that AMD modules are probably going to make your head spin at this point; they still give me headaches.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • Users who have thanked rnd me for this post:

    Kyle123 (01-13-2013)

  • #3
    New Coder
    Join Date
    Jan 2013
    Posts
    10
    Thanks
    3
    Thanked 1 Time in 1 Post
    Thanks, that's really useful input.

    I hadn't considered data-attribs, makes sense to convert those and stop abusing the rel tag

    I'm not sure entirely what you mean by boilerplate heavy, do you mean that it adds spurious code that isn't really needed/too formulaic?

    I get your point on inline styles, but I'm not too concerned about them since they're only to initially lay out the "icons" on the desktop, then they're all draggable.

    Thanks for the pointers on Dojo and YUI, I'll check them out. I'm intrigued with the approach of putting css and html in the comment block, what would this look like? I don't need FireFox compat since it'll be used in an intranet environment.

    As for repeating code, I was getting round this by including common libraries in the desktop page at load, so they'll always be there, Jquery, Jquery UI and datatables to now.

    Thanks again for your help

  • #4
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,296
    Thanks
    10
    Thanked 583 Times in 564 Posts
    Quote Originally Posted by Kyle123 View Post
    I'm not sure entirely what you mean by boilerplate heavy, do you mean that it adds spurious code that isn't really needed/too formulaic?
    the js for each widget. you should be able to move the loop to some base file, and you don't need the anon function wrapping it all. also, imho, a widget file should include a bit of meta about itself, like name, filename, lastupdate, copyright, short description, etc. trust me, when you look at a file in 18 months, you'll be glad it's there. That meta can replace the loop and anon for a non-weight-adding swap that leaves a better module behind.




    Quote Originally Posted by Kyle123 View Post
    Thanks for the pointers on Dojo and YUI, I'll check them out. I'm intrigued with the approach of putting css and html in the comment block, what would this look like? I don't need FireFox compat since it'll be used in an intranet environment.
    functions can be viewed as thier source code using their toString() method. except for firefox, this source view includes code comments.
    as long as your css or html does not contain "*/", you can store it safely in a comment. all you need to do is grab the function's string, split it at the comments, and bingo: multi-line unquoted or escaped text.


    i've been doing this sort of thing for at least five years, and it's even better on mobile than it was for desktops, thanks to webkit being king. the code in that linked post is ancient, don't use it (E4X is dead in FF now/next ver). it was from a time when there were really only two browsers: blue and orange...

    anyway, here is a copy/demo of the ripper i use for single-block markup functions:

    Code:
    function rating1(){/*
    
    <fieldset class="fieldset">
    	<legend>Rate Thread</legend>
    	<div style="padding:3px">
    		<div>If you like, you can add a score for this thread.</div>
    		<div>
    			<select name="rating" tabindex="1">
    				<option value="0">Choose a rating</option>
    				<optgroup label="&nbsp;">
    					<option value="5">5 : Excellent</option>
    					<option value="4">4 : Good</option>
    					<option value="3">3 : Average</option>
    					<option value="2">2 : Bad</option>
    					<option value="1">1 : Terrible</option>
    				</optgroup>
    			</select>
    		</div>
    	</div>
    </fieldset>
    
    */}
    
    
    
    //unpacks a single commented block in a template function:
    Function.prototype.rip=function(){
      return String(this).split("*/")[0].split("/*")[1];
    }
    
    
    
    //example of using ripper:
    alert(  rating1.rip()  ) //shows HTML above without JS wrappings...
    Last edited by rnd me; 01-14-2013 at 09:59 AM.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • Users who have thanked rnd me for this post:

    Kyle123 (01-15-2013)

  • #5
    New Coder
    Join Date
    Jan 2013
    Posts
    10
    Thanks
    3
    Thanked 1 Time in 1 Post
    Sorry for my delayed response, I can see how that's useful.

    Yes, I can move the loop for the widget into a base file and I hear you on the meta - It's something I'm a big advocate of in other coding projects.

    Thanks again for your help

  • #6
    New Coder
    Join Date
    Jan 2013
    Posts
    10
    Thanks
    3
    Thanked 1 Time in 1 Post
    IF anyone's interested in a similar project, I found that the most efficient/neatest way of doing this is through a module loading library. I've used requirejs, the basic method is:

    A main loading module that handles all the desktop set up and handles the loading of additional modules. Standalone js modules are then called as required and added to the desktop, these are pure js/jquery modules containing no html. Each of them contain a url to the html for the "widget" which is called by the main desktop js.

    This approach has allowed a lot of flexibility, where the widget html content needs to be rendered by the server the page is called via ajax, otherwise the js in the widget builds the html.

    requireJS has also reduced initial loading times since there's no requirement to load js libraries that aren't linked to widgets just in-case the user wants to use them


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •