-
-
Save devote/4717631 to your computer and use it in GitHub Desktop.
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Basic</title> | |
<script src="/history.js"></script> | |
<script src="/page.js"></script> | |
<script src="/history-plugin.js"></script> | |
</head> | |
<body> | |
<script> | |
if (!window.history.replaceState) { | |
alert('missing replaceState'); | |
} | |
</script> | |
<h1>Basic</h1> | |
<p></p> | |
<ul> | |
<li><a href="./">/</a></li> | |
<li><a href="#whoop">#whoop</a></li> | |
<li><a href="./about">/about</a></li> | |
<li><a href="./contact">/contact</a></li> | |
<li><a href="./not-found?foo=bar">/not-found</a></li> | |
</ul> | |
<script> | |
// the "notfound" implements a catch-all | |
// with page('*', notfound). Here we have | |
// no catch-all, so page.js will redirect | |
// to the location of paths which do not | |
// match any of the following routes | |
page.base('/basic'); | |
page('/', index); | |
page('/about', about); | |
page('/contact', contact); | |
page('*', notfound); | |
page(); | |
function index() { | |
document.getElementsByTagName('p')[0] | |
.innerHTML = 'viewing index'; // IE unsupport textContent | |
} | |
function about() { | |
document.getElementsByTagName('p')[0] | |
.innerHTML = 'viewing about'; | |
} | |
function contact() { | |
document.getElementsByTagName('p')[0] | |
.innerHTML = 'viewing contact'; | |
} | |
function notfound() { | |
document.getElementsByTagName('p')[0] | |
.innerHTML = 'not found'; | |
} | |
</script> | |
</body> | |
</html> |
/** | |
* The plugin includes support for older non-HTML5 browsers for the library: https://github.com/visionmedia/page.js | |
* | |
* Documentation: | |
* Connect on your site library: https://github.com/devote/HTML5-History-API | |
* Next, connect the library: https://github.com/visionmedia/page.js | |
* After them, connect this the plugin. | |
* | |
* Good luck! | |
* | |
* Copyright 2013, Dmitriy Pakhtinov ( spb.piksel@gmail.com ) | |
* | |
* Dual licensed under the MIT and GPL licenses: | |
* http://www.opensource.org/licenses/mit-license.php | |
* http://www.gnu.org/licenses/gpl.html | |
* | |
* Update: 06-02-2013 | |
*/ | |
(function(window, undefined) { | |
// get the version IE | |
var msie = +(((window.eval && eval("/*@cc_on 1;@*/") && /msie (\d+)/i.exec(navigator.userAgent)) || [])[1] || 0), | |
pageStart = page.start, | |
pageStop = page.stop, | |
pageDispatch = page.dispatch, | |
pageReplace = page.replace, | |
pageBase = page.base, | |
// overload 'page.dispatch' method had because of this line | |
location = history.location || window.location; | |
// IE incorrectly generates property '.pathname' in links | |
if (msie && (msie === 8 || msie === 9)) { | |
// fix for this | |
var descriptor = Object.getOwnPropertyDescriptor(HTMLAnchorElement.prototype, 'pathname'); | |
Object.defineProperty(HTMLAnchorElement.prototype, "pathname", { | |
get: function() { | |
var pathname = descriptor.get.call(this); | |
return pathname.indexOf( "/" ) === 0 ? pathname : "/" + pathname; | |
}, | |
set: descriptor.set | |
}); | |
} | |
page.base = function() { | |
if (arguments.length) { | |
history.redirect(undefined, arguments[0].replace(/\/?$/, '/')); | |
} | |
pageBase.apply(page, arguments); | |
} | |
page.start = function(options) { | |
// temporarily replace method | |
page.replace = pReplace; | |
// check the availability of the event model w3c | |
if (!window.addEventListener) { | |
// temporarily add a method | |
window.addEventListener = function(type, callback) { | |
var context = type === 'click' ? document : window; | |
context.attachEvent("on" + type, callback.proxy = function(e){ | |
var event = e || window.event; | |
event.defaultPrevented = event.returnValue === false; | |
var el = event.target = event.srcElement; | |
while (el && 'A' != el.nodeName) el = el.parentNode; | |
if (el && 'A' == el.nodeName) { | |
// emulate event object for work in IE7 | |
event = { | |
which: 1, | |
target: { | |
nodeName: 'A', | |
href: el.href, | |
pathname: el.pathname.indexOf('/') === 0 ? el.pathname : '/' + el.pathname, | |
search: el.search, | |
hash: el.hash, | |
getAttribute: function() {return el.getAttribute('href')} | |
}, | |
preventDefault: function() {window.event.returnValue = false;} | |
} | |
} | |
callback.call(window, event); | |
}); | |
} | |
pageStart.apply(page, arguments); | |
window.addEventListener = undefined; | |
} else { | |
pageStart.apply(page, arguments); | |
} | |
page.replace = pageReplace; | |
} | |
page.stop = function() { | |
// check the availability of the event model w3c | |
if (!window.removeEventListener) { | |
// temporarily add a method | |
window.removeEventListener = function(type, callback) { | |
var context = type === 'click' ? document : window; | |
context.detachEvent("on" + type, callback.proxy); | |
delete callback.proxy; | |
} | |
pageStop.apply(page, arguments); | |
window.addEventListener = undefined; | |
} else { | |
pageStop.apply(page, arguments); | |
} | |
} | |
page.dispatch = function(ctx) { | |
var i = 0; | |
function next() { | |
var fn = page.callbacks[i++]; | |
if (!fn) return unhandled(ctx); | |
fn(ctx, next); | |
} | |
next(); | |
} | |
function unhandled(ctx) { | |
if (location.pathname + location.search == ctx.canonicalPath) return; | |
page.stop(); | |
ctx.unhandled = true; | |
window.location = ctx.canonicalPath; | |
} | |
function pReplace() { | |
arguments[0] = location.pathname + location.search; | |
return pageReplace.apply(page, arguments); | |
} | |
})(window); |
Hmm, it also doesn't seem to work in IE8. I'm using IE9's Browser Mode emulation so maybe that is the cause?
Browser Mode: IE8 Document Mode: IE8 Standards
Missing replaceState and throws this error:
SCRIPT438: Object doesn't support property or method 'addEventListener'
page.js, line 95 character 37
Can you have a try and see if it works for you, please?
Here is the modified basic example page that I am testing with:
<!DOCTYPE html>
<html>
<head>
<title>Basic</title>
<script src="/history.js"></script>
<script src="/page.js"></script>
<script src="/history-plugin.js"></script>
</head>
<body>
<script>
if (!window.history.replaceState) {
alert('missing replaceState');
}
</script>
<h1>Basic</h1>
<p></p>
<ul>
<li><a href="./">/</a></li>
<li><a href="#whoop">#whoop</a></li>
<li><a href="./about">/about</a></li>
<li><a href="./contact">/contact</a></li>
<li><a href="./not-found?foo=bar">/not-found</a></li>
</ul>
<script>
// the "notfound" implements a catch-all
// with page('*', notfound). Here we have
// no catch-all, so page.js will redirect
// to the location of paths which do not
// match any of the following routes
page.base('/basic');
page('/', index);
page('/about', about);
page('/contact', contact);
page();
function index() {
document.querySelector('p')
.textContent = 'viewing index';
}
function about() {
document.querySelector('p')
.textContent = 'viewing about';
}
function contact() {
document.querySelector('p')
.textContent = 'viewing contact';
}
</script>
</body>
</html>
I'm wondering if the issues I'm seeing are due to the express server setup preventing access to the 'history' js files... Behavior matches what I would expect if your history polyfill isn't being loaded at all. But I'm not seeing any errors in the IE9 console...
@alanning: Hi,
Yes there were mistakes and imperfections, which I have corrected. Everything should work well in IE 7-8-9
Please test! Thank you!
Thanks for the update. Unfortunately, the page.js 'basic' test is still not working for me in IE9 or IE8.
There are no errors thrown in IE9 that I can see.
The steps to reproduce and the expected behavior are included below:
-
-
cd page.js
-
npm install
- copy 'history.js' and 'history-plugin.js' files to the 'examples/' directory
- include the code snippet below [1] in the 'examples/index.js' file between the 'Get page.js' and 'Get list of examples.' sections
- include the code snippet below [2] in the 'examples/basic/index.html' file, replacing the existing script include for page.js
-
node examples
- open http://localhost:3000 in IE9
- click 'basic'. See 'viewing index'
- click '/about'. See 'viewing about'
- click '/contact'. See 'viewing contact'
- click browser's Back button. Should see 'viewing about' but still see 'viewing contact'
[1] examples/index.js
/**
* GET history files
*/
app.get('/history.js', function(req, res){
res.sendfile(join(__dirname, '.', 'history.js'));
});
app.get('/history-plugin.js', function(req, res){
res.sendfile(join(__dirname, '.', 'history-plugin.js'));
});
[2] examples/basic/index.html
<!--[if gte IE 7]>
<script src="/history.js"></script>
<![endif]-->
<script src="/page.js"></script>
<!--[if gte IE 7]>
<script src="/history-plugin.js"></script>
<![endif]-->
If your browser go to the address: http://localhost:3000/history.js
you see the contents of the file history.js
? If so, check what Content-Type
the server sends along with the files. Because IE9 does not like bad Content-Type
, for him to send Content-Type: application/javascript
for JavaScript file(s)
Nice work!!
Thanks for writing this and for letting us know about it in the meteor-router IE Support issue thread [1].
I wanted to point out a few things:
I believe this is because the history polyfill sees that most of history is already supported so it doesn't load itself. But IE9 doesn't actually implement a 'replaceState' so technically the polyfill should check for that individually.
[1] tmeasday/meteor-router#33