UNPKG

turbolinks

Version:

Turbolinks makes navigating your web application faster

163 lines (130 loc) 4.5 kB
#= require ./http_request class Turbolinks.Visit constructor: (@controller, location, @action) -> @identifier = Turbolinks.uuid() @location = Turbolinks.Location.wrap(location) @adapter = @controller.adapter @state = "initialized" @timingMetrics = {} start: -> if @state is "initialized" @recordTimingMetric("visitStart") @state = "started" @adapter.visitStarted(this) cancel: -> if @state is "started" @request?.cancel() @cancelRender() @state = "canceled" complete: -> if @state is "started" @recordTimingMetric("visitEnd") @state = "completed" @adapter.visitCompleted?(this) @controller.visitCompleted(this) fail: -> if @state is "started" @state = "failed" @adapter.visitFailed?(this) changeHistory: -> unless @historyChanged actionForHistory = if @location.isEqualTo(@referrer) then "replace" else @action method = getHistoryMethodForAction(actionForHistory) @controller[method](@location, @restorationIdentifier) @historyChanged = true issueRequest: -> if @shouldIssueRequest() and not @request? @progress = 0 @request = new Turbolinks.HttpRequest this, @location, @referrer @request.send() getCachedSnapshot: -> if snapshot = @controller.getCachedSnapshotForLocation(@location) if not @location.anchor? or snapshot.hasAnchor(@location.anchor) if @action is "restore" or snapshot.isPreviewable() snapshot hasCachedSnapshot: -> @getCachedSnapshot()? loadCachedSnapshot: -> if snapshot = @getCachedSnapshot() isPreview = @shouldIssueRequest() @render -> @cacheSnapshot() @controller.render({snapshot, isPreview}, @performScroll) @adapter.visitRendered?(this) @complete() unless isPreview loadResponse: -> if @response? @render -> @cacheSnapshot() if @request.failed @controller.render(error: @response, @performScroll) @adapter.visitRendered?(this) @fail() else @controller.render(snapshot: @response, @performScroll) @adapter.visitRendered?(this) @complete() followRedirect: -> if @redirectedToLocation and not @followedRedirect @location = @redirectedToLocation @controller.replaceHistoryWithLocationAndRestorationIdentifier(@redirectedToLocation, @restorationIdentifier) @followedRedirect = true # HTTP Request delegate requestStarted: -> @recordTimingMetric("requestStart") @adapter.visitRequestStarted?(this) requestProgressed: (@progress) -> @adapter.visitRequestProgressed?(this) requestCompletedWithResponse: (@response, redirectedToLocation) -> @redirectedToLocation = Turbolinks.Location.wrap(redirectedToLocation) if redirectedToLocation? @adapter.visitRequestCompleted(this) requestFailedWithStatusCode: (statusCode, @response) -> @adapter.visitRequestFailedWithStatusCode(this, statusCode) requestFinished: -> @recordTimingMetric("requestEnd") @adapter.visitRequestFinished?(this) # Scrolling performScroll: => unless @scrolled if @action is "restore" @scrollToRestoredPosition() or @scrollToTop() else @scrollToAnchor() or @scrollToTop() @scrolled = true scrollToRestoredPosition: -> position = @restorationData?.scrollPosition if position? @controller.scrollToPosition(position) true scrollToAnchor: -> if @location.anchor? @controller.scrollToAnchor(@location.anchor) true scrollToTop: -> @controller.scrollToPosition(x: 0, y: 0) # Instrumentation recordTimingMetric: (name) -> @timingMetrics[name] ?= new Date().getTime() getTimingMetrics: -> Turbolinks.copyObject(@timingMetrics) # Private getHistoryMethodForAction = (action) -> switch action when "replace" then "replaceHistoryWithLocationAndRestorationIdentifier" when "advance", "restore" then "pushHistoryWithLocationAndRestorationIdentifier" shouldIssueRequest: -> if @action is "restore" not @hasCachedSnapshot() else true cacheSnapshot: -> unless @snapshotCached @controller.cacheSnapshot() @snapshotCached = true render: (callback) -> @cancelRender() @frame = requestAnimationFrame => @frame = null callback.call(this) cancelRender: -> cancelAnimationFrame(@frame) if @frame