No-framework JavaScript

Matchstick structure

Recently I’ve been stripping out jQuery and Vue from a page I’d been working on. Frameworks can be really useful, but when not utilised fully it’s worth asking whether importing an entire library or framework is necessary. In this post, I’ll share some basic ideas using native vanilla JavaScript.

var getJsonpResponse = function(url, params, callback, appender = document.querySelector('head')) {

// Create <script> object
var script = document.createElement('script');

// build the url with params
script.src = (function(url, params = {}) {

// e.g. params.callback=jsonpcallback_hjhz7
if (typeof params.callback === "undefined") params.callback = "jsonpcallback_" + Math.random().toString(36).substring(7);

// generate param string e.g. n1=v1&n2=v2
var paramString = Object.keys(params).map((key) => {
return key + '=' + encodeURIComponent(params[key]);
}).join('&');

// affix urlParams string on the end of url
if (paramString) {
if (url.indexOf("?") > 0) { // contains ?
let reversed = url.split("").reverse().join("");
if (url.indexOf("?") === 0 || url.indexOf("&") === 0) {
url += paramString;
} else {
url += "&" + paramString;
}
} else {
url += "?" + paramString;
}
}

return url;

})(url, params);

// handler callback
window[params.callback] = function(data) {

// developer defined callback
callback(data);

// tidy up!
// allow the function to be garbage collected, tidy up window, and
// remove the script from the dom
window[params.callback] = null && delete window[params.callback];
script.parentNode.removeChild(script);
};

// append the script to run it
appender.appendChild(script);

};

Making JSONP requests

I find JSONP really useful when querying APIs to get around CORS issues. CORS provides important protection against Cross-Site Request Forgery attacks and depending on how sensitive your data is, you might not want to permit cross domain access to API resources. However, there are times when fetching non-sensitive data that it can be a pain.

Below is a function I wrote to handle JSONP API requests:

var getJsonpResponse = function(url, params, callback, appender = document.querySelector('head')) {

// Create <script> object
var script = document.createElement('script');

// build the url with params
script.src = (function(url, params = {}) {

// e.g. params.callback=jsonpcallback_hjhz7
if (typeof params.callback === "undefined") params.callback = "jsonpcallback_" + Math.random().toString(36).substring(7);

// generate param string e.g. n1=v1&n2=v2
var paramString = Object.keys(params).map((key) => {
return key + '=' + encodeURIComponent(params[key]);
}).join('&');

// affix urlParams string on the end of url
if (paramString) {
if (url.indexOf("?") > 0) { // contains ?
let reversed = url.split("").reverse().join("");
if (url.indexOf("?") === 0 || url.indexOf("&") === 0) {
url += paramString;
} else {
url += "&" + paramString;
}
} else {
url += "?" + paramString;
}
}

return url;

})(url, params);

// handler callback
window[params.callback] = function(data) {

// developer defined callback
callback(data);

// tidy up!
// allow the function to be garbage collected, tidy up window, and
// remove the script from the dom
window[params.callback] = null && delete window[params.callback];
script.parentNode.removeChild(script);
};

// append the script to run it
appender.appendChild(script);

};

State management and updating the DOM on change

Frameworks such as React and Vue will maintain state of an app and, when state updates, makes updates to the DOM and such. Essentially this is an observer pattern where “observers” are notified when the subject or state is altered.

class StateManager {

    constructor() {

        this.stateChangeHandlers = [];

        // when we update state, we notify observers (e.g. templates)
        this.state = {};

    }

    /**
     * This is to update state and automatically call the state change handler
     * @param values {object}
     */
    setState(values = {}) {

        // update state
        this.state = Object.assign(this.state, values);

        // notify handlers
        this.stateChangeHandlers.forEach(handler => {
            handler(this.state);
        });

    }

    /**
     * Register a handler for when state changes
     * @param mixed {args,...} (key, handler) or (handler)
     */
    onStateChange(handler) {

        this.stateChangeHandlers.push(handler);

    }
}


var state = new StateManager();

// here is where we set handler to fire when state changes 
state.onStateChange(function(state) {
    document.getElementById('app').innerHTML = "State changed: " + JSON.stringify(state);
});

state.setState({
    name: "Martyn"
});

Letting go of jQuery

jQuery was a blessing when it arrived especially when browser incompatibility was rife (IE6, ugh!). Standards have come along way and there are so many native methods to do things such as DOM selection, looping, etc than before. By all means, continue to use jQuery if you want as there is tons of useful functionality there. For me though, I’d rather not use it unless it’s really neccessary and ave manage to remove it from a few sites and not be so dependent on it.

I won’t repeat what’s already out there, but I’ll leave this link which I found useful when dropping jQuery from a site:

http://youmightnotneedjquery.com/

Location based personalisation and APIs

Location based personalisation is when a page is personalised for a user depending on their location. For example, a user from China could be shown a notification to visit a company’s Chinese micro-site, or users from India visiting a university website could be shown a block of content informing them about popular courses Indian students apply for. When used in this way, the marketing power of your website can be greatly enhanced. Continue reading →

A Foundation 6 / SASS work-flow

Vector graphic of Foundation yeti in a space rocket

Foundation is one of the most advanced front-end frameworks for building responsive websites. It is designed to work on all types of devices. It uses SASS which is a CSS pre-processor helping to reduce repetition with CSS and save time. In this short tutorial, I’ll discuss my current workflow using these two technologies. Continue reading →

Zend Framework 1 and PHPUnit: Controller tests

Zend Framework logo on green background

This is a example of PHPUnit testing for Zend Framework 1. I haven’t used this framework for a while but do recall the struggle to achieve automated testing on routes. So, if anyone reading this is still stuck on this old framework I hope this might be of some help 🙂 Continue reading →

A Bootstrap 3 / LESS work-flow

Bootstrap stack logo

Currently working on a project and on this occasion worked from the beginning by overwriting Bootstrap’s variables (as opposed to simply just overwriting its styles). My workflow, which will no doubt change as I discover new and better ways, for now it’s working out well. Continue reading →

スコットランド独立住民投票

Scottish independence flags

今月、歴史的なスコットランド独立住民投票もあります。それでスコットランド人はイギリスイギリスから抜けて、独立した国になることを決めます。賛成が多数なら、スコットランド人だけで自国の政治を行えるし、核兵器を放棄することができるし、国民保険サービスを守ることができるし、独立したほうがいいと思います。しかし、どんな通貨を使うのかとか、どのぐらい石油があるかなどの心配があるので、揉めている人が多いです。実は私は外国に住んでいるので投票権がありません。もし投票ができれば、ぜひ賛成します。独立国として今よりいい社会をつくることができると思います。 Continue reading →

古いノートパソコンはどうしたらいいかな

わたしのノートパッドは時代遅れなので、好きなOSの旧バーション以外動かすのがあまりよくではありませんでした。だから今年新しいノートパソコンを買いました。そのおかげで、問題なく、現在のバーションを動かすことができます。 Continue reading →

Deploying with Git

Git logo

I’ve been spending the day putting together a more automated method of deploying my websites – deploying with Git after I push to the remote repository on the server. Not only is this incredible easy to deploy changes once setup, it ensures that my live site is tied in nicely with my version control. Anyway it took a little time to tinker with so I thought I’d share my method I’m using. This approach uses a script to build an bare repository on the server, and hooks to pull changes to the live site. As every production environment is different I suggest this as a guide and make appropriate changes to suite your environment. Continue reading →