Help modularizing DRY code. OOP?

Hi all,

Been learning a lot over the past weeks, thanks to all the help I’ve received in the forums here :nerd:

I’ve come to the stage that I’ve built a lot of functions and AJAX/getJSON requests — which seem to be doing a lot of the same things.

DRY is certainly visible.

Hoping to build a couple of modules or some sort of javascript object(s) I can use and simply pass some variables/parameters. Take things to the next level :smile:

Ok, starting with an example.

I have a number of the same click events, the only thing that will change is the selector:

$(document).on('click', '#results .single', function(e){
	
});
$(document).on('click', '.more', function(e){
	
});
$(document).on('click', '#results .change', function(e){
	
});
$(document).on('click', '.home', function(e){
	
});

Is this a good time to build a useable function?

And within these click events, amongst other things I have either a single AJAX request, or getJSON files with promise.

getJSON example
I have at least four of the below which use nearly identical code, beside the url and template the code is the same which is becoming extremely busy.

$(document).on('click', '.more', function(e){

//...

// getJSON
// This set up calls two json files, one after the other
$.getJSON(urlOne, function(data) {
    $.extend(data, funcs);
    var template = $('#tplOne').html();
    var html = Mustache.render(template, data, partials);
    $("#resultsOne").html(html);
  })
  .then(
$.getJSON(urlTwo, function(data) {
    $.extend(data, funcs);
    var template = $('#tplTwo').html();
    var html = Mustache.render(template, data);
    $('#resultsTwo').html(html);
    
    //... Will need to add extra variables and stuff here in some instances.
    
  }));

});

Ideally, wondering best way/how to build a reusable click event function, and a getJSON function I can add into this click event, or build one big useable function :thinking:

Great to hear advice or examples of best way of doing this.

Thnaks.
Barry

Is this what you’re looking for?

$(document).on('click', '#results .single', doStuff)
$(document).on('click', '.more', doStuff)
$(document).on('click', '#results .change', doStuff)
$(document).on('click', '.home', doStuff)

function doStuff(e) {
  e.preventDefault()
  console.log('stuff')
}

Since you’re setting the results to different elements on the page, I don’t see any reason to synchronously call those json endpoints.

getStuff(urlOne, $('#tplOne'), $('#resultsOne')).then(console.log('done'))
getStuff(urlTwo, $('#tplTwo'), $('#resultsTwo')).then(console.log('done'))

function getStuff(url, $template, $elm) {
  return $.getJSON(url, function(data) {
    $.extend(data, funcs);
    var template = $template.html();
    var html = Mustache.render(template, data, partials);
    $elm.html(html);
  })
}

Also, this isn’t OOP. It’s just functions. JavaScript isn’t inherently OOP and takes a good bit of work to make it act like OOP. Even class in ES6 isn’t really OOP, but it’s a step closer. JS isn’t functional either, but it tends to lend itself better to those concepts.

If you’re working in JS, just ditch the notion of OOP. It’s not worth the hassle of trying to code JS like Java or C# when it’s not OOP. But, feel free to include pieces of OOP or functional programming where you feel it’s necessary. JS is a multi-paradigm language.

3 Likes

Update

Just seen your post, removed my last comment.
Reading your latest post now, cheers.

And the AJAX snippet:

// AJAX
// This setup fetches the json file, then populates the template
var result = $.ajax({
  dataType: 'jsonp',
  url: urlOne,
  async: false
});
result.done(function(data) {
  $.extend(data, funcs);
  var template = $(queryTpl).html();
  var html = Mustache.render(template, data, partials);
  $('#results').html(html);
  
  //... Will need to add extra variables and stuff here

});

I’m using the above setup in conjunction with the getJSON, in different instance on the same page. Sometimes I only need to make one call, other times I need two calls — as displayed in the first getJSON example.

Barry

I think I understand.

How things generally work, think SPA.
On page load I fetch a json result and display it inside a template.
Then it’s up to the user to fire the click events which fetch a new dataset and replace the template existing data.

In some instances I need the first getJSON to finish so I can get the ID which is needed to successful run the second (.then) getJSON if the user wants to read more information about a single item.

I might need to rethink some of this.

Yes, thanks for clarifying, getting a little head of myself :slight_smile:

And what do you think about the AJAX example?

Barry

One way to find your way to a successful outcome is to name the anonymous functions.

$.getJSON(urlOne, function templateOne(data) {
    $.extend(data, funcs);
    var template = $('#tplOne').html();
    var html = Mustache.render(template, data, partials);
    $("#resultsOne").html(html);
  })
  .then(
$.getJSON(urlTwo, function templateTwo(data) {
    $.extend(data, funcs);
    var template = $('#tplTwo').html();
    var html = Mustache.render(template, data);
    $('#resultsTwo').html(html);
});

For then you can extract those functions out:

function templateOne(data) {
    $.extend(data, funcs);
    var template = $('#tplOne').html();
    var html = Mustache.render(template, data, partials);
    $("#resultsOne").html(html);
}
function templateTwo(data) {
    $.extend(data, funcs);
    var template = $('#tplTwo').html();
    var html = Mustache.render(template, data);
    $('#resultsTwo').html(html);
}
$.getJSON(urlOne, templateOne)
  .then(
$.getJSON(urlTwo, templateTwo);

and then create a generic function that does the same job:

function renderTemplate(data, templateSource, target, partials) {
    $.extend(data, funcs);
    var template = $(templateSource).html();
    var html = Mustache.render(template, data, partials);
    $(target).html(html);
}
function templateOne(data) {
    renderTemplate(data, '#tplOne', '#resultsOne', partials);
}
function templateTwo(data) {
    renderTemplate(data, '#tplTwo', '#resultsTwo', {});
}
$.getJSON(urlOne, templateOne)
  .then(
$.getJSON(urlTwo, templateTwo);

From there, the different information for each template is easily visible now, and can be moved in to a data structure to help keep everything organised.

var templates = [
    {url: urlOne, source: '#tplOne', target: '#resultsOne', partials: partials},
    {url: urlTwo, source: '#tplTwo', target: '#resultsTwo', partials: {}}
]
function renderTemplate(data, templateSource, target, partials) {
    $.extend(data, funcs);
    var template = $(templateSource).html();
    var html = Mustache.render(template, data, partials);
    $(target).html(html);
}
function useTemplate(index) {
    return function (data) {
        var tplInfo = templates[index];
        renderTemplate(data, tplInfo.source, tplInfo.target, tplInfo.partials);
    }
}
$.getJSON(urlOne, useTemplate(0))
  .then(
$.getJSON(urlTwo, useTemplate(1));
2 Likes

Thanks a lot @Paul_Wilkins

Great examples cheers, just what I’m after :grinning:

I’ll need to digest this now and run some tests, see if I can refactor my original code and get things up and running.

Will post back once. I’m sure I’ll have a couple of questions :nerd:

Barry

Here’s some good details on the very common steps used to extract a function.

The technique used is called refactoring, and there is a good free book about refactoring JavaScript at https://www.safaribooksonline.com/library/view/refactoring-javascript/9781491964910/ch01.html

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.