turbolinks-js 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: