From bd969ed423b5f51623f4510047d7da2a7401b2dc Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Wed, 20 May 2015 20:31:50 +0200 Subject: [PATCH] Introduced WoltLab/WCF/Environment as a replacement for $.browser --- .../install/files/js/WoltLab/WCF/Bootstrap.js | 29 ++-- .../js/WoltLab/WCF/Controller/Popover.js | 4 +- wcfsetup/install/files/js/WoltLab/WCF/Core.js | 16 +-- .../files/js/WoltLab/WCF/Environment.js | 127 ++++++++++++++++++ .../install/files/js/WoltLab/WCF/UI/Dialog.js | 4 +- .../install/files/js/WoltLab/WCF/UI/Mobile.js | 14 +- .../files/js/WoltLab/WCF/UI/TabMenu/Simple.js | 2 +- .../files/js/WoltLab/WCF/UI/Tooltip.js | 4 +- wcfsetup/install/files/js/require.config.js | 1 + 9 files changed, 172 insertions(+), 29 deletions(-) create mode 100644 wcfsetup/install/files/js/WoltLab/WCF/Environment.js diff --git a/wcfsetup/install/files/js/WoltLab/WCF/Bootstrap.js b/wcfsetup/install/files/js/WoltLab/WCF/Bootstrap.js index 73d47ecc89..ff371d32da 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/Bootstrap.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/Bootstrap.js @@ -10,14 +10,14 @@ */ define( [ - 'jquery', 'favico', 'enquire', 'WoltLab/WCF/Date/Time/Relative', + 'favico', 'enquire', 'WoltLab/WCF/Date/Time/Relative', 'UI/SimpleDropdown', 'WoltLab/WCF/UI/Mobile', 'WoltLab/WCF/UI/TabMenu', 'WoltLab/WCF/UI/FlexibleMenu', - 'UI/Dialog', 'WoltLab/WCF/UI/Tooltip', 'WoltLab/WCF/Language' + 'UI/Dialog', 'WoltLab/WCF/UI/Tooltip', 'WoltLab/WCF/Language', 'WoltLab/WCF/Environment' ], function( - $, favico, enquire, relativeTime, - simpleDropdown, UIMobile, UITabMenu, UIFlexibleMenu, - UIDialog, UITooltip, Language + favico, enquire, DateTimeRelative, + UISimpleDropdown, UIMobile, UITabMenu, UIFlexibleMenu, + UIDialog, UITooltip, Language, Environment ) { "use strict"; @@ -37,8 +37,11 @@ define( * Initializes the core UI modifications and unblocks jQuery's ready event. */ setup: function() { - relativeTime.setup(); - simpleDropdown.setup(); + Environment.setup(); + + DateTimeRelative.setup(); + + UISimpleDropdown.setup(); UIMobile.setup(); UITabMenu.setup(); UIFlexibleMenu.setup(); @@ -51,13 +54,21 @@ define( forms[i].setAttribute('method', 'post'); } - if ($.browser.msie) { + if (Environment.browser() === 'microsoft') { window.onbeforeunload = function() { /* Prevent "Back navigation caching" (http://msdn.microsoft.com/en-us/library/ie/dn265017%28v=vs.85%29.aspx) */ }; } - $.holdReady(false); + // DEBUG ONLY + var interval = 0; + interval = window.setInterval(function() { + if (typeof window.jQuery === 'function') { + window.clearInterval(interval); + + window.jQuery.holdReady(false); + } + }, 20); } }; diff --git a/wcfsetup/install/files/js/WoltLab/WCF/Controller/Popover.js b/wcfsetup/install/files/js/WoltLab/WCF/Controller/Popover.js index 9b6992ff95..8334bf604e 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/Controller/Popover.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/Controller/Popover.js @@ -6,7 +6,7 @@ * @license GNU Lesser General Public License * @module WoltLab/WCF/Controller/Popover */ -define(['Dictionary', 'DOM/Util', 'UI/Alignment'], function(Dictionary, DOMUtil, UIAlignment) { +define(['Dictionary', 'Environment', 'DOM/Util', 'UI/Alignment'], function(Dictionary, Environment, DOMUtil, UIAlignment) { "use strict"; var _activeId = null; @@ -119,7 +119,7 @@ define(['Dictionary', 'DOM/Util', 'UI/Alignment'], function(Dictionary, DOMUtil, * @param {object} options handler options */ init: function(options) { - if ($.browser.mobile) { + if (Environment.platform() !== 'desktop') { return; } diff --git a/wcfsetup/install/files/js/WoltLab/WCF/Core.js b/wcfsetup/install/files/js/WoltLab/WCF/Core.js index b52d5e333b..249c7e9764 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/Core.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/Core.js @@ -26,17 +26,17 @@ define([], function() { } return url.replace(/^index\.php\/(.*?)\/\?/, function(match, controller) { - var $parts = controller.split(/([A-Z][a-z0-9]+)/); - var $controller = ''; - for (var $i = 0, $length = $parts.length; $i < $length; $i++) { - var $part = $parts[$i].trim(); - if ($part.length) { - if ($controller.length) $controller += '-'; - $controller += $part.toLowerCase(); + var parts = controller.split(/([A-Z][a-z0-9]+)/); + var controller = ''; + for (var i = 0, length = parts.length; i < length; i++) { + var part = parts[i].trim(); + if (part.length) { + if (controller.length) controller += '-'; + controller += part.toLowerCase(); } } - return 'index.php?' + $controller + '/&'; + return 'index.php?' + controller + '/&'; }); }, diff --git a/wcfsetup/install/files/js/WoltLab/WCF/Environment.js b/wcfsetup/install/files/js/WoltLab/WCF/Environment.js new file mode 100644 index 0000000000..528077ef48 --- /dev/null +++ b/wcfsetup/install/files/js/WoltLab/WCF/Environment.js @@ -0,0 +1,127 @@ +/** + * Provides basic details on the JavaScript environment. + * + * @author Alexander Ebert + * @copyright 2001-2015 WoltLab GmbH + * @license GNU Lesser General Public License + * @module WoltLab/WCF/Environment + */ +define([], function() { + "use strict"; + + var _browser = 'other'; + var _editor = 'none'; + var _platform = 'desktop'; + var _touch = false; + + /** + * @constructor + */ + function Environment() {}; + Environment.prototype = { + /** + * Determines environment variables. + */ + setup: function() { + if (typeof window.chrome === 'object') { + // this detects Opera as well, we could check for window.opr if we need to + _browser = 'chrome'; + } + else { + var styles = window.getComputedStyle(document.documentElement); + for (var i = 0, length = styles.length; i < length; i++) { + var property = styles[i]; + + if (property.indexOf('-ms-') === 0) { + // it is tempting to use 'msie', but it wouldn't really represent 'Edge' + _browser = 'microsoft'; + } + else if (property.indexOf('-moz-') === 0) { + _browser = 'firefox'; + } + else if (property.indexOf('-webkit-') === 0) { + _browser = 'safari'; + } + } + } + + var ua = window.navigator.userAgent.toLowerCase(); + if (ua.indexOf('crios') !== -1) { + _browser = 'chrome'; + _platform = 'ios'; + } + else if (/(?:iphone|ipad|ipod)/.test(ua)) { + _browser = 'safari'; + _platform = 'ios'; + } + else if (ua.indexOf('android') !== -1) { + _platform = 'android'; + } + else if (ua.indexOf('iemobile') !== -1) { + _browser = 'microsoft'; + _platform = 'windows'; + } + + if (_platform === 'desktop' && (ua.indexOf('mobile') !== -1 || ua.indexOf('tablet') !== -1)) { + _platform = 'mobile'; + } + + _editor = 'redactor'; + _touch = (!!('ontouchstart' in window) || (!!('msMaxTouchPoints' in window.navigator) && window.navigator.msMaxTouchPoints > 0) || window.DocumentTouch && document instanceof DocumentTouch); + }, + + /** + * Returns the lower-case browser identifier. + * + * Possible values: + * - chrome: Chrome and Opera + * - firefox + * - microsoft: Internet Explorer and Microsoft Edge + * - safari + * + * @return {string} browser identifier + */ + browser: function() { + return _browser; + }, + + /** + * Returns the available editor's name or an empty string. + * + * @return {string} editor name + */ + editor: function() { + return _editor; + }, + + /** + * Returns the browser platform. + * + * Possible values: + * - desktop + * - android + * - ios: iPhone, iPad and iPod + * - windows: Windows on phones/tablets + * + * @return {string} browser platform + */ + platform: function() { + return _platform; + }, + + /** + * Returns true if browser is potentially used with a touchscreen. + * + * Warning: Detecting touch is unreliable and should be avoided at all cost. + * + * @deprecated 2.2 - exists for backward-compatibility only, will be removed in the future + * + * @return {boolean} true if a touchscreen is present + */ + touch: function() { + return _touch; + } + }; + + return new Environment(); +}); diff --git a/wcfsetup/install/files/js/WoltLab/WCF/UI/Dialog.js b/wcfsetup/install/files/js/WoltLab/WCF/UI/Dialog.js index 97ee658bea..74ec468d3b 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/UI/Dialog.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/UI/Dialog.js @@ -6,7 +6,7 @@ * @license GNU Lesser General Public License * @module WoltLab/WCF/UI/Dialog */ -define(['jquery', 'enquire', 'Core', 'Dictionary', 'Language', 'DOM/Util'], function($, enquire, Core, Dictionary, Language, DOMUtil) { +define(['enquire', 'Core', 'Dictionary', 'Environment', 'Language', 'DOM/Util'], function(enquire, Core, Dictionary, Environment, Language, DOMUtil) { "use strict"; var _activeDialog = null; @@ -298,7 +298,7 @@ define(['jquery', 'enquire', 'Core', 'Dictionary', 'Language', 'DOM/Util'], func contentContainer.style.setProperty('max-height', ~~maximumHeight + 'px'); // fix for a calculation bug in Chrome causing the scrollbar to overlap the border - if ($.browser.chrome) { + if (Environment.browser() === 'chrome') { if (data.content.scrollHeight > maximumHeight) { data.content.style.setProperty('margin-right', '-1px'); } diff --git a/wcfsetup/install/files/js/WoltLab/WCF/UI/Mobile.js b/wcfsetup/install/files/js/WoltLab/WCF/UI/Mobile.js index bce846d538..f58ac94cb6 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/UI/Mobile.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/UI/Mobile.js @@ -6,7 +6,7 @@ * @license GNU Lesser General Public License * @module WoltLab/WCF/UI/Mobile */ -define(['jquery', 'enquire', 'Language', 'DOM/Traverse'], function($, enquire, Language, DOMTraverse) { +define(['enquire', 'Environment', 'Language', 'DOM/Traverse'], function(enquire, Environment, Language, DOMTraverse) { "use strict"; var _buttonGroupNavigations = null; @@ -27,10 +27,14 @@ define(['jquery', 'enquire', 'Language', 'DOM/Traverse'], function($, enquire, L _main = document.getElementById('main'); _sidebar = _main.querySelector('#main > div > div > .sidebar'); - if ($.browser.touch) { + if (Environment.touch()) { document.documentElement.classList.add('touch'); } + if (Environment.platform() !== 'desktop') { + document.documentElement.classList.add('mobile'); + } + enquire.register('screen and (max-width: 800px)', { match: this.enable.bind(this), unmatch: this.disable.bind(this), @@ -38,7 +42,7 @@ define(['jquery', 'enquire', 'Language', 'DOM/Traverse'], function($, enquire, L deferSetup: true }); - if ($.browser.msie && _sidebar.clientWidth > 305) { + if (Environment.browser() === 'microsoft' && _sidebar.clientWidth > 305) { this._fixSidebarIE(); } }, @@ -49,7 +53,7 @@ define(['jquery', 'enquire', 'Language', 'DOM/Traverse'], function($, enquire, L enable: function() { _enabled = true; - if ($.browser.msie) this._fixSidebarIE(); + if (Environment.browser() === 'microsoft') this._fixSidebarIE(); }, /** @@ -58,7 +62,7 @@ define(['jquery', 'enquire', 'Language', 'DOM/Traverse'], function($, enquire, L disable: function() { _enabled = false; - if ($.browser.msie) this._fixSidebarIE(); + if (Environment.browser() === 'microsoft') this._fixSidebarIE(); }, _fixSidebarIE: function() { diff --git a/wcfsetup/install/files/js/WoltLab/WCF/UI/TabMenu/Simple.js b/wcfsetup/install/files/js/WoltLab/WCF/UI/TabMenu/Simple.js index c3f94cba98..a9e10791d7 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/UI/TabMenu/Simple.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/UI/TabMenu/Simple.js @@ -6,7 +6,7 @@ * @license GNU Lesser General Public License * @module WoltLab/WCF/UI/TabMenu/Simple */ -define(['jquery', 'Dictionary', 'DOM/Util', 'EventHandler'], function($, Dictionary, DOMUtil, EventHandler) { +define(['Dictionary', 'DOM/Util', 'EventHandler'], function(Dictionary, DOMUtil, EventHandler) { "use strict"; /** diff --git a/wcfsetup/install/files/js/WoltLab/WCF/UI/Tooltip.js b/wcfsetup/install/files/js/WoltLab/WCF/UI/Tooltip.js index b402504436..7763a6f8f6 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/UI/Tooltip.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/UI/Tooltip.js @@ -6,7 +6,7 @@ * @license GNU Lesser General Public License * @module WoltLab/WCF/UI/Tooltip */ -define(['jquery', 'UI/Alignment'], function($, UIAlignment) { +define(['Environment', 'UI/Alignment'], function(Environment, UIAlignment) { "use strict"; var _elements = null; @@ -23,7 +23,7 @@ define(['jquery', 'UI/Alignment'], function($, UIAlignment) { * Initializes the tooltip element and binds event listener. */ setup: function() { - if ($.browser.mobile) return; + if (Environment.platform() !== 'desktop') return; _tooltip = document.createElement('div'); _tooltip.setAttribute('id', 'balloonTooltip'); diff --git a/wcfsetup/install/files/js/require.config.js b/wcfsetup/install/files/js/require.config.js index 5dcfd82a4b..4d49395e16 100644 --- a/wcfsetup/install/files/js/require.config.js +++ b/wcfsetup/install/files/js/require.config.js @@ -11,6 +11,7 @@ requirejs.config({ 'Dictionary': 'WoltLab/WCF/Dictionary', 'DOM/Traverse': 'WoltLab/WCF/DOM/Traverse', 'DOM/Util': 'WoltLab/WCF/DOM/Util', + 'Environment': 'WoltLab/WCF/Environment', 'EventHandler': 'WoltLab/WCF/Event/Handler', 'Language': 'WoltLab/WCF/Language', 'UI/Alignment': 'WoltLab/WCF/UI/Alignment', -- 2.20.1