File: //usr/share/nodejs/turbolinks/src/turbolinks/controller.js
// Generated by CoffeeScript 1.12.8
(function() {
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
require('./location');
require('./browser_adapter');
require('./history');
require('./view');
require('./scroll_manager');
require('./snapshot_cache');
require('./visit');
Turbolinks.Controller = (function() {
function Controller() {
this.clickBubbled = bind(this.clickBubbled, this);
this.clickCaptured = bind(this.clickCaptured, this);
this.pageLoaded = bind(this.pageLoaded, this);
this.history = new Turbolinks.History(this);
this.view = new Turbolinks.View(this);
this.scrollManager = new Turbolinks.ScrollManager(this);
this.restorationData = {};
this.clearCache();
this.setProgressBarDelay(500);
}
Controller.prototype.start = function() {
if (Turbolinks.supported && !this.started) {
addEventListener("click", this.clickCaptured, true);
addEventListener("DOMContentLoaded", this.pageLoaded, false);
this.scrollManager.start();
this.startHistory();
this.started = true;
return this.enabled = true;
}
};
Controller.prototype.disable = function() {
return this.enabled = false;
};
Controller.prototype.stop = function() {
if (this.started) {
removeEventListener("click", this.clickCaptured, true);
removeEventListener("DOMContentLoaded", this.pageLoaded, false);
this.scrollManager.stop();
this.stopHistory();
return this.started = false;
}
};
Controller.prototype.clearCache = function() {
return this.cache = new Turbolinks.SnapshotCache(10);
};
Controller.prototype.visit = function(location, options) {
var action, ref;
if (options == null) {
options = {};
}
location = Turbolinks.Location.wrap(location);
if (this.applicationAllowsVisitingLocation(location)) {
if (this.locationIsVisitable(location)) {
action = (ref = options.action) != null ? ref : "advance";
return this.adapter.visitProposedToLocationWithAction(location, action);
} else {
return window.location = location;
}
}
};
Controller.prototype.startVisitToLocationWithAction = function(location, action, restorationIdentifier) {
var restorationData;
if (Turbolinks.supported) {
restorationData = this.getRestorationDataForIdentifier(restorationIdentifier);
return this.startVisit(location, action, {
restorationData: restorationData
});
} else {
return window.location = location;
}
};
Controller.prototype.setProgressBarDelay = function(delay) {
return this.progressBarDelay = delay;
};
Controller.prototype.startHistory = function() {
this.location = Turbolinks.Location.wrap(window.location);
this.restorationIdentifier = Turbolinks.uuid();
this.history.start();
return this.history.replace(this.location, this.restorationIdentifier);
};
Controller.prototype.stopHistory = function() {
return this.history.stop();
};
Controller.prototype.pushHistoryWithLocationAndRestorationIdentifier = function(location, restorationIdentifier1) {
this.restorationIdentifier = restorationIdentifier1;
this.location = Turbolinks.Location.wrap(location);
return this.history.push(this.location, this.restorationIdentifier);
};
Controller.prototype.replaceHistoryWithLocationAndRestorationIdentifier = function(location, restorationIdentifier1) {
this.restorationIdentifier = restorationIdentifier1;
this.location = Turbolinks.Location.wrap(location);
return this.history.replace(this.location, this.restorationIdentifier);
};
Controller.prototype.historyPoppedToLocationWithRestorationIdentifier = function(location, restorationIdentifier1) {
var restorationData;
this.restorationIdentifier = restorationIdentifier1;
if (this.enabled) {
restorationData = this.getRestorationDataForIdentifier(this.restorationIdentifier);
this.startVisit(location, "restore", {
restorationIdentifier: this.restorationIdentifier,
restorationData: restorationData,
historyChanged: true
});
return this.location = Turbolinks.Location.wrap(location);
} else {
return this.adapter.pageInvalidated();
}
};
Controller.prototype.getCachedSnapshotForLocation = function(location) {
var ref;
return (ref = this.cache.get(location)) != null ? ref.clone() : void 0;
};
Controller.prototype.shouldCacheSnapshot = function() {
return this.view.getSnapshot().isCacheable();
};
Controller.prototype.cacheSnapshot = function() {
var location, snapshot;
if (this.shouldCacheSnapshot()) {
this.notifyApplicationBeforeCachingSnapshot();
snapshot = this.view.getSnapshot();
location = this.lastRenderedLocation;
return Turbolinks.defer((function(_this) {
return function() {
return _this.cache.put(location, snapshot.clone());
};
})(this));
}
};
Controller.prototype.scrollToAnchor = function(anchor) {
var element;
if (element = this.view.getElementForAnchor(anchor)) {
return this.scrollToElement(element);
} else {
return this.scrollToPosition({
x: 0,
y: 0
});
}
};
Controller.prototype.scrollToElement = function(element) {
return this.scrollManager.scrollToElement(element);
};
Controller.prototype.scrollToPosition = function(position) {
return this.scrollManager.scrollToPosition(position);
};
Controller.prototype.scrollPositionChanged = function(scrollPosition) {
var restorationData;
restorationData = this.getCurrentRestorationData();
return restorationData.scrollPosition = scrollPosition;
};
Controller.prototype.render = function(options, callback) {
return this.view.render(options, callback);
};
Controller.prototype.viewInvalidated = function() {
return this.adapter.pageInvalidated();
};
Controller.prototype.viewWillRender = function(newBody) {
return this.notifyApplicationBeforeRender(newBody);
};
Controller.prototype.viewRendered = function() {
this.lastRenderedLocation = this.currentVisit.location;
return this.notifyApplicationAfterRender();
};
Controller.prototype.pageLoaded = function() {
this.lastRenderedLocation = this.location;
return this.notifyApplicationAfterPageLoad();
};
Controller.prototype.clickCaptured = function() {
removeEventListener("click", this.clickBubbled, false);
return addEventListener("click", this.clickBubbled, false);
};
Controller.prototype.clickBubbled = function(event) {
var action, link, location;
if (this.enabled && this.clickEventIsSignificant(event)) {
if (link = this.getVisitableLinkForNode(event.target)) {
if (location = this.getVisitableLocationForLink(link)) {
if (this.applicationAllowsFollowingLinkToLocation(link, location)) {
event.preventDefault();
action = this.getActionForLink(link);
return this.visit(location, {
action: action
});
}
}
}
}
};
Controller.prototype.applicationAllowsFollowingLinkToLocation = function(link, location) {
var event;
event = this.notifyApplicationAfterClickingLinkToLocation(link, location);
return !event.defaultPrevented;
};
Controller.prototype.applicationAllowsVisitingLocation = function(location) {
var event;
event = this.notifyApplicationBeforeVisitingLocation(location);
return !event.defaultPrevented;
};
Controller.prototype.notifyApplicationAfterClickingLinkToLocation = function(link, location) {
return Turbolinks.dispatch("turbolinks:click", {
target: link,
data: {
url: location.absoluteURL
},
cancelable: true
});
};
Controller.prototype.notifyApplicationBeforeVisitingLocation = function(location) {
return Turbolinks.dispatch("turbolinks:before-visit", {
data: {
url: location.absoluteURL
},
cancelable: true
});
};
Controller.prototype.notifyApplicationAfterVisitingLocation = function(location) {
return Turbolinks.dispatch("turbolinks:visit", {
data: {
url: location.absoluteURL
}
});
};
Controller.prototype.notifyApplicationBeforeCachingSnapshot = function() {
return Turbolinks.dispatch("turbolinks:before-cache");
};
Controller.prototype.notifyApplicationBeforeRender = function(newBody) {
return Turbolinks.dispatch("turbolinks:before-render", {
data: {
newBody: newBody
}
});
};
Controller.prototype.notifyApplicationAfterRender = function() {
return Turbolinks.dispatch("turbolinks:render");
};
Controller.prototype.notifyApplicationAfterPageLoad = function(timing) {
if (timing == null) {
timing = {};
}
return Turbolinks.dispatch("turbolinks:load", {
data: {
url: this.location.absoluteURL,
timing: timing
}
});
};
Controller.prototype.startVisit = function(location, action, properties) {
var ref;
if ((ref = this.currentVisit) != null) {
ref.cancel();
}
this.currentVisit = this.createVisit(location, action, properties);
this.currentVisit.start();
return this.notifyApplicationAfterVisitingLocation(location);
};
Controller.prototype.createVisit = function(location, action, arg) {
var historyChanged, ref, restorationData, restorationIdentifier, visit;
ref = arg != null ? arg : {}, restorationIdentifier = ref.restorationIdentifier, restorationData = ref.restorationData, historyChanged = ref.historyChanged;
visit = new Turbolinks.Visit(this, location, action);
visit.restorationIdentifier = restorationIdentifier != null ? restorationIdentifier : Turbolinks.uuid();
visit.restorationData = Turbolinks.copyObject(restorationData);
visit.historyChanged = historyChanged;
visit.referrer = this.location;
return visit;
};
Controller.prototype.visitCompleted = function(visit) {
return this.notifyApplicationAfterPageLoad(visit.getTimingMetrics());
};
Controller.prototype.clickEventIsSignificant = function(event) {
return !(event.defaultPrevented || event.target.isContentEditable || event.which > 1 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey);
};
Controller.prototype.getVisitableLinkForNode = function(node) {
if (this.nodeIsVisitable(node)) {
return Turbolinks.closest(node, "a[href]:not([target]):not([download])");
}
};
Controller.prototype.getVisitableLocationForLink = function(link) {
var location;
location = new Turbolinks.Location(link.getAttribute("href"));
if (this.locationIsVisitable(location)) {
return location;
}
};
Controller.prototype.getActionForLink = function(link) {
var ref;
return (ref = link.getAttribute("data-turbolinks-action")) != null ? ref : "advance";
};
Controller.prototype.nodeIsVisitable = function(node) {
var container;
if (container = Turbolinks.closest(node, "[data-turbolinks]")) {
return container.getAttribute("data-turbolinks") !== "false";
} else {
return true;
}
};
Controller.prototype.locationIsVisitable = function(location) {
return location.isPrefixedBy(this.view.getRootLocation()) && location.isHTML();
};
Controller.prototype.getCurrentRestorationData = function() {
return this.getRestorationDataForIdentifier(this.restorationIdentifier);
};
Controller.prototype.getRestorationDataForIdentifier = function(identifier) {
var base;
return (base = this.restorationData)[identifier] != null ? base[identifier] : base[identifier] = {};
};
return Controller;
})();
}).call(this);