turbolinks
Version:
Turbolinks makes navigating your web application faster
245 lines (188 loc) • 7.69 kB
text/coffeescript
#= require ./location
#= require ./browser_adapter
#= require ./history
#= require ./view
#= require ./scroll_manager
#= require ./snapshot_cache
#= require ./visit
class Turbolinks.Controller
constructor: ->
= new Turbolinks.History this
= new Turbolinks.View this
= new Turbolinks.ScrollManager this
= {}
start: ->
if Turbolinks.supported and not
addEventListener("click", , true)
addEventListener("DOMContentLoaded", , false)
.start()
= true
= true
disable: ->
= false
stop: ->
if
removeEventListener("click", , true)
removeEventListener("DOMContentLoaded", , false)
.stop()
= false
clearCache: ->
= new Turbolinks.SnapshotCache 10
visit: (location, options = {}) ->
location = Turbolinks.Location.wrap(location)
if
if
action = options.action ? "advance"
.visitProposedToLocationWithAction(location, action)
else
window.location = location
startVisitToLocationWithAction: (location, action, restorationIdentifier) ->
if Turbolinks.supported
restorationData =
else
window.location = location
setProgressBarDelay: (delay) ->
= delay
# History
startHistory: ->
= Turbolinks.Location.wrap(window.location)
= Turbolinks.uuid()
.start()
.replace( , )
stopHistory: ->
.stop()
pushHistoryWithLocationAndRestorationIdentifier: (location, ) ->
= Turbolinks.Location.wrap(location)
.push( , )
replaceHistoryWithLocationAndRestorationIdentifier: (location, ) ->
= Turbolinks.Location.wrap(location)
.replace( , )
# History delegate
historyPoppedToLocationWithRestorationIdentifier: (location, ) ->
if
restorationData =
= Turbolinks.Location.wrap(location)
else
.pageInvalidated()
# Snapshot cache
getCachedSnapshotForLocation: (location) ->
.get(location)?.clone()
shouldCacheSnapshot: ->
.getSnapshot().isCacheable()
cacheSnapshot: ->
if
snapshot = .getSnapshot()
location =
Turbolinks.defer =>
.put(location, snapshot.clone())
# Scrolling
scrollToAnchor: (anchor) ->
if element = .getElementForAnchor(anchor)
else
scrollToElement: (element) ->
.scrollToElement(element)
scrollToPosition: (position) ->
.scrollToPosition(position)
# Scroll manager delegate
scrollPositionChanged: (scrollPosition) ->
restorationData =
restorationData.scrollPosition = scrollPosition
# View
render: (options, callback) ->
.render(options, callback)
viewInvalidated: ->
.pageInvalidated()
viewWillRender: (newBody) ->
viewRendered: ->
= .location
# Event handlers
pageLoaded: =>
=
clickCaptured: =>
removeEventListener("click", , false)
addEventListener("click", , false)
clickBubbled: (event) =>
if and
if link =
if location =
if
event.preventDefault()
action =
# Application events
applicationAllowsFollowingLinkToLocation: (link, location) ->
event =
not event.defaultPrevented
applicationAllowsVisitingLocation: (location) ->
event =
not event.defaultPrevented
notifyApplicationAfterClickingLinkToLocation: (link, location) ->
Turbolinks.dispatch("turbolinks:click", target: link, data: { url: location.absoluteURL }, cancelable: true)
notifyApplicationBeforeVisitingLocation: (location) ->
Turbolinks.dispatch("turbolinks:before-visit", data: { url: location.absoluteURL }, cancelable: true)
notifyApplicationAfterVisitingLocation: (location) ->
Turbolinks.dispatch("turbolinks:visit", data: { url: location.absoluteURL })
notifyApplicationBeforeCachingSnapshot: ->
Turbolinks.dispatch("turbolinks:before-cache")
notifyApplicationBeforeRender: (newBody) ->
Turbolinks.dispatch("turbolinks:before-render", data: {newBody})
notifyApplicationAfterRender: ->
Turbolinks.dispatch("turbolinks:render")
notifyApplicationAfterPageLoad: (timing = {}) ->
Turbolinks.dispatch("turbolinks:load", data: { url: .absoluteURL, timing })
# Private
startVisit: (location, action, properties) ->
?.cancel()
=
.start()
createVisit: (location, action, {restorationIdentifier, restorationData, historyChanged} = {}) ->
visit = new Turbolinks.Visit this, location, action
visit.restorationIdentifier = restorationIdentifier ? Turbolinks.uuid()
visit.restorationData = Turbolinks.copyObject(restorationData)
visit.historyChanged = historyChanged
visit.referrer =
visit
visitCompleted: (visit) ->
clickEventIsSignificant: (event) ->
not (
event.defaultPrevented or
event.target.isContentEditable or
event.which > 1 or
event.altKey or
event.ctrlKey or
event.metaKey or
event.shiftKey
)
getVisitableLinkForNode: (node) ->
if
Turbolinks.closest(node, "a[href]:not([target]):not([download])")
getVisitableLocationForLink: (link) ->
location = new Turbolinks.Location link.getAttribute("href")
location if
getActionForLink: (link) ->
link.getAttribute("data-turbolinks-action") ? "advance"
nodeIsVisitable: (node) ->
if container = Turbolinks.closest(node, "[data-turbolinks]")
container.getAttribute("data-turbolinks") isnt "false"
else
true
locationIsVisitable: (location) ->
location.isPrefixedBy( .getRootLocation()) and location.isHTML()
getCurrentRestorationData: ->
getRestorationDataForIdentifier: (identifier) ->
[identifier] ?= {}