Compare commits

...

30 Commits
0.2.1 ... 0.2.3

Author SHA1 Message Date
Maxime Thirouin
4877bac2ae 0.2.3 2016-03-24 12:39:07 +01:00
Maxime Thirouin
afe0ddb6b9 Fixed: `this.reload` is now a Function
Closes #65
2016-03-24 12:38:15 +01:00
Maxime Thirouin
a5d36d28f8 Update README.md 2016-03-15 11:36:53 +01:00
Maxime Thirouin
7a4056fd77 Update README.md 2016-03-15 11:35:13 +01:00
Maxime Thirouin
ba6ef126c0 Internal: add "npm run release" command
—skip-test is used because of tesling (it does not like to be spawned
or something like that)…
2016-03-12 07:52:52 +01:00
Maxime Thirouin
01536bfbf5 0.2.2
Closes #55
2016-03-12 07:42:37 +01:00
Maxime Thirouin
722ddf2a30 Internal: simple repository url 2016-03-12 07:27:47 +01:00
Maxime Thirouin
34fc00c89d Add standalone file back, no big deal
Closes #57
2016-03-12 07:27:06 +01:00
Maxime Thirouin
c02193c61b Internal: update CHANGELOG #59 2016-03-12 07:26:26 +01:00
Maxime Thirouin
824b229158 Merge pull request #59 from coolhihi/master
Fixed: error when using pjax with google analytics
2016-03-12 07:09:55 +01:00
COoL
e3d0f8cc1b fixed an error when using pjax with google analytics 2016-01-15 17:32:07 +08:00
Maxime Thirouin
8ea8ffad07 Update CHANGELOG 2016-01-05 07:42:00 +01:00
Maxime Thirouin
c12e4cdedd Merge pull request #52 from darylteo/patch-51
Patch 51
2016-01-05 07:15:11 +01:00
Maxime Thirouin
546b7e309a Merge pull request #50 from darylteo/patch-5
Patch 5
2016-01-05 07:14:29 +01:00
Maxime Thirouin
2f4bd760a5 Merge pull request #49 from darylteo/patch-39
[FIX] #39 - events on top level
2016-01-05 07:14:17 +01:00
darylteo
477d967804 Add clone and executeScripts as well 2016-01-05 15:02:39 +11:00
darylteo
e882b8639a Use required forEachElse 2016-01-05 15:02:00 +11:00
darylteo
3d25bee131 Bind required functions to pjax 2016-01-05 14:22:03 +11:00
darylteo
47059bdb04 Add test for switch selectors 2016-01-05 14:12:52 +11:00
darylteo
791400ed20 Tests for #5 2016-01-04 23:45:25 +11:00
darylteo
97c8b2d749 [NEW] #5 Ignore default prevented clicks 2016-01-04 23:19:36 +11:00
darylteo
b156a4f389 [TEST] Test for #39 2016-01-04 22:52:30 +11:00
darylteo
1d292a1a6e [FIX] #39 - events on top level
Events triggered on top level elements (such as window or document)
lead to a HierarchyRequestError due to a fix in IE browsers
where dispatchEvent does not fire if an element is not in the DOM.

The current test is simply to check for the existence of parentNode
However, this means top level elements get added to itself, causing
the error.

The proposed fix simply tests for top level elements in the test.
2016-01-04 22:30:00 +11:00
Maxime Thirouin
aaa2631eb7 Merge pull request #42 from MohamedBoualleg/patch-1
Update README.md
2015-12-18 08:25:55 +01:00
Maxime Thirouin
460dea8a9e Merge pull request #44 from rstacruz/fix/stuff
Add examples, remove failing test
2015-11-14 12:28:26 +01:00
Rico Sta. Cruz
b908621842 Fix lint errors 2015-11-13 23:59:22 +11:00
Rico Sta. Cruz
b20ee2261e Add example 2015-11-13 10:40:59 +11:00
Rico Sta. Cruz
ad6292fffb Add prepublish hook 2015-11-13 10:28:16 +11:00
Mohamed Bouallegue
4ed4577539 Update README.md 2015-10-11 04:06:04 +01:00
Maxime Thirouin
6eafcf8dc6 Add a standalone build to ensure it "should" work 2015-02-19 07:51:42 +01:00
15 changed files with 218 additions and 65 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
.DS_Store .DS_Store
node_modules/ node_modules/
tests/scripts/index.html tests/scripts/index.html
pjax.js

