From b6702a5ea0e01b8aaa389462e869948d41ad9f86 Mon Sep 17 00:00:00 2001 From: Maxime Thirouin Date: Thu, 22 May 2014 06:20:38 +0200 Subject: [PATCH] Add attachLink method with test --- src/scripts/lib/proto/attach-link.js | 76 ++++++++++++++++++++++++++ src/scripts/lib/refresh.js | 3 + tests/scripts/lib/proto/attach-link.js | 58 ++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 src/scripts/lib/proto/attach-link.js create mode 100644 src/scripts/lib/refresh.js create mode 100644 tests/scripts/lib/proto/attach-link.js diff --git a/src/scripts/lib/proto/attach-link.js b/src/scripts/lib/proto/attach-link.js new file mode 100644 index 0000000..bb3a64a --- /dev/null +++ b/src/scripts/lib/proto/attach-link.js @@ -0,0 +1,76 @@ +require("../../polyfills/Function.prototype.bind") + +var on = require("../events/on") +var clone = require("../clone") + +var attrClick = "data-pjax-click-state" +var attrKey = "data-pjax-keyup-state" + +var linkAction = function(el, event) { + // Don’t break browser special behavior on links (like page in new window) + if (event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) { + el.setAttribute(attrClick, "modifier") + return + } + + // we do test on href now to prevent unexpected behavior if for some reason + // user have href that can be dynamically updated + + // Ignore external links. + if (el.protocol !== window.location.protocol || el.host !== window.location.host) { + el.setAttribute(attrClick, "external") + return + } + + // Ignore click if we are on an anchor on the same page + if (el.pathname === window.location.pathname && el.hash.length > 0) { + el.setAttribute(attrClick, "anchor-present") + return + } + + // Ignore anchors on the same page (keep native behavior) + if (el.hash && el.href.replace(el.hash, "") === window.location.href.replace(location.hash, "")) { + el.setAttribute(attrClick, "anchor") + return + } + + // Ignore empty anchor "foo.html#" + if (el.href === window.location.href.split("#")[0] + "#") { + el.setAttribute(attrClick, "anchor-empty") + return + } + + event.preventDefault() + + // don’t do "nothing" if user try to reload the page by clicking the same link twice + if (el.href === window.location.href.split("#")[0]) { + el.setAttribute(attrClick, "refresh") + this.refresh() + return + } + + el.setAttribute(attrClick, "load") + this.loadUrl(el.href, clone(this.options)) +} + +module.exports = function(el) { + var instance = this + + on(el, "click", function(event) { + linkAction.call(instance, el, event) + }) + + on(el, "keyup", function(event) { + + // Don’t break browser special behavior on links (like page in new window) + if (event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) { + el.setAttribute(attrKey, "modifier") + return + } + + if(event.keyCode == 13) { + linkAction.call(instance, el, event) + } + + }.bind(this)) +} diff --git a/src/scripts/lib/refresh.js b/src/scripts/lib/refresh.js new file mode 100644 index 0000000..44b38a6 --- /dev/null +++ b/src/scripts/lib/refresh.js @@ -0,0 +1,3 @@ +module.exports = function() { + window.location.reload() +} diff --git a/tests/scripts/lib/proto/attach-link.js b/tests/scripts/lib/proto/attach-link.js new file mode 100644 index 0000000..b5272f9 --- /dev/null +++ b/tests/scripts/lib/proto/attach-link.js @@ -0,0 +1,58 @@ +var tape = require("tape") + +var on = require("../../../../src/scripts/lib/events/on") +var trigger = require("../../../../src/scripts/lib/events/trigger") +var attachLink = require("../../../../src/scripts/lib/proto/attach-link") + +var a = document.createElement("a") +var attr = "data-pjax-click-state" +var preventDefault = function(e) { e.preventDefault() } + +tape("test attach link prototype method", function(t) { + t.plan(7) + + attachLink.call({ + options: {}, + refresh: function() { + t.equal(a.getAttribute(attr), "refresh", "triggering exact same url refresh the page") + }, + loadUrl: function() { + t.equal(a.getAttribute(attr), "load", "triggering a internal link actually load the page") + } + }, a) + + var internalUri = window.location.protocol + "//" + window.location.host + window.location.pathname + window.location.search + + a.href = internalUri + on(a, "click", preventDefault) // to avoid link to be open (break testing env) + trigger(a, "click", {metaKey: true}) + t.equal(a.getAttribute(attr), "modifier", "event key modifier stop behavior") + + a.href = "http://external.com/" + trigger(a, "click") + t.equal(a.getAttribute(attr), "external", "external url stop behavior") + + a.href = internalUri + "#anchor" + trigger(a, "click") + t.equal(a.getAttribute(attr), "anchor-present", "internal anchor stop behavior") + + window.location.hash = "#anchor" + a.href = internalUri + "#another-anchor" + trigger(a, "click") + t.notEqual(a.getAttribute(attr), "anchor", "differents anchors stop behavior") + window.location.hash = "" + + a.href = internalUri + "#" + trigger(a, "click") + t.equal(a.getAttribute(attr), "anchor-empty", "empty anchor stop behavior") + + a.href = internalUri + trigger(a, "click") + // see refresh defined above + + a.href = window.location.protocol + "//" + window.location.host + "/internal" + trigger(a, "click") + // see loadUrl defined above + + t.end() +})