JQuery vs Vanilla JS

Benchmark created on


Preparation HTML

<div id="github-timeline-widget">
</div>

  };

  Benchmark.prototype.teardown = function() {
    document.getElementById('github-timeline-widget').innerHTML = "";
  };
</script>

Setup

Benchmark.prototype.setup = function() {
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js">

Test runner

Ready to run.

Testing in
TestOps/sec
Plain JS
var GitHubTimelineApi;
GitHubTimelineApi = (function () {
    function GitHubTimelineApi() {
    }
    GitHubTimelineApi.prototype.formatAsTimeAgo = function (ms) {
        var tc = [3.15569e7, 2629741, 604800, 86400, 3600, 60, 1],
            td = ['year', 'month', 'week', 'day', 'hour', 'minute', 'second'],
            ti = {year: 0, month: 1, week: 2, day: 3, hour: 4, minute: 5, second: 6};
        //ti avoids use of Array.indexOf for accepting shortest/longest args as strings
        base = 1000,
        time = ms / base,
        shortest = (arguments[2]) ? ti[arguments[2].replace(/s\b/gi, '')] : 6,
        longest  = (arguments[1]) ? ti[arguments[1].replace(/s\b/gi, '')] : 0,
        limit = arguments[3] || shortest - longest;

        if(ms < base) return "Just now";

        var time_in_units = 0, ret_val = [], depth = 0;

        for(var x = longest; x <= shortest; x++) {
            time_in_units = Math.floor(time / tc[x]);
            if(time_in_units >= 1) {
                depth++;
                time = time - (time_in_units * tc[x]);
                if(depth === 1 && td[x] === 'day' && time_in_units === 1) return 'Yesterday';
                ret_val.push(time_in_units);
                ret_val.push(td[x] + ((ret_val[ret_val.length-1] > 1) ? 's' : '') + ' ago');
            }
            if(depth === limit) break;
        }

        return ret_val.join(' ');
    };

    GitHubTimelineApi.prototype._parseGitHubEvent = function (event) {
        var branch, icon_class, repository, text, timestamp, url, _ref;
        url = (event.url != null ? event.url : void 0) || (((_ref = event.payload) != null ? _ref.url : void 0) != null ? event.payload.url : void 0) || "https://github.com";
        url = url.replace("github.com//", "github.com/");
        timestamp = new Date((event.created_at != null ? event.created_at : void 0) || 0).valueOf();
        if (event.repository != null) {
            repository = event.repository.owner + "/" + event.repository.name;
        }

        var event_type = event.type.replace('Event', '');

        var et = {
            Create : {t: {repository: ['created repo', '$repo'],tag: ['created tag', '$.ref', 'at', '$repo'],branch: ['created branch', '$.ref', 'at', '$repo']}},
            ForkApply: {i: 'merge', t: ['merged to', '$repo']},
            Fork: {i: 'repo-forked', t: ['forked ', '$repo']},
            Watch: {i: {started: 'watching', stopped : 'unwatch'},t: { started: ['started watching', '$repo'], stopped: ['stopped watching', '$repo']}},
            PullRequest: {i: {opened: 'issue-opened', reopened : 'issue-reopened', closed: 'issue-closed'},t: {opened : ['opened issue on', '$repo'],reopened : ['reopened issue on', '$repo'],closed : ['closed issue on', '$repo']}},
            Gist: {i: {update: 'gist-add', fork : 'gist-forked', create : 'gist'},t: {create: ['created', '$.name'], update : ['updated', '$.name'], fork : ['forked', '$.name']}},
            Gollum : {i: 'wiki',t: {created : ['created a wiki page on', '$repo'], edited : ['edited a wiki page on', '$repo']}},
            CommitComment : {i: 'commit-comment', t: ['commented on', '$repo']},
            Delete : {i: 'branch-delete', t: ['deleted branch', '$.ref', 'at', '$repo']},
            Public : {i: 'public-mirror', t: ['open sourced', '$repo']},
            IssueComment : {i: 'discussion', t: ['commented on an issue at', '$repo']},
            Member: {t: {added: ['added' + '$.member', 'to', '$repo']}},
            Push : {t: ['pushed to', '$branch', 'at', '$repo'] },
            Follow: {t: ['started following', '$.target.login']}
        };

        et.Issues = et.PullRequest;
        et.Wiki = et.Gollum;

        var eti = et[event_type].i || event_type,
            ett = et[event_type].t || event_type;

        icon_class = (typeof eti === 'string') ? eti : eti[event.payload.action];

        function generateText(arr) {
            for(var x = 0; x < arr.length; x++) {
                if(arr[x].substr(0, 1) === '$') {
                    if(arr[x] === '$repo') {
                        arr[x] = repository;
                    } else if(arr[x].substring(0, 2) === '$.') {
                        var pv =  arr[x].substring(2).split('.');
                        arr[x] = (pv.length === 1) ? event.payload[pv[0]] : event.payload[pv[0]][pv[1]];
                    } else if(arr[x] === '$branch') {
                        arr[x] = event.payload.ref.substr(event.payload.ref.lastIndexOf("/") + 1);
                    }
                    if(arr[x] === undefined) return null;
                    arr[x] = '<strong>' + arr[x] + '</strong>';
                }
            }
            if(typeof arr === 'string') return arr;
            return arr.join(' ');
        }

        if(typeof ett === 'object' && ett instanceof Array === false) {
            text = generateText(ett[event.payload.ref_type] || ett[event.payload.action] || ett[event.payload.pages[0].action]);
        } else {
            text = generateText(ett);
        }

        if (text != null) {
            return[url, icon_class, timestamp, text]
        } else {
            return[]
        }
    };
    GitHubTimelineApi.prototype._parseGitHubTimeline = function (data, callback) {
        var event, event_data, events, _i, _len;
        events = [];
        for (_i = 0, _len = data.length; _i < _len; _i++) {
            event = data[_i];
            event_data = this._parseGitHubEvent(event);
            if (event_data.length) {
                events.push(event_data)
            }
        }
        return callback(events)
    };
    GitHubTimelineApi.prototype.getTimelineForUser = function (user, callback) {
        var _this = this;
        jQuery.ajaxSetup({cache:true});
        return jQuery.getJSON("https://github.com/" + user + ".json?callback=?", function (data) {
            return _this._parseGitHubTimeline(data, callback)
        })
    };
    GitHubTimelineApi.prototype.getUserIdForUser = function (user, callback) {
        var _this = this;
        jQuery.ajaxSetup({cache:true});
        return jQuery.getJSON("https://github.com/api/v2/json/user/show/" + user + "?callback=?", function (data) {
            return callback(data.user.id)
        })
    };
    return GitHubTimelineApi
})();
jQuery.fn.githubTimelineWidget = function (options) {
    var defaults, script, script_path, scripts, _i, _len, _ref;
    defaults = {username:"timeline", limit:1024, user_id:true, header:"octocat", humble:false};
    if (script_path != null) {
        jQuery("<link/>").attr("rel", "stylesheet").attr("type", "text/css").attr("href", script_path + "github-timeline-widget.css").prependTo("head")
    }
    //TODO: do we still need to hide the widget?
    //jQuery("#github-timeline-widget").toggle();
    return this.each(function () {
        var $this, api, it, list;
        it = this;
        $this = jQuery(this);
        it.opts = jQuery.extend({}, defaults, options);
        if (options.header) {
            
            var header_html = jQuery("<a>").attr("class", "github-timeline-header").attr("href", "https://github.com/" + it.opts.username).html("" + it.opts.username + " on GitHub <hr>");
            if (options.header === "octocat") {
                header_html = jQuery("<span>").attr("class", "mega-icon mega-icon-octocat").html(header_html)
            }
            jQuery(header_html).appendTo($this)
        }
        list = jQuery("<ul>").attr("class", "github-timeline-events").appendTo($this);
        api = new GitHubTimelineApi;
        api.getTimelineForUser(it.opts.username, function (events) {
            var div_text, event, event_link, events_left, icon_class, list_item, text, timestamp, timestamp_ago, url, _j, _len1;
            events_left = it.opts.limit;
            for (_j = 0, _len1 = events.length; _j < _len1; _j++) {
                event = events[_j];
                if (events_left-- === 0) {
                    break
                }
                url = event[0], icon_class = event[1], timestamp = event[2], text = event[3];
                list_item = jQuery("<li>").attr("class", "github-timeline-event").appendTo(list);
                event_link = jQuery("<a>").attr("href", url);
                if (icon_class) {
                    jQuery("<span>").attr("class", "github-timeline-event-icon mini-icon mini-icon-" + icon_class).appendTo(list_item).wrap(event_link)
                }
                div_text = jQuery("<div>").attr("class", "github-timeline-event-text").html(text).appendTo(list_item).wrapInner(event_link);
                if (timestamp) {
                    timestamp_ago = api.formatAsTimeAgo(new Date() - timestamp, 'years', 'minutes', 1);
                    if (timestamp_ago) {
                        jQuery("<div>").attr("class", "github-timeline-event-time").text(timestamp_ago).appendTo(div_text)
                    }
                }
            }
            if (options.fadeIn) {
                //TODO: add css fade-in if delay still present
                //jQuery("#github-timeline-widget").fadeIn("fast")
            } else {
                //TODO: add css fade-in if delay still present
                //jQuery("#github-timeline-widget").toggle()
            }
            if (!options.humble) {
                return jQuery("<a>").attr("class", "github-timeline-source-link").attr("href", "https://github.com/alindeman/github-timeline-widget").text("GitHub Timeline Widget").appendTo($this)
            } else {
                return $this
            }
        });
        if (it.opts.user_id) {
            return api.getUserIdForUser(it.opts.username, function (user_id) {
                jQuery("<br/>").appendTo(".github-timeline-header");
                return jQuery("<span>").attr("class", "github-timeline-header-user-id").text("(user #" + user_id + ")").appendTo(".github-timeline-header")
            })
        }
    })
};
jQuery(document).ready(function() {
  $("#github-timeline-widget").githubTimelineWidget({
    username: 'jmealo',
    limit: 1024,
    user_id: false,
    humble: true,
    fadeIn: true,
    header: 'octocat'
  });
});
ready
jQuery
var GitHubTimelineApi;
GitHubTimelineApi = (function() {
  function GitHubTimelineApi() {}
  GitHubTimelineApi.prototype._strongify = function(string) {
    return "<strong>" + string + "</strong>"
  };
  GitHubTimelineApi.prototype.formatAsTimeAgo = function(date) {
    var day_diff, diff;
    diff = ((new Date).getTime() - date.getTime()) / 1000;
    day_diff = Math.floor(diff / 86400);
    if ((isNaN(day_diff)) || (day_diff < 0)) {
      return null
    }
    if (day_diff === 0) {
      if (diff < 60) {
        return "just now"
      } else {
        if (diff < 120) {
          return "1 minute ago"
        } else {
          if (diff < 3600) {
            return "" + (Math.floor(diff / 60)) + " minutes ago"
          } else {
            if (diff < 7200) {
              return "1 hour ago"
            } else {
              if (diff < 86400) {
                return "" + (Math.floor(diff / 3600)) + " hours ago"
              }
            }
          }
        }
      }
    } else {
      if (day_diff === 1) {
        return "Yesterday"
      } else {
        if (day_diff < 7) {
          return "" + day_diff + " days ago"
        } else {
          return "" + (Math.ceil(day_diff / 7)) + " weeks ago"
        }
      }
    }
  };
  GitHubTimelineApi.prototype._parseGitHubEvent = function(event) {
    var branch, icon_class, repository, text, timestamp, url, _ref;
    url = (event.url != null ? event.url : void 0) || (((_ref = event.payload) != null ? _ref.url : void 0) != null ? event.payload.url : void 0) || "https://github.com";
    url = url.replace("github.com//", "github.com/");
    timestamp = new Date((event.created_at != null ? event.created_at : void 0) || 0).valueOf();
    if (event.repository != null) {
      repository = this._strongify("" + event.repository.owner + "/" + event.repository.name)
    }
    switch (event.type) {
    case "CreateEvent":
      icon_class = "create";
      switch (event.payload.object) {
      case "repository":
        text = "created repo " + repository;
        break;
      case "tag":
        text = "created tag " + (this._strongify(event.payload.object_name)) + " at " + repository;
        break;
      case "branch":
        text = "created branch " + (this._strongify(event.payload.object_name)) + " at " + repository
      }
      break;
    case "MemberEvent":
      switch (event.payload.action) {
      case "added":
        icon_class = "member-added";
        text = "added " + (this._strongify(event.payload.member)) + " to " + repository
      }
      break;
    case "PushEvent":
      branch = event.payload.ref.substr(event.payload.ref.lastIndexOf("/") + 1);
      icon_class = "push";
      text = "pushed to " + (this._strongify(branch)) + " at " + repository;
      break;
    case "ForkApplyEvent":
      icon_class = "merge";
      text = "merged to " + repository;
      break;
    case "ForkEvent":
      icon_class = "repo-forked";
      text = "forked " + repository;
      break;
    case "WatchEvent":
      switch (event.payload.action) {
      case "started":
        icon_class = "watching";
        text = "started watching " + repository;
        break;
      case "stopped":
        icon_class = "unwatch";
        text = "stopped watching " + repository
      }
      break;
    case "FollowEvent":
      text = null;
      break;
    case "IssuesEvent":
    case "PullRequestEvent":
      switch (event.payload.action) {
      case "opened":
        icon_class = "issue-opened";
        text = "opened issued on " + repository;
        break;
      case "reopened":
        icon_class = "issue-reopened";
        text = "reopened issued on " + repository;
        break;
      case "closed":
        icon_class = "issue-closed";
        text = "closed issue on " + repository
      }
      break;
    case "GistEvent":
      switch (event.payload.action) {
      case "create":
        icon_class = "gist";
        text = "created " + (this._strongify(event.payload.name));
        break;
      case "update":
        icon_class = "gist-add";
        text = "updated " + (this._strongify(event.payload.name));
        break;
      case "fork":
        icon_class = "gist-forked";
        text = "forked " + (this._strongify(event.payload.name))
      }
      break;
    case "WikiEvent":
    case "GollumEvent":
      icon_class = "wiki";
      switch (event.payload.action) {
      case "created":
        text = "created a wiki page on " + repository;
        break;
      case "edited":
        text = "edited a wiki page on " + repository
      }
      break;
    case "CommitCommentEvent":
      icon_class = "commit-comment";
      text = "commented on " + repository;
      break;
    case "DeleteEvent":
      icon_class = "branch-delete";
      switch (event.payload.ref_type) {
      case "branch":
        text = "deleted branch " + (this._strongify(event.payload.ref)) + " at " + repository
      }
      break;
    case "PublicEvent":
      icon_class = "public-mirror";
      text = "open sourced " + repository;
      break;
    case "DownloadEvent":
      text = null
    }
    if (text != null) {
      return [url, icon_class, timestamp, text]
    } else {
      return []
    }
  };
  GitHubTimelineApi.prototype._parseGitHubTimeline = function(data, callback) {
    var event, event_data, events, _i, _len;
    events = [];
    for (_i = 0, _len = data.length; _i < _len; _i++) {
      event = data[_i];
      event_data = this._parseGitHubEvent(event);
      if (event_data.length) {
        events.push(event_data)
      }
    }
    return callback(events)
  };
  GitHubTimelineApi.prototype.getTimelineForUser = function(user, callback) {
    var _this = this;
    jQuery.ajaxSetup({
      cache: true
    });
    return jQuery.getJSON("https://github.com/" + user + ".json?callback=?", function(data) {
      return _this._parseGitHubTimeline(data, callback)
    })
  };
  GitHubTimelineApi.prototype.getUserIdForUser = function(user, callback) {
    var _this = this;
    jQuery.ajaxSetup({
      cache: true
    });
    return jQuery.getJSON("https://github.com/api/v2/json/user/show/" + user + "?callback=?", function(data) {
      return callback(data.user.id)
    })
  };
  return GitHubTimelineApi
})();
jQuery.fn.githubTimelineWidget = function(options) {
  var defaults, script, script_path, scripts, _i, _len, _ref;
  defaults = {
    username: "timeline",
    limit: 5,
    user_id: true,
    header: "octocat",
    humble: false
  };
  scripts = document.getElementsByTagName("script");
  for (_i = 0, _len = scripts.length; _i < _len; _i++) {
    script = scripts[_i];
    if ((_ref = script.src) != null ? _ref.match(/github-timeline-widget\.js/) : void 0) {
      script_path = script.src.replace(/github-timeline-widget\.js.*$/, "");
      break
    }
  }
  if (script_path != null) {
    jQuery("<link/>").attr("rel", "stylesheet").attr("type", "text/css").attr("href", script_path + "github-timeline-widget.css").prependTo("head")
  }
  jQuery("#github-timeline-widget").toggle();
  return this.each(function() {
    var $this, api, it, list;
    it = this;
    $this = jQuery(this);
    it.opts = jQuery.extend({}, defaults, options);
    if (options.header) {
      var header_html = jQuery("<a>").attr("class", "github-timeline-header").attr("href", "https://github.com/" + it.opts.username).html("" + it.opts.username + " on GitHub <hr>");
      if (options.header === "octocat") {
        header_html = jQuery("<span>").attr("class", "mega-icon mega-icon-octocat").html(header_html)
      }
      jQuery(header_html).appendTo($this)
    }
    list = jQuery("<ul>").attr("class", "github-timeline-events").appendTo($this);
    api = new GitHubTimelineApi;
    api.getTimelineForUser(it.opts.username, function(events) {
      var div_text, event, event_link, events_left, icon_class, list_item, text, timestamp, timestamp_ago, url, _j, _len1;
      events_left = it.opts.limit;
      for (_j = 0, _len1 = events.length; _j < _len1; _j++) {
        event = events[_j];
        if (events_left-- === 0) {
          break
        }
        url = event[0], icon_class = event[1], timestamp = event[2], text = event[3];
        list_item = jQuery("<li>").attr("class", "github-timeline-event").appendTo(list);
        event_link = jQuery("<a>").attr("href", url);
        if (icon_class) {
          jQuery("<span>").attr("class", "github-timeline-event-icon mini-icon mini-icon-" + icon_class).appendTo(list_item).wrap(event_link)
        }
        div_text = jQuery("<div>").attr("class", "github-timeline-event-text").html(text).appendTo(list_item).wrapInner(event_link);
        if (timestamp) {
          timestamp_ago = api.formatAsTimeAgo(new Date(timestamp));
          if (timestamp_ago) {
            jQuery("<div>").attr("class", "github-timeline-event-time").text(timestamp_ago).appendTo(div_text)
          }
        }
      }
      if (options.fadeIn) {
        jQuery("#github-timeline-widget").fadeIn("fast")
      } else {
        jQuery("#github-timeline-widget").toggle()
      }
      if (!options.humble) {
        return jQuery("<a>").attr("class", "github-timeline-source-link").attr("href", "https://github.com/alindeman/github-timeline-widget").text("GitHub Timeline Widget").appendTo($this)
      } else {
        return $this
      }
    });
    if (it.opts.user_id) {
      return api.getUserIdForUser(it.opts.username, function(user_id) {
        jQuery("<br/>").appendTo(".github-timeline-header");
        return jQuery("<span>").attr("class", "github-timeline-header-user-id").text("(user #" + user_id + ")").appendTo(".github-timeline-header")
      })
    }
  })
};

jQuery(document).ready(function() {
  $("#github-timeline-widget").githubTimelineWidget({
    username: 'jmealo',
    limit: 1024,
    user_id: false,
    humble: true,
    fadeIn: true,
    header: 'octocat'
  });
});
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.