View File

@@ -1,6 +1,25 @@
# unreleased # 0.2.3 - 2016-03-24
- - Fixed: ``currentUrlFullReload`` option now works
- Fixed: ``this.reload`` is now a Function
([#65](https://github.com/MoOx/pjax/issues/65))
# 0.2.2 - 2016-03-12
- Fixed: added back standalone version in `./pjax.js`
([#57](https://github.com/MoOx/pjax/issues/57)
- Fixed: error when using pjax with google analytics (``options`` was undefined)
([#59](https://github.com/MoOx/pjax/pull/59))
- Fixed: HierarchyRequestError error
([#49](https://github.com/MoOx/pjax/pull/49))
- Fixed: ``TypeError: Pjax.forEachEls is not a function``
([#52](https://github.com/MoOx/pjax/pull/52))
- Fixed: ``TypeError: Pjax.executeScripts is not a function``
([#52](https://github.com/MoOx/pjax/pull/52))
- Fixed: ``TypeError: Pjax.clone is not a function``
([#52](https://github.com/MoOx/pjax/pull/52))
- Added: Ignore events with prevented defaults
([#50](https://github.com/MoOx/pjax/pull/50))
# 0.2.1 - 2015-02-04 # 0.2.1 - 2015-02-04

View File

@@ -1,7 +1,6 @@
# Pjax [![Build Status](http://img.shields.io/travis/MoOx/pjax.svg)](https://travis-ci.org/MoOx/pjax) # Pjax
[![Build Status](http://img.shields.io/travis/MoOx/pjax.svg)](https://travis-ci.org/MoOx/pjax) [@todo fix CI](https://github.com/MoOx/pjax/issues/63).
[![browser support](https://ci.testling.com/MoOx/pjax.png)](https://ci.testling.com/MoOx/pjax)
> Easily enable fast Ajax navigation on any website (using pushState + xhr) > Easily enable fast Ajax navigation on any website (using pushState + xhr)
@@ -16,9 +15,6 @@ Especially for user that have low bandwidth connection._
**No more full page reload. No more lots of HTTP request.** **No more full page reload. No more lots of HTTP request.**
# Note: current master is WIP.
Checkout [v0.1.4](https://github.com/MoOx/pjax/tree/a17a6b90bebefd8f5209e6a6f7d8c5d59296232a) for latest "stable" (no tests so kind of funny to call that stable).
## Demo ## Demo
@@ -44,7 +40,7 @@ want (including html metas, title, navigation state).
### Under the hood ### Under the hood
- It listen to every clicks on links _you want_ (by default all of them), - It listen to every clicks on links _you want_ (by default all of them),
- When a internal link hitted, Pjax grabs HTML from your server via ajax, - When an internal link is clicked, Pjax grabs HTML from your server via ajax,
- Pjax render pages DOM tree (without loading any resources - images, css, js...) - Pjax render pages DOM tree (without loading any resources - images, css, js...)
- It check if all defined parts can be replaced: - It check if all defined parts can be replaced:
- if page doesn't suit requirement, classic navigation used, - if page doesn't suit requirement, classic navigation used,
@@ -394,25 +390,6 @@ Useful to debug page layout differences.
When set to true, clicking on a link that point the current url trigger a full page reload. When set to true, clicking on a link that point the current url trigger a full page reload.
#### Extend Pjax
Pjax prototype & utilities methods can be used & changed so you can patch or hack
Pjax behavior, as you wish.
Here is a summary of functions:
- `Pjax.prototype.log` (`function()`): console.log function that is enable/disabled by `debug` option
- `Pjax.prototype.getElements` (`function(el)`): retrieve elements to attach Pjax behavior
- `Pjax.prototype.parseDOM` (`function(el)`): parse DOM to attach behavior using `Pjax.prototype.getElements` & `Pjax.prototype.attachLink`
- `Pjax.prototype.attachLink` (`function(el)`): attach Pjax behavior to a link
- `Pjax.prototype.forEachSelectors` (`function(cb, context, DOMcontext)`): call a function for each selectors defined
- `Pjax.prototype.switchSelectors` (`function(selectors, fromEl, toEl, options)`): loop on selectors to switch elements
- `Pjax.prototype.latestChance` (`function(href)`): when everything is fucked up, it's our only hope (just call `window.location = href`)
- `Pjax.prototype.onSwitch` (`function()`): callback triggered when elements are switched, for now it's just trigger a window resize event (lots of lib are listening to this event to draw stuff)
- `Pjax.prototype.loadContent` (`function(html, options)`): switch elements for each selectors
- `Pjax.prototype.doRequest` (`function(location, callback)`): make the ajax request to grab page from the server
- `Pjax.prototype.loadUrl` (`function(href, options)`): do the ajax request, handle html results & eventually handle browser history, analytics & scroll.
### Events ### Events
Pjax fires a number of events regardless of how its invoked. Pjax fires a number of events regardless of how its invoked.
@@ -537,15 +514,19 @@ wrapper on each page (to avoid differences of DOM between pages)
--- ---
## Contributing ## Examples
Work on a branch, install dev-dependencies, respect coding style & run tests before submitting a bug fix or a feature. Clone this repository and run `npm run example`, then open `http://localhost:3000/example` in your browser.
$ git clone https://github.com/MoOx/pjax.git ---
$ git checkout -b patch-1
$ npm install
$ npm test
## [Changelog](CHANGELOG.md) ## CONTRIBUTING
* ⇄ Pull requests and ★ Stars are always welcome.
* For bugs and feature requests, please create an issue.
* Pull requests must be accompanied by passing automated tests (`$ npm test`).
## [CHANGELOG](CHANGELOG.md)
## [LICENSE](LICENSE)
## [License](LICENSE)

View File

@@ -1,6 +1,6 @@
{ {
"name": "pjax", "name": "pjax",
"version": "0.1.4", "version": "0.2.2",
"description": "Easily enable fast Ajax navigation on any website (using pushState + xhr)", "description": "Easily enable fast Ajax navigation on any website (using pushState + xhr)",
"keywords": [ "keywords": [
"pjax", "pjax",
@@ -11,7 +11,7 @@
"transition", "transition",
"animation" "animation"
], ],
"main": "src/pjax.js", "main": "pjax.js",
"homepage": "https://github.com/MoOx/pjax", "homepage": "https://github.com/MoOx/pjax",
"authors": [ "authors": [
"Maxime Thirouin" "Maxime Thirouin"

26
example/example.js Normal file
View File

@@ -0,0 +1,26 @@
/* global Pjax */
console.log("Document initialized:", window.location.href)
document.addEventListener("pjax:send", function() {
console.log("Event: pjax:send", arguments)
})
document.addEventListener("pjax:complete", function() {
console.log("Event: pjax:complete", arguments)
})
document.addEventListener("pjax:error", function() {
console.log("Event: pjax:error", arguments)
})
document.addEventListener("pjax:success", function() {
console.log("Event: pjax:success", arguments)
})
document.addEventListener("DOMContentLoaded", function() {
var pjax = new Pjax({
selectors: [".body"],
// currentUrlFullReload: true,
})
console.log("Pjax initialized.", pjax)
})

17
example/index.html Normal file
View File

@@ -0,0 +1,17 @@
<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<title>Hello</title>
<script src='../pjax.js'></script>
<script src='example.js'></script>
</head>
<body>
<div class='body'>
<h1>Index</h1>
Hello.
Go to <a href='page2.html'>Page 2</a> and view your console to see Pjax events.
Clicking on <a href='index.html'>this page</a> will just reload the page entierly.
</div>
</body>
</html>

15
example/page2.html Normal file
View File

@@ -0,0 +1,15 @@
<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<title>Hello</title>
<script src='../pjax.js'></script>
<script src='example.js'></script>
</head>
<body>
<div class='body'>
<h1>Page 2</h1>
Hello. Go to <a href='index.html'>Index</a>.
</div>
</body>
</html>

View File

@@ -1,3 +1,7 @@
var clone = require('./lib/clone.js')
var executeScripts = require('./lib/execute-scripts.js')
var forEachEls = require("./lib/foreach-els.js")
var newUid = require("./lib/uniqueid.js") var newUid = require("./lib/uniqueid.js")
@@ -5,6 +9,7 @@ var on = require("./lib/events/on.js")
// var off = require("./lib/events/on.js") // var off = require("./lib/events/on.js")
var trigger = require("./lib/events/trigger.js") var trigger = require("./lib/events/trigger.js")
var Pjax = function(options) { var Pjax = function(options) {
this.firstrun = true this.firstrun = true
@@ -18,7 +23,7 @@ var Pjax = function(options) {
on(window, "popstate", function(st) { on(window, "popstate", function(st) {
if (st.state) { if (st.state) {
var opt = Pjax.clone(this.options) var opt = clone(this.options)
opt.url = st.state.url opt.url = st.state.url
opt.title = st.state.title opt.title = st.state.title
opt.history = false opt.history = false
@@ -46,14 +51,16 @@ Pjax.prototype = {
refresh: require("./lib/proto/refresh.js"), refresh: require("./lib/proto/refresh.js"),
reload: require("./lib/reload.js"),
attachLink: require("./lib/proto/attach-link.js"), attachLink: require("./lib/proto/attach-link.js"),
forEachSelectors: function(cb, context, DOMcontext) { forEachSelectors: function(cb, context, DOMcontext) {
return require("./lib/foreach-selectors.js")(this.options.selectors, cb, context, DOMcontext) return require("./lib/foreach-selectors.js").bind(this)(this.options.selectors, cb, context, DOMcontext)
}, },
switchSelectors: function(selectors, fromEl, toEl, options) { switchSelectors: function(selectors, fromEl, toEl, options) {
return require("./lib/switches-selectors.js")(this.options.switches, this.options.switchesOptions, selectors, fromEl, toEl, options) return require("./lib/switches-selectors.js").bind(this)(this.options.switches, this.options.switchesOptions, selectors, fromEl, toEl, options)
}, },
// too much problem with the code below // too much problem with the code below
@@ -118,8 +125,8 @@ Pjax.prototype = {
// execute scripts when DOM have been completely updated // execute scripts when DOM have been completely updated
this.options.selectors.forEach(function(selector) { this.options.selectors.forEach(function(selector) {
Pjax.forEachEls(document.querySelectorAll(selector), function(el) { forEachEls(document.querySelectorAll(selector), function(el) {
Pjax.executeScripts(el) executeScripts(el)
}) })
}) })
// } // }

View File

@@ -16,7 +16,7 @@ module.exports = function(els, events, opts) {
forEachEls(els, function(el) { forEachEls(els, function(el) {
var domFix = false var domFix = false
if (!el.parentNode) { if (!el.parentNode && el !== document && el !== window) {
// THANKS YOU IE (9/10//11 concerned) // THANKS YOU IE (9/10//11 concerned)
// dispatchEvent doesn't work if element is not in the dom // dispatchEvent doesn't work if element is not in the dom
domFix = true domFix = true

View File

@@ -43,7 +43,10 @@ var linkAction = function(el, event) {
event.preventDefault() event.preventDefault()
// dont do "nothing" if user try to reload the page by clicking the same link twice // dont do "nothing" if user try to reload the page by clicking the same link twice
if (el.href === window.location.href.split("#")[0]) { if (
this.options.currentUrlFullReload &&
el.href === window.location.href.split("#")[0]
) {
el.setAttribute(attrClick, "reload") el.setAttribute(attrClick, "reload")
this.reload() this.reload()
return return
@@ -53,14 +56,26 @@ var linkAction = function(el, event) {
this.loadUrl(el.href, clone(this.options)) this.loadUrl(el.href, clone(this.options))
} }
var isDefaultPrevented = function(event) {
return event.defaultPrevented || event.returnValue === false;
}
module.exports = function(el) { module.exports = function(el) {
var that = this var that = this
on(el, "click", function(event) { on(el, "click", function(event) {
if (isDefaultPrevented(event)) {
return
}
linkAction.call(that, el, event) linkAction.call(that, el, event)
}) })
on(el, "keyup", function(event) { on(el, "keyup", function(event) {
if (isDefaultPrevented(event)) {
return
}
// Dont break browser special behavior on links (like page in new window) // Dont break browser special behavior on links (like page in new window)
if (event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) { if (event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
el.setAttribute(attrKey, "modifier") el.setAttribute(attrKey, "modifier")

View File

@@ -7,7 +7,7 @@ module.exports = function(options){
this.options.switches = this.options.switches || {} this.options.switches = this.options.switches || {}
this.options.switchesOptions = this.options.switchesOptions || {} this.options.switchesOptions = this.options.switchesOptions || {}
this.options.history = this.options.history || true this.options.history = this.options.history || true
this.options.analytics = this.options.analytics || function(options) { this.options.analytics = this.options.analytics || function() {
// options.backward or options.foward can be true or undefined // options.backward or options.foward can be true or undefined
// by default, we do track back/foward hit // by default, we do track back/foward hit
// https://productforums.google.com/forum/#!topic/analytics/WVwMDjLhXYk // https://productforums.google.com/forum/#!topic/analytics/WVwMDjLhXYk
@@ -15,7 +15,7 @@ module.exports = function(options){
_gaq.push(["_trackPageview"]) _gaq.push(["_trackPageview"])
} }
if (window.ga) { if (window.ga) {
ga("send", "pageview", {page: options.url, title: options.title}) ga("send", "pageview", {page: location.pathname, title: document.title})
} }
} }
this.options.scrollTo = (typeof this.options.scrollTo === 'undefined') ? 0 : this.options.scrollTo; this.options.scrollTo = (typeof this.options.scrollTo === 'undefined') ? 0 : this.options.scrollTo;

View File

@@ -1,6 +1,6 @@
{ {
"name": "pjax", "name": "pjax",
"version": "0.2.1", "version": "0.2.3",
"description": "Easily enable fast Ajax navigation on any website (using pushState + xhr)", "description": "Easily enable fast Ajax navigation on any website (using pushState + xhr)",
"keywords": [ "keywords": [
"pjax", "pjax",
@@ -11,43 +11,46 @@
"transition", "transition",
"animation" "animation"
], ],
"repository": { "repository": "https://github.com/MoOx/pjax.git",
"type": "git",
"url": "https://github.com/MoOx/pjax.git"
},
"homepage": "https://github.com/MoOx/pjax",
"bugs": {
"url": "https://github.com/MoOx/pjax/issues"
},
"author": "Maxime Thirouin", "author": "Maxime Thirouin",
"license": "MIT", "license": "MIT",
"main": "src/pjax.js", "main": "src/pjax.js",
"files": [ "files": [
"CHANGELOG.md",
"LICENSE",
"index.js", "index.js",
"lib" "lib",
"pjax.js"
], ],
"devDependencies": { "devDependencies": {
"browserify": "^3.46.0", "browserify": "^3.46.0",
"coverify": "^1.0.6", "coverify": "^1.0.6",
"jscs": "^1.6.2", "jscs": "^1.6.2",
"jshint": "^2.5.6", "jshint": "^2.5.6",
"npmpub": "^3.1.0",
"serve": "1.4.0",
"tape": "^3.0.0", "tape": "^3.0.0",
"testling": "^1.6.1" "testling": "^1.6.1"
}, },
"scripts": { "scripts": {
"lint": "jscs **/*.js && jshint . --exclude-path .gitignore", "lint": "jscs **/*.js && jshint . --exclude-path .gitignore",
"test": "npm run lint && testling", "standalone": "browserify index.js --standalone Pjax > pjax.js",
"tests": "testling",
"test": "npm run lint && npm run standalone && npm run tests",
"test--html": "testling --html > tests/scripts/index.html", "test--html": "testling --html > tests/scripts/index.html",
"coverage": "browserify -t coverify tests/**/*.js | testling | coverify" "coverage": "browserify -t coverify tests/**/*.js | testling | coverify",
"example": "echo '\n==> Open http://localhost:3000/example in your browser.'; serve .",
"prepublish": "npm run standalone",
"release": "npm test && npmpub --skip-test"
}, },
"testling": { "testling": {
"files": "tests/**/*.js", "files": "tests/**/*.js",
"browsers": [ "browsers": [
"ie/10..latest", "ie/10..latest",
"firefox/4.0", "firefox/latest", "firefox/nightly", "firefox/4.0",
"chrome/10", "chrome/latest", "chrome/canary", "firefox/latest",
"firefox/nightly",
"chrome/10",
"chrome/latest",
"chrome/canary",
"opera/12..latest", "opera/12..latest",
"opera/next", "opera/next",
"safari/5.1..latest", "safari/5.1..latest",

View File

@@ -90,3 +90,21 @@ tape("test events on/off/trigger for multiple elements, multiple events", functi
t.end() t.end()
}) })
tape("test events on top level elements", function(t) {
var el = document;
el.className = ""
on(el, "click", classCb)
trigger(el, "click")
t.equal(el.className, "on", "attached callback has been fired properly on document")
el = window;
el.className = ""
on(el, "click", classCb)
trigger(el, "click")
t.equal(el.className, "on", "attached callback has been fired properly on window")
t.end()
})

View File

@@ -56,3 +56,22 @@ tape("test attach link prototype method", function(t) {
t.end() t.end()
}) })
tape("test attach link preventDefaulted events", function(t) {
var callbacked = false
var a = document.createElement("a")
attachLink.call({
options: {},
loadUrl: function() {
callbacked = true
}
}, a)
a.href = "#"
on(a, "click", preventDefault)
trigger(a, "click")
t.equal(callbacked, false, "events that are preventDefaulted should not fire callback")
t.end()
})

View File

@@ -1,9 +1,41 @@
var tape = require("tape") var tape = require("tape")
// var switchesSelectors = require("../../lib/switches-selectors.js") var switchesSelectors = require("../../lib/switches-selectors.js")
// @author darylteo
tape("test switchesSelectors", function(t) { tape("test switchesSelectors", function(t) {
t.fail() // switchesSelectors relies on a higher level function callback
// should really be passed in instead so I'll leave it here as a TODO:
var pjax = {
onSwitch: function() {
console.log('Switched')
}
}
var tmpEl = document.implementation.createHTMLDocument()
// a div container is used because swapping the containers
// will generate a new element, so things get weird
// using "body" generates a lot of testling cruft that I don't
// want so let's avoid that
var container = document.createElement("div")
container.innerHTML = "<p>Original Text</p><span>No Change</span>"
document.body.appendChild(container)
var container2 = tmpEl.createElement("div")
container2.innerHTML = "<p>New Text</p><span>New Span</span>"
tmpEl.body.appendChild(container2)
switchesSelectors.bind(pjax)(
{}, // switches
{}, // switchesOptions
['p'], //selectors,
tmpEl, // fromEl
document, // toEl,
{} // options
)
t.equals(container.innerHTML, '<p>New Text</p><span>No Change</span>', 'Elements correctly switched')
t.end() t.end()
}) })