Coder Social home page Coder Social logo

turbolinks / turbolinks-classic Goto Github PK

View Code? Open in Web Editor NEW
3.5K 127.0 428.0 715 KB

Classic version of Turbolinks. Now deprecated in favor of Turbolinks 5.

License: MIT License

Ruby 30.14% Shell 0.31% HTML 11.09% JavaScript 2.25% CoffeeScript 56.20%

turbolinks-classic's Introduction

Turbolinks Classic is now deprecated

Turbolinks 5 is a ground-up rewrite with a new flow, new events, but the same core idea. It's available at turbolinks/turbolinks. This repository remains available for existing applications built on what we now call Turbolinks Classic.

Turbolinks

Turbolinks makes following links in your web application faster. Instead of letting the browser recompile the JavaScript and CSS between each page change, it keeps the current page instance alive and replaces only the body (or parts of) and the title in the head. Think CGI vs persistent process.

This is similar to pjax, but instead of worrying about what element on the page to replace and tailoring the server-side response to fit, we replace the entire body by default, and let you specify which elements to replace on an opt-in basis. This means that you get the bulk of the speed benefits from pjax (no recompiling of the JavaScript or CSS) without having to tailor the server-side response. It just works.

Do note that this of course means that you'll have a long-running, persistent session with maintained state. That's what's making it so fast. But it also means that you may have to pay additional care not to leak memory or otherwise bloat that long-running state. That should rarely be a problem unless you're doing something really funky, but you do have to be aware of it. Your memory leaking sins will not be swept away automatically by the cleansing page change any more.

No jQuery or any other library

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 library to work. But it works great with the jQuery framework, or whatever else you have.

Events

With Turbolinks pages will change without a full reload, so you can't rely on DOMContentLoaded or jQuery.ready() to trigger your code. Instead Turbolinks fires events on document to provide hooks into the lifecycle of the page.

Event Argument originalEvent.data Notes
page:before-change {url} The page is about to change. Cancellable with event.preventDefault(). Does not fire on history back/forward.
page:fetch {url} A new page is about to be fetched from the server.
page:receive {url} A page has been fetched from the server, but not yet parsed.
page:before-unload [affectedNodes] Nodes are about to be changed.
page:change [affectedNodes] Nodes have changed. Also fires on DOMContentLoaded.
page:update Fired alongside both page:change and jQuery's ajaxSuccess (if available).
page:load [newBody] A new body element has been loaded into the DOM. Does not fire on partial replacement or when a page is restored from cache, so as not to fire twice on the same body.
page:partial-load [affectedNodes] New elements have been loaded into the DOM via partial replacement.
page:restore A cached body element has been loaded into the DOM.
page:after-remove affectedNode An element has been removed from the DOM or body evicted from the cache and must be cleaned up. jQuery event listeners are cleaned up automatically.

Example: load a fresh version of a page from the server

  • page:before-change link clicked or Turbolinks.visit() called (cancellable)
  • page:fetch about to send XHR
  • page:receive received response from server
  • page:before-unload ([currentBody]) page has been parsed and is about to be changed
  • page:change ([newBody]) new body is in place
  • page:update
  • page:load ([newBody]) page has been loaded (progress bar hidden, scroll position updated)
  • page:after-remove (oldBody) an old body has been evicted from the cache

Example: partial replacement with Turbolinks.replace()

  • page:before-unload ([currentNodes...]) nodes are about to be changed
  • page:after-remove (currentNode) a node has been removed from the DOM and must be cleaned up (fires once per node)
  • page:change ([newNodes...]) new nodes are in place
  • page:update
  • page:partial-load ([newNodes...])

Example lifecycle setup:

// using jQuery for simplicity

$(document).on('ready', function(event) {
  // initialize persistent state
});

$(document).on('ready page:load', function(event) {
  // apply non-idempotent transformations to the body
});

$(document).on('page:partial-load', function(event) {
  // apply non-idempotent transformations to the nodes in event.originalEvent.data
});

$(document).on('page:change', function(event) {
  // idempotent function
});

$(document).on('page:after-remove', function(event) {
  // delete references to the nodes in event.originalEvent.data to prevent memory leaks
});

Page Cache

By default, Turbolinks keeps 10 pages in memory (the full body element is kept in memory, so as not to lose state). On popstate, it attempts to restore pages from the cache. When a page exists in the cache, the following events are triggered:

  • page:before-unload ([currentBody]) page is about to be changed
  • page:change ([cachedBody]) body from cached page is in place
  • page:restore

The number of pages Turbolinks caches can be configured to suit your application's needs:

Turbolinks.pagesCached(); // View the current cache size
Turbolinks.pagesCached(20); // Set the cache size

If you need to make dynamic HTML updates in the current page and want it to be cached properly you can call:

Turbolinks.cacheCurrentPage();

Note: performing a partial replacement with URL change will remove the current page from the cache. This is because the replaced nodes cannot be brought back. If the user clicks the back button following a visit with partial replacement, the previous page will be fetched from the server.

Transition Cache: A Speed Boost

Transition Cache makes loading cached pages instantaneous. Once a user has visited a page, returning later to the page results in an instant load.

For example, if Page A is already cached by Turbolinks and you are on Page B, clicking a link to Page A will immediately display the cached copy of Page A. Turbolinks will then fetch Page A from the server and replace the cached page once the new copy is returned.

To enable Transition Cache, include the following in your javascript:

Turbolinks.enableTransitionCache();

The one drawback is that dramatic differences in appearance between a cached copy and new copy may lead to a jarring affect for the end-user. This will be especially true for pages that have many moving parts (expandable sections, sortable tables, infinite scrolling, etc.).

If you find that a page is causing problems, you can have Turbolinks skip displaying the cached copy by adding data-no-transition-cache to any DOM element on the offending page.

Progress Bar

Because Turbolinks skips the traditional full page reload, browsers won't display their native progress bar when changing pages. To fill this void, Turbolinks offers a JavaScript-and-CSS-based progress bar to display page loading progress (as of v3.0, the progress bar is turned on by default).

To disable (or re-enable) the progress bar, include one of the following in your JavaScript:

Turbolinks.ProgressBar.disable();
Turbolinks.ProgressBar.enable();

The progress bar is implemented on the <html> element's pseudo :before element and can be customized by including CSS with higher specificity than the included styles. For example:

html.turbolinks-progress-bar::before {
  background-color: red !important;
  height: 5px !important;
}

Control the progress bar manually using these methods:

Turbolinks.ProgressBar.start();
Turbolinks.ProgressBar.advanceTo(value); // where value is between 0-100
Turbolinks.ProgressBar.done();

Initialization

Turbolinks will be enabled only if the server has rendered a GET request.

Why not all request types? Some browsers track the request method of each page load, but triggering pushState methods doesn't change this value. This could lead to the situation where pressing the browser's reload button on a page that was fetched with Turbolinks would attempt a POST (or something other than GET) because the last full page load used that method.

Opting out of Turbolinks

By default, all internal HTML links will be funneled through Turbolinks, but you can opt out by marking links or their parent container with data-no-turbolink. For example, if you mark a div with data-no-turbolink, then all links inside of that div will be treated as regular links. If you mark the body, every link on that entire page will be treated as regular links.

<a href="/">Home (via Turbolinks)</a>
<div id="some-div" data-no-turbolink>
  <a href="/">Home (without Turbolinks)</a>
</div>

Note that internal links to files containing a file extension other than .html will automatically be opted out of Turbolinks. To whitelist additional file extensions to be processed by Turbolinks, use Turbolinks.allowLinkExtensions().

Turbolinks.allowLinkExtensions();                 // => ['html']
Turbolinks.allowLinkExtensions('md');             // => ['html', 'md']
Turbolinks.allowLinkExtensions('coffee', 'scss'); // => ['html', 'md', 'coffee', 'scss']

Also, Turbolinks is installed as the last click handler for links. So if you install another handler that calls event.preventDefault(), Turbolinks will not run. This ensures that you can safely use Turbolinks with things like data-method, data-remote, or data-confirm from Rails.

Note: in v3.0, the default behavior of redirect_to is to redirect via Turbolinks on XHR + non-GET requests. You can opt-out of this behavior by passing turbolinks: false to redirect_to.

By default, Turbolinks includes itself in ActionController::Base. To opt out of the Turbolinks features in certain controllers (redirect_to behavior, request_method cookie, X-XHR-Referer referrer check, etc.), set config.turbolinks.auto_include to false in application.rb and include Turbolinks::Controller in the controllers where you use Turbolinks.

jquery.turbolinks

If you have a lot of existing JavaScript that binds elements on jQuery.ready(), you can pull the jquery.turbolinks library into your project that will trigger ready() when Turbolinks triggers the page:load event. It may restore functionality of some libraries.

Add the gem to your project, then add the following line to your JavaScript manifest file, after jquery.js but before turbolinks.js:

//= require jquery.turbolinks

Additional details and configuration options can be found in the jquery.turbolinks README.

Asset change detection

You can track certain assets, like application.js and application.css, that you want to ensure are always of the latest version inside a Turbolinks session. This is done by marking those asset links with data-turbolinks-track, like so:

<link href="/assets/application-9bd64a86adb3cd9ab3b16e9dca67a33a.css" rel="stylesheet"
      type="text/css" data-turbolinks-track>

If those assets change URLs (embed an md5 stamp to ensure this), the page will do a full reload instead of going through Turbolinks. This ensures that all Turbolinks sessions will always be running off your latest JavaScript and CSS.

When this happens, you'll technically be requesting the same page twice. Once through Turbolinks to detect that the assets changed, and then again when we do a full redirect to that page.

Evaluating script tags

Turbolinks will evaluate any script tags in pages it visits, if those tags do not have a type or if the type is text/javascript. All other script tags will be ignored.

As a rule of thumb when switching to Turbolinks, move all of your javascript tags inside the head and then work backwards, only moving javascript code back to the body if absolutely necessary. If you have any script tags in the body you do not want to be re-evaluated then you can set the data-turbolinks-eval attribute to false:

<script type="text/javascript" data-turbolinks-eval=false>
  console.log("I'm only run once on the initial page load");
</script>

Turbolinks will not re-evaluate script tags on back/forward navigation, unless their data-turbolinks-eval attribute is set to always:

<script type="text/javascript" data-turbolinks-eval=always>
  console.log("I'm run on every page load, including history back/forward");
</script>

Triggering a Turbolinks visit manually

You can use Turbolinks.visit(path) to go to a URL through Turbolinks.

You can also use redirect_to path, turbolinks: true in Rails to perform a redirect via Turbolinks.

Client-side API

Turbolinks

Function Arguments Notes
visit() path, options Load a new page and change the URL.
replace() stringOrDocumentoptions Replace the current page without changing the URL.
Option Type Notes
change Array Replace only the nodes with the given ids.
append Array Append the children of nodes with the given ids.
prepend Array Prepend the children of nodes with the given ids.
keep Array Replace the body but keep the nodes with the given ids.
flush Boolean Replace the body, including data-turbolinks-permanent nodes.
title Boolean or String If false, don't update the document title. If a string, set the value as title.
scroll Boolean If false, don't scroll to top (or #target) after the page is loaded.
cacheRequest Boolean Enable/disable the request cache.
showProgressBar Boolean Show/hide the progress bar during the request.
Function Arguments Notes
pagesCached() None or Number Get or set the maximum number of pages that should be cached.
cacheCurrentPage()
enableTransitionCache()
disableRequestCaching()
allowLinkExtensions() String... Whitelist additional file extensions to be processed by Turbolinks.
Property Notes
supported true if the browser fully supports Turbolinks.
EVENTS Map of event names.

Turbolinks.ProgressBar

Function Arguments Notes
enable()
disable()
start()
advanceTo() Number Value must be between 0 and 100.
done()

Full speed for pushState browsers, graceful fallback for everything else

Like pjax, this naturally only works with browsers capable of pushState. But of course we fall back gracefully to full page reloads for browsers that do not support it.

Note: there is currenty no fallback for partial replacement on browsers that don't support pushState.

Compatibility

Turbolinks is designed to work with any browser that fully supports pushState and all the related APIs. This includes Safari 6.0+ (but not Safari 5.1.x!), IE10, and latest Chromes and Firefoxes.

Do note that existing JavaScript libraries may not all be compatible with Turbolinks out of the box due to the change in instantiation cycle. You might very well have to modify them to work with Turbolinks's new set of events. For help with this, check out the Turbolinks Compatibility project.

Turbolinks works with Rails 3.2 and newer.

Known issues

  • External scripts are not guaranteed to execute in DOM order (#513)
  • Iframes in data-turbolinks-permanent nodes are reloaded on page load (#511)
  • Audio and video elements in data-turbolinks-permanent nodes are paused on page load (#508)
  • Partial replacement removes pages from the cache (#551)

Installation

  1. Add gem 'turbolinks' to your Gemfile.
  2. Run bundle install.
  3. Add //= require turbolinks to your Javascript manifest file (usually found at app/assets/javascripts/application.js). If your manifest requires both turbolinks and jQuery, make sure turbolinks is listed after jQuery.
  4. Restart your server and you're now using turbolinks!

Running the tests

Ruby:

rake test:all

BUNDLE_GEMFILE=Gemfile.rails42 bundle
BUNDLE_GEMFILE=Gemfile.rails42 rake test

JavaScript:

bundle install
npm install

script/test   # requires phantomjs >= 2.0
script/server # http://localhost:9292/javascript/index.html

Language Ports

These projects are not affiliated with or endorsed by the Rails Turbolinks team.

Credits

Thanks to Chris Wanstrath for his original work on Pjax. Thanks to Sam Stephenson and Josh Peek for their additional work on Pjax and Stacker and their help with getting Turbolinks released. Thanks to David Estes and Nick Reed for handling the lion's share of post-release issues and feature requests. And thanks to everyone else who's fixed or reported an issue!

turbolinks-classic's People

Contributors

arthurnn avatar benweint avatar davydotcom avatar dhh avatar frankshowalter avatar glebm avatar ilucin avatar javan avatar jonwolfe avatar josh avatar keram avatar kristianpd avatar mala avatar marcamillion avatar mattbrictson avatar mgotink avatar phallguy avatar rafaelfranca avatar readmecritic avatar reed avatar rhardih avatar rjspotter avatar rmosolgo avatar smidwap avatar spadin avatar stevenbristol avatar thibaut avatar timruffles avatar vickash avatar yasuoza avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

turbolinks-classic's Issues

configurable cache element

I've just hacked together a quick implementation of specifying a configurable cache element, so you can do something like this:

Turbolinks.setup({cache_id: 'main_container'});

For instances where you don't want to refresh the entire body. I have this requirement on two projects I'm working on so thought it might be a common case. Thoughts?

Cache issue when mixing 'back' button an Turbolink visit

Found an odd bug but I can't seem to track down how to fix the problem.

Steps to reproduce:

  1. Start at http://localhost:9292/test/index.html
  2. Click the Other page link.
  3. Hit the back button on the browser.
  4. Click the Other page link.
  5. Click the Home link.
  6. Hit the back button on the browser.

You'd expect to see the other.html page which is a single link, but nothing changes and instead you see the content for index.html

jQuery UI tips and tricks

Just leaving some notes for some things i noticed when using jQuery ui components (particularly the datepicker)..

When a page has changed, the .datepicker has not reinitialized because it doesnt check to see if its datePicker div has been removed from the dom, but it has.

To correct this you can do something like this...

jQuery.datepicker.dpDiv.appendTo( jQuery('body') );

I updated this solution per @rpflorence ... thanks for the catch.

extractAssets should ignore certain types?

Hi - I've been using Pjax in a limited scope for a while, but only just started trying out Turbolinks in our app, so forgive me if I'm missing something.

I'm struggling with the assetsChanged method always returning true for pretty much any two pages on our site, which then results in Turbolinks doing a full page reload. We have a number of oembed <link> tags in our pages, as well as specialised RSS <links> for differing areas of the site, and some legacy Facebook <link> tags like rel=image_src.

I'm wondering if it would make sense to be able to tell Turbolinks to ignore link tags with certain type or rel attributes (eg "application/xml+oembed"). There are obvious problems with that approach - eg the ombed tags would still refer to an old page, but since they're intended for machine consumption only perhaps it doesn't matter. (RSS is a bit trickier... ideally you might replace the old RSS tags in the head with the new ones, though I'm not even sure if browsers would notice the change. Maybe that doesn't matter though, since having an RSS button in your browser chrome seems to be rapidly disappearing.)

Any thoughts? Or am I doing it wrong?

Some inline script tags not being evaluated

If you have a script tag at the bottom of a form...to say initialize custom elements in the form. This script tag is not being evaluated from a turbolink. It is not a dom ready issue, it simply does not get evaluated by the dom writer.

Not sure what the issue is here, difficult to track down. If i put a script tag at the top of the body element it seems to evaluate it. its down further where it does not.

302 redirects do not seem to work

It seems that when you click on a link where a 302 redirect is made, the content is changed but the url in the browser reflects the url before the redirect.

Example :

  • When I click on http://example.com/carts/42/line_items?item_id=123
  • I should be redirect to http://example.com/my_cart
  • The content is the good one, but the url is http://example.com/carts/42/line_items?item_id=123 in the navbar

Twitter Button breaks Turbolinks?

Hi,

I tried to get Turbolinks working on a project I'm playing around with but I couldn't figure why it didn't worked. Then I grabed this example project from Railscasts and searched along. It seems that as soon as I add an embeded Twitter button Turbolinks stops working. Is there any workaround or fix?

Thanks

reset scroll position on page replacement

It's really annoying then you visit a link with shorter content and being greeted with a blank page, having to scroll up to see the content. I just experimented with resetting the scroll position to 0,0 on successful fetch and it feels much more natural:

xhr.onload  = ->
    changePage extractTitleAndContent(xhr.responseText)...
    reflectRedirectedUrl xhr
    resetScrollPosition()
    triggerEvent 'page:load'

resetScrollPosition = ->
  window.scrollTo 0, 0

Page goes blank with LiveReload in footer

I use LiveReload for instantly updating CSS, etc changes on my Rails sites.
I've just installed turbolinks on one of my Rails apps and the page just shows blank when clicking any links.

When removing the LiveReload script from the footer the site works OK and wow the site is much faster!

Lost Anchor #

Turbolinks seems to loose the anchor on page:change.

Given a link href="/foo/bar#100" it will show this link in the URL until page:change is triggered.

After that it's just "/foo/bar".

Could someone confirm this behaviour?

Post request instead of get when hitting refresh

After making a post action which don't redirects you (error messages i.e), if you navigate to any link and then hit refresh, the browser (Chrome at least) tries to refresh the current url with a post request.

Thanks for all the awesome stuff you are sharing <3
Matt

Incompatible with Chrome for iOS

There are some pushState-related differences from Mobile Safari in Chrome for iOS that cause Turbolinks not to work. Here's what I've found:

  1. rememberInitialPage runs on the first call to visit in Mobile Safari, but in Chrome for iOS it runs as soon as the page loads.
  2. In Mobile Safari, the window.history.state access in rememberCurrentState reflects the state that was set in the previous call to replaceState in rememberCurrentUrl. In Chrome for iOS, window.history.state is null in rememberCurrentState, so currentState is null too.
  3. Because currentState is null in Chrome for iOS on the first call to visit, cacheCurrentPage fails. If you explicitly call Turbolinks.visit, the end result is the page never loads. If you click a link, it will fall back to a full page load.

Events observed in script tags are still observed when changing page

Related to #58 (JS script tags of pages visited with turbolinks are executed).

If you observe events in one of these script tags, when you go to another page, the event handler is not removed.
It's problematic, for different reasons, one of them is that if you come back to this page, the event handler are executed twice (or three times if you come back another time, etc.)

Firefox 15 Ubuntu.

Works fine in Chrome on Ubuntu. Firefox 15 on Ubuntu returns a white screen, you can reload the page to get the requested page.

Canceling confirm popup still goes to path in link

<a href="/users" class="btn btn-danger float_right" data-confirm="Are you sure?" data-method="delete" rel="nofollow">Cancel my account</a>

When I click on this link and then click cancel on the confirmation popup a GET request is made to /users instead of canceling the request.

If I click ok in the confirmation popup the delete is processed correctly. Using a full url instead of the relative path for the href, removing turbolinks, or adding data-no-turbolink fix this issue.

Based on the documentation shouldn't turbolinks catch this since I have data-confirm and data-method in the link?

This is the devise cancel my account link from the template it generates.

suggestion for turboforms

I've got an implementation of turboforms working which hijacks all 'normal' forms on the page and sends then asynchronously, replacing the body with the result. This example is rails-specific but could be made generic:

extractUrlTitleAndBody = (content) ->
  doc = createDocument content
  url = doc.querySelector('meta[name=currentPath]').getAttribute('content')
  title = doc.querySelector 'title'
  [ url, title?.textContent, doc.body ]

setContent = (url, title, body) ->
  cacheCurrentPage()
  reflectNewUrl url
  changePage title, body

turboforms = () ->
  $('form:not([data-remote]),a[data-turboform]').each (index, el) =>
    el = $(el)
    el.attr('data-remote', 'true')
    el.bind 'ajax:beforeSend', (event, data, status, xhr) =>
      triggerEvent 'page:fetch'
    el.bind '[RemoteForm] ajax:success', (event, data, status, xhr) =>
      setContent extractUrlTitleAndBody(xhr.responseText)...
      triggerEvent 'page:load'

It raises two questions

  1. is turboforms something people want?
  2. this could be made as an extension to turbolinks (this is kind of how I'm hooking into it). The turbolinks api doesn't really allow for this at present but could easily be exposed to allow for extensions like this

Safari 5 not supported

It appears Safari 5.1.7 does not support window.history.state which was introduced in commit 185dec1. Since it degrades gracefully I can understand if you don't want to support this version, but I wanted others to be aware of it in case they try to test Turbolinks behavior on this version.

Perhaps it should state somewhere in the readme which browser versions are supported? This can help when developers are testing and debugging on various browsers. If developers are unknowingly using an unsupported browser they would not notice JavaScript that is incompatible with Turbolinks.

Reload the page when detecting a change in assets

Turbolinks should keep an index of external assets from the first page hit. Imagine these two assets declared in the HEAD:

<link  href="https://d3dma7a8zw52bz.cloudfront.net/assets/application-9ce82b8e23611aebdd79033e8063d82f.css" media="all" rel="stylesheet" type="text/css" />
<script  src="https://d3dma7a8zw52bz.cloudfront.net/assets/application-983dc7ef267ab91bed1488896e7a6f6c.js" type="text/javascript"></script>

Turbolinks should extract the two urls and then compare each subsequent request against them. If there's a change in the URL, it should do a full page reload instead of just turbolinking, such that the new CSS or JS can be reflected.

jCarouselLite stopped working after implementing Turbolinks

I have a slider of images with jCarouselLite, this stopped working after adding Turbolinks to the project.

All though this is the only page where the jCarouselLite slider isnt working:

$('#employees_slider').jCarouselLite({
      auto: 0,
      visible: 4,
      start: 0,
      speed: 2000,
      btnNext: ".right",
      btnPrev: ".left"
    });
= link_to (image_tag 'left.png', :class => 'left', :width => "48"), ""
= link_to (image_tag 'right.png', :class => 'right', :width => "48", :style => "float:right;"), ""
#employees_slider
  %ul.employee_images
    - @employees.each do |employee|
      %li{:style => "width:200px !important;margin-right: 25px !important;"}
        - if !employee.remote_image_url.nil?
          = image_tag employee.remote_image_url, :id => "employee_#{employee.id}", :class => "employee_image"
        - else
          = image_tag employee.image, :id => "employee_#{employee.id}", :class => "employee_image"
        %p.employee_info{:id => "info_#{employee.id}"}
          = employee.name
          %br/
          = employee.title
          %br/
          %b=t ".email"
          = employee.email
          %br/
          %b=t ".phone"
          = employee.phone

Possibility to replace meta tags

Hi,

Currently turbolinks replaces only body and title as far as I know.

I needed to also replace other meta tags such as opengraph and HTML5 microdata.

<meta property="og:title" content="Article title"/>
<meta property="og:type" content="article"/>
<meta property="og:url" content="http://news.com/items/1228"/>
<meta property="og:site_name" content="News Agency"/>
<meta property="og:description" content="news"/>
<meta property="article:tag" content="Science"/>
<meta property="og:image" content="https://url.to/thumb.jpg"/>

What would be the best approach? maybe use javascript?

Things that need a bit of clarification…

So following the idea from the readme: "So if you wanted to have a client-side spinner, you could listen for page:fetch to start it and page:change to stop it."

Probably startSpinner() would insert some element ("Loading…") into the body. However as on page:change, the body has been replaced, so the inserted object would have been gone. I do not see an easy and obvious way to gracefully end the spinner, it would just disappear.

Something else:
For action specific javascript, I usually have a siteName.controllerName.actionName js namespace and would call its init() method from the view.
How would I translate that to turbolinks? I have not the slightest idea, what controller or action is served to me (if not by some hack, where I would place some

in my body and parse that).

page:load on first load or back

I'm probably missing something, but it does not seem that page:load is triggered on reload or back (or on first load) of a page.
Is this what is supposed to happen? And if so, what is the best way to catch these events using page:load?

Thanks!

Code used in application.js:

document.addEventListener("page:load", function(){
  alert("loaded");
})

Problems integrating Turbolinks with Facebook JS SDK

This is not really a Turbolinks issue but a problem I guess many will run into using the Facebook JS SDK. The SDK is initiliazed inside the HTML body like this: https://developers.facebook.com/docs/reference/javascript/

When the SDK initializes, it creates a fb-root iframe tag to communicate with the FB API. When Turbolinks reloads the page, the fb-root tag vanishes and there doesn't seem to be a way trigger the re-initilialization of the Facebook sdk.

I'm trying to figure out the best way to handle this. Can an element of the body remain in between two requests? How can inline javascript be executed? (Let me know I should repost to Stack Overflow instead)

ConstrainPageCacheTo(10) doesn't work when history limit reached

In Chrome, the history limit is apparently 50, and when we reach this limit, this line :
delete pageCache[currentState.position - limit] if currentState.position == window.history.length - 1
doesn't work anymore, so the pageCache grows out of its limit of 10.

Removing body also removes event listeners on body

Javascript libraries like Twitter Bootstrap put event listeners on body.

Such as:
https://github.com/twitter/bootstrap/blob/master/js/bootstrap-alert.js
https://github.com/twitter/bootstrap/blob/master/js/bootstrap-modal.js

By replacing body, these event listeners are removed and events aren't handled after a page is changed.

Replacing the body's innerHTML with the replacement body's innerHTML has the correct functionality in these situations. But then you sacrifice cases in which you want to change the body element, its attributes, and listeners.

Perhaps there could be a data attribute on body which configures body replacement for the uncommon case. For example, you could specify data-turbolinks-replaceinner="true" on body and when the page is replaced, it replaces the body's innerHTML and leaves the body element with its listeners.

WDYT?

Just stopped working, Google Maps set assetsChanged to true

Today my turbolinks just stopped working. Everything worked yesterday and I have not done any updates. Turbolinks do not even work when i disable all my other javascript files (I use Rails 3.2.8 and have commented out everything exept jquery, jquery_ujs and turbolinks in my application.js).
I have tried to trigger turbolinks manually with Turbolinks.visit(path) but it is the same.

Now when i click on a link, the browser makes a GET request with the new page like it's expected to do but the get response contains the full page and not only the body. After the get request are done, browser do a full page reload.

I have set a brek point in firebug (line 14) to test if the broswer support pushstate and it does, breakpoint never triggered.

I have uninstalled the gem, cleared catch, tested in FireFox 16.0.1, Chrome 22.0.1 and Safari 6.0.1, everything are the same!

Please, help me to solve this really annoying problem. I haven't done any changes since yesterday and then everything worked fine.

Edit,
I installed Oh My ZSH yesterday but guess it does not matter.

Issues with bootstrap plugins

Hi, I looking for the best way to do that.. don't know if it could be fixed in turbolinks, in bootstrap, or anywhere...

But, I recently created a question in stackoverflow, and found that's the strange behavior is because the way of modal plugins of bootstrap were implemented.

Maybe it is a possible hack to do with that, to made it work...

Back button and reload can cause the wrong page to display

Misbehavior

  1. Open a page that uses turbolinks. Call this Page 1.
  2. Click a link to another page on the site using turbolinks. Call this Page 2.
  3. Click the Back button to get back to Page 1.
  4. Click the Reload button.
  5. Click the link to Page 2 again.
  6. Click the Reload button.
  7. Click the Back button.

You will now be looking at Page 2 but Page 1's address is in the address bar.

This happens for me in Firefox 16, Chrome 22, and Safari 6.

Cause

Turbolinks' page cache ids (state.position values) start at window.history.length - 1. When you hit the back button, window.history.length doesn't change. Hitting reload makes Turbolinks restart its id numbering at window.history.length - 1. Certain dances involving back and reload can cause two different pages to have the same state.position in the browser's records, making Turbolinks pull the wrong page from its own cache.

In the case above, assuming you started with a new tab, window.history.length == 3 from step 2 onward. In step 5, Turbolinks tells the browser Page 1's state.position is 2. In step 7, Turbolinks tells the browser Page 2's state.position is also 2. Turbolinks puts Page 2 in its cache, then processes the popstate event to load Page 1. Since Page 1's state.position is 2, it just pulls Page 2 out of the cache, thinking it's Page 1.

Suggested Fix

Instead of window.history.length-1, you could use new Date().getTime()

Integration with fancyBox (v1.3.4)

Hi,

I'm having issues with fancyBox integration.

When I reload gallery page everything works as expected.

When I go to gallery page using turbolink the image preview modal is not working.

I'm not getting any js errors.

Here is my application.js

document.addEventListener("page:load", function(){
  init('load');
});

document.addEventListener("page:change", function(){
  init('change');
});

$(document).ready(function() {
  init('ready');
});

function init(msg) {
  $("a.fancybox").fancybox();
  alert(msg);
}

Thanks in advance,
Marek

redirect_to in before_filter does not update address in address bar...

In my application (as in most applications), my ApplicationController handles authorization.

I have a before_filter method in my UserSessions controller:

before_filter :require_guest, only: [:new, :create]

which calls the method within ApplicationController:

def require_guest
  redirect_to user_path, notice: 'You are already registered and logged-in.' if current_user
end

This keeps people from trying to log-in when they're already logged-in.

When turbolinks is active, the redirect happens in the browser window and an alert is shown to the user (expected behavior). However, the URL in the address bar still shows 'site.com/login' (the URL for UserSessions#new).

Integration problem with Stripe Button

I'm trying to integrate the new Stripe Button as described here : https://stripe.com/docs/button

The button shows up fine on a fresh page load but doesn't show at all when the page is loaded with Turbolink. here is the exact code :

<form action="/charge" method="post">
  <script src="https://button.stripe.com/v1/button.js" class="stripe-button" data-key="YOUR_KEY"></script>
</form>

The JS file has no initialization method. It just executes when it's loaded. Is that a use case that should work with Turbolinks? I see inline JS should load fine but I'm not sure about external scripts.

Doesn't appear to respect data-confirm...

I have the following in my layout:

%a{href: user_applications_path, data: {confirm: 'Are you sure you want to navigate away from this page? All unsaved data will be lost.' }}

When this link is clicked, an alert is displayed, as-expected. However, if I click 'Cancel', the link is followed. The expected behavior is not to follow the link, right?

As a note, this was working with rack-pjax.

asset caching doesn't work with async loaded js (like google analytics)

I just updated to the latest and I started getting full page refreshes, I tracked this down to the assetsChanged function which is always returning true because of the async js I'm loading which is present in the cached document but not present in the newly fetched version.

This is breaking for the YouTube API and Google Analytics at the moment. Trying to see if I can find a solution..

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.