turbolinks-js 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 David Heinemeier Hansson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ Turbolinks-js
2
+ =============
3
+
4
+ Same as [Turbolinks](https://github.com/rails/turbolinks) but without CoffeeScript
5
+ requirement.
6
+
7
+ Turbolinks makes following links in your web application faster. Instead of
8
+ letting the browser recompile the JavaScript and CSS between each page change,
9
+ and potentially spend extra HTTP requests checking if the assets are up-to-date,
10
+ we keep the current instance alive and replace only the body and the title in the
11
+ head. Think CGI vs persistent process.
12
+
13
+ This is similar to pjax, but instead of worrying about what element on the page to
14
+ replace, and tailoring the server-side response to fit, we replace the entire body.
15
+ This means that you get the bulk of the speed benefits from pjax (no recompiling of
16
+ the JavaScript or CSS) without having to tailor the server-side response. It just
17
+ works.
18
+
19
+ By default, all internal links will be funneled through Turbolinks, but you can opt
20
+ out by marking links with data-no-turbolink.
21
+
22
+ No jQuery or any other framework
23
+ --------------------------------
24
+
25
+ Turbolinks is designed to be as light-weight as possible (so you won't think twice about using it even for mobile stuff). It does not require jQuery or any other framework to work.
26
+ But it works great _with_ jQuery or Prototype or whatever else have you.
27
+
28
+ The page:update event
29
+ ---------------------
30
+
31
+ Since pages will change without a full reload with Turbolinks, you can't by default
32
+ rely on `dom:loaded` to trigger your JavaScript code. Instead, Turbolinks uses the
33
+ `page:update` event.
34
+
35
+ Triggering a Turbolinks visit manually
36
+ ---------------------------------------
37
+
38
+ You can use `Turbolinks.visit(path)` to go to a URL through Turbolinks.
39
+
40
+ Available only for pushState browsers
41
+ -------------------------------------
42
+
43
+ Like pjax, this naturally only works with browsers capable of `pushState`. But of
44
+ course we fall back gracefully to full page reloads for browsers that do not support
45
+ it.
46
+
47
+ Work left to do
48
+ ---------------
49
+
50
+ * CSS/JS asset change detection and reload.
51
+ * Add a DOM cache for faster back button.
52
+ * Remember scroll position when using back button.
@@ -0,0 +1,146 @@
1
+ (function() {
2
+ var anchoredLink, browserSupportsPushState, createDocument, crossOriginLink, extractLink, fetchReplacement, fullReplacement, handleClick, ignoreClick, newTabClick, noTurbolink, nonHtmlLink, reflectNewUrl, rememberInitialPage, replaceHTML, triggerPageChange, visit;
3
+
4
+ visit = function(url) {
5
+ if (typeof browserSupportsPushState !== "undefined" && browserSupportsPushState !== null) {
6
+ reflectNewUrl(url);
7
+ return fetchReplacement(url);
8
+ } else {
9
+ return document.location.href = url;
10
+ }
11
+ };
12
+
13
+ fetchReplacement = function(url) {
14
+ var xhr;
15
+ xhr = new XMLHttpRequest;
16
+ xhr.open('GET', url, true);
17
+ xhr.setRequestHeader('Accept', 'text/html, application/xhtml+xml, application/xml');
18
+ xhr.onload = function() {
19
+ return fullReplacement(xhr.responseText, url);
20
+ };
21
+ xhr.onabort = function() {
22
+ return console.log("Aborted turbolink fetch!");
23
+ };
24
+ return xhr.send();
25
+ };
26
+
27
+ fullReplacement = function(html, url) {
28
+ replaceHTML(html);
29
+ return triggerPageChange();
30
+ };
31
+
32
+ reflectNewUrl = function(url) {
33
+ return window.history.pushState({
34
+ turbolinks: true
35
+ }, "", url);
36
+ };
37
+
38
+ triggerPageChange = function() {
39
+ var event;
40
+ event = document.createEvent('Events');
41
+ event.initEvent('page:change', true, true);
42
+ return document.dispatchEvent(event);
43
+ };
44
+
45
+ createDocument = (function() {
46
+ var createDocumentUsingParser, createDocumentUsingWrite, testDoc, _ref;
47
+ createDocumentUsingParser = function(html) {
48
+ return (new DOMParser).parseFromString(html, "text/html");
49
+ };
50
+ createDocumentUsingWrite = function(html) {
51
+ var doc;
52
+ doc = document.implementation.createHTMLDocument("");
53
+ doc.open("replace");
54
+ doc.write(html);
55
+ doc.close;
56
+ return doc;
57
+ };
58
+ if (window.DOMParser) {
59
+ testDoc = createDocumentUsingParser("<html><body><p>test");
60
+ }
61
+ if ((testDoc != null ? (_ref = testDoc.body) != null ? _ref.childNodes.length : void 0 : void 0) === 1) {
62
+ return createDocumentUsingParser;
63
+ } else {
64
+ return createDocumentUsingWrite;
65
+ }
66
+ })();
67
+
68
+ replaceHTML = function(html) {
69
+ var doc, originalBody, title;
70
+ doc = createDocument(html);
71
+ originalBody = document.body;
72
+ document.documentElement.appendChild(doc.body, originalBody);
73
+ document.documentElement.removeChild(originalBody);
74
+ if (title = doc.querySelector("title")) {
75
+ return document.title = title.textContent;
76
+ }
77
+ };
78
+
79
+ extractLink = function(event) {
80
+ var link;
81
+ link = event.target;
82
+ while (!(link === document || link.nodeName === 'A')) {
83
+ link = link.parentNode;
84
+ }
85
+ return link;
86
+ };
87
+
88
+ crossOriginLink = function(link) {
89
+ return location.protocol !== link.protocol || location.host !== link.host;
90
+ };
91
+
92
+ anchoredLink = function(link) {
93
+ return ((link.hash && link.href.replace(link.hash, '')) === location.href.replace(location.hash, '')) || (link.href === location.href + '#');
94
+ };
95
+
96
+ nonHtmlLink = function(link) {
97
+ return link.href.match(/\.[a-z]+$/g) && !link.href.match(/\.html?$/g);
98
+ };
99
+
100
+ noTurbolink = function(link) {
101
+ return link.getAttribute('data-no-turbolink') != null;
102
+ };
103
+
104
+ newTabClick = function(event) {
105
+ return event.which > 1 || event.metaKey || event.ctrlKey;
106
+ };
107
+
108
+ ignoreClick = function(event, link) {
109
+ return crossOriginLink(link) || anchoredLink(link) || nonHtmlLink(link) || noTurbolink(link) || newTabClick(event);
110
+ };
111
+
112
+ handleClick = function(event) {
113
+ var link;
114
+ link = extractLink(event);
115
+ if (link.nodeName === 'A' && !ignoreClick(event, link)) {
116
+ visit(link.href);
117
+ return event.preventDefault();
118
+ }
119
+ };
120
+
121
+ browserSupportsPushState = window.history && window.history.pushState && window.history.replaceState;
122
+
123
+ rememberInitialPage = function() {
124
+ return window.history.replaceState({
125
+ turbolinks: true
126
+ }, "", document.location.href);
127
+ };
128
+
129
+ if (browserSupportsPushState) {
130
+ rememberInitialPage();
131
+ window.addEventListener('popstate', function(event) {
132
+ var _ref;
133
+ if ((_ref = event.state) != null ? _ref.turbolinks : void 0) {
134
+ return fetchReplacement(document.location.href);
135
+ }
136
+ });
137
+ document.addEventListener('click', function(event) {
138
+ return handleClick(event);
139
+ });
140
+ }
141
+
142
+ this.Turbolinks = {
143
+ visit: visit
144
+ };
145
+
146
+ }).call(this);
data/lib/turbolinks.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Turbolinks
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
data/test/config.ru ADDED
@@ -0,0 +1,14 @@
1
+ require 'sprockets'
2
+ require 'coffee-script'
3
+
4
+ Root = File.expand_path("../..", __FILE__)
5
+
6
+ Assets = Sprockets::Environment.new do |env|
7
+ env.append_path File.join(Root, "lib", "assets", "javascripts")
8
+ end
9
+
10
+ map "/js" do
11
+ run Assets
12
+ end
13
+
14
+ run Rack::Directory.new(Root)
data/test/index.html ADDED
@@ -0,0 +1,20 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Home</title>
6
+ <script type="text/javascript" src="/js/turbolinks.js"></script>
7
+ <script type="text/javascript">
8
+ document.addEventListener("page:change", function() {
9
+ console.log("page changed");
10
+ });
11
+ </script>
12
+ </head>
13
+ <body>
14
+ <ul>
15
+ <li><a href="/test/other.html">Other page</a></li>
16
+ <li><a href="/test/other.html"><span>Wrapped link</span></a></li>
17
+ <li><a href="http://www.google.com/">Cross origin</a></li>
18
+ </ul>
19
+ </body>
20
+ </html>
data/test/other.html ADDED
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Home</title>
6
+ <script type="text/javascript" src="/js/turbolinks.js"></script>
7
+ <script type="text/javascript">
8
+ document.addEventListener("page:change", function() {
9
+ console.log("page changed");
10
+ });
11
+ </script>
12
+ </head>
13
+ <body>
14
+ <ul>
15
+ <li><a href="/test/index.html">Home</a></li>
16
+ </ul>
17
+ </body>
18
+ </html>
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: turbolinks-js
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - David Heinemeier Hansson
9
+ - Francesco Rodriguez
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-09-27 00:00:00.000000000 Z
14
+ dependencies: []
15
+ description:
16
+ email:
17
+ - lrodriguezsanc@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - lib/assets/javascripts/turbolinks.js
23
+ - lib/turbolinks.rb
24
+ - README.md
25
+ - MIT-LICENSE
26
+ - test/config.ru
27
+ - test/index.html
28
+ - test/other.html
29
+ homepage:
30
+ licenses: []
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 1.8.23
50
+ signing_key:
51
+ specification_version: 3
52
+ summary: Turbolinks-js makes following links in your web application faster (use with
53
+ Rails Asset Pipeline). No CoffeeScript requirement.
54
+ test_files: []
55
+ has_rdoc: