devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
173 lines (138 loc) • 5.92 kB
JavaScript
"use strict";
require("../integration/jquery");
var $ = require("jquery"),
noop = require("../core/utils/common").noop,
window = require("../core/utils/window").getWindow(),
Class = require("../core/class"),
Callbacks = require("../core/utils/callbacks"),
browserAdapters = require("./browser_adapters"),
SessionStorage = require("../core/utils/storage").sessionStorage,
devices = require("../core/devices");
var SESSION_KEY = "dxPhoneJSApplication";
var HistoryBasedNavigationDevice = Class.inherit({
ctor: function ctor(options) {
options = options || {};
this._browserAdapter = options.browserAdapter || this._createBrowserAdapter(options);
this.uriChanged = Callbacks();
this._browserAdapter.popState.add(this._onPopState.bind(this));
},
init: noop,
getUri: function getUri() {
return this._browserAdapter.getHash();
},
setUri: function setUri(uri, replaceCurrent) {
if (replaceCurrent) {
return this._browserAdapter.replaceState(uri);
} else if (uri !== this.getUri()) {
return this._browserAdapter.pushState(uri);
} else {
return $.Deferred().resolve().promise();
}
},
back: function back() {
return this._browserAdapter.back();
},
_onPopState: function _onPopState() {
this.uriChanged.fire(this.getUri());
},
_isBuggyAndroid2: function _isBuggyAndroid2() {
// NOTE: window.location is not updated after history.pushState() changes the URL https://code.google.com/p/android/issues/detail?id=17471
var realDevice = devices.real();
var version = realDevice.version;
return realDevice.platform === "android" && version.length > 1 && (version[0] === 2 && version[1] < 4 || version[0] < 2);
},
_isBuggyAndroid4: function _isBuggyAndroid4() {
// NOTE: Android 4.0: history.back() to first item sets hash to empty string instead of first item hash value
var realDevice = devices.real();
var version = realDevice.version;
return realDevice.platform === "android" && version.length > 1 && version[0] === 4 && version[1] === 0;
},
_isWindowsPhone8: function _isWindowsPhone8() {
// NOTE: Windows Phone 8 can't work in browser. It works only if packed as native app. Taking into account permanent cordova bugs in each new version:
// https://issues.apache.org/jira/browse/CB-4873
// https://issues.apache.org/jira/browse/CB-6763
// https://issues.apache.org/jira/browse/CB-7356
// we have to disable some navigation stuff to make everything work
var realDevice = devices.real();
return realDevice.platform === "win" && realDevice.phone;
},
_createBrowserAdapter: function _createBrowserAdapter(options) {
var sourceWindow = options.window || window,
supportPushReplace = sourceWindow.history.replaceState && sourceWindow.history.pushState,
result;
if (this._isWindowsPhone8()) {
result = new browserAdapters.BuggyCordovaWP81BrowserAdapter(options);
} else if (sourceWindow !== sourceWindow.top) {
result = new browserAdapters.HistorylessBrowserAdapter(options);
} else if (this._isBuggyAndroid4()) {
result = new browserAdapters.BuggyAndroidBrowserAdapter(options);
} else if (this._isBuggyAndroid2() || !supportPushReplace) {
result = new browserAdapters.OldBrowserAdapter(options);
} else {
result = new browserAdapters.DefaultBrowserAdapter(options);
}
return result;
}
});
var StackBasedNavigationDevice = HistoryBasedNavigationDevice.inherit({
ctor: function ctor(options) {
this.callBase(options);
this.backInitiated = Callbacks();
this._rootStateHandler = null;
$(window).on("unload", this._saveBrowserState);
},
init: function init() {
var that = this;
if (that._browserAdapter.canWorkInPureBrowser) {
return that._initRootPage().done(function () {
if (that._browserAdapter.isRootPage()) {
that._browserAdapter.pushState("");
}
});
} else {
return $.Deferred().resolve().promise();
}
},
setUri: function setUri(uri) {
return this.callBase(uri, !this._browserAdapter.isRootPage());
},
_saveBrowserState: function _saveBrowserState() {
var sessionStorage = SessionStorage();
if (sessionStorage) {
sessionStorage.setItem(SESSION_KEY, true);
}
},
_initRootPage: function _initRootPage() {
var hash = this.getUri(),
sessionStorage = SessionStorage();
if (!sessionStorage || sessionStorage.getItem(SESSION_KEY)) {
return $.Deferred().resolve().promise();
}
sessionStorage.removeItem(SESSION_KEY);
this._browserAdapter.createRootPage();
return this._browserAdapter.pushState(hash);
},
_onPopState: function _onPopState() {
if (this._browserAdapter.isRootPage()) {
if (this._rootStateHandler) {
this._rootStateHandler();
} else {
this.backInitiated.fire();
}
} else {
if (!this._rootStateHandler) {
this._createRootStateHandler();
}
this.back();
}
},
_createRootStateHandler: function _createRootStateHandler() {
var uri = this.getUri();
this._rootStateHandler = function () {
this.uriChanged.fire(uri);
this._rootStateHandler = null;
};
}
});
exports.HistoryBasedNavigationDevice = HistoryBasedNavigationDevice;
exports.StackBasedNavigationDevice = StackBasedNavigationDevice;