[!!!][TASK] Use progress bar instead of mask for loading 42/34242/6
authorBenjamin Mack <benni@typo3.org>
Sun, 16 Nov 2014 11:16:39 +0000 (12:16 +0100)
committerHelmut Hummel <helmut.hummel@typo3.org>
Fri, 26 Dec 2014 09:15:04 +0000 (10:15 +0100)
The core currently has two places where a loading
indicator is shown:

* Loading iframes, using a mask created by ExtJS
* Loading IRRE elements via AJAX, hand-made for IRRE

This behaviour should be unified with a new and clean API
using the JS library nprogress (MIT license).

Some old CSS code can safely removed, as it is not
used anymore.

Releases: master
Resolves: #64035
Change-Id: Iaf45af96aa022571195d1a27cfaa9dfd0f4ad63a
Reviewed-on: http://review.typo3.org/34242
Reviewed-by: Jigal van Hemert <jigal.van.hemert@typo3.org>
Tested-by: Jigal van Hemert <jigal.van.hemert@typo3.org>
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Tested-by: Helmut Hummel <helmut.hummel@typo3.org>
typo3/contrib/nprogress/nprogress.js [new file with mode: 0644]
typo3/js/extjs/backendcontentiframe.js
typo3/sysext/backend/Resources/Public/JavaScript/iframepanel.js
typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js
typo3/sysext/core/Classes/Page/PageRenderer.php
typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_tceforms.less
typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_misc_loading.less [deleted file]
typo3/sysext/t3skin/Resources/Private/Styles/nprogress/nprogress.less [new file with mode: 0644]
typo3/sysext/t3skin/Resources/Private/Styles/t3skin.less
typo3/sysext/t3skin/Resources/Public/Css/visual/t3skin.css
typo3/sysext/workspaces/Resources/Public/JavaScript/preview.js

diff --git a/typo3/contrib/nprogress/nprogress.js b/typo3/contrib/nprogress/nprogress.js
new file mode 100644 (file)
index 0000000..124351e
--- /dev/null
@@ -0,0 +1,476 @@
+/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress
+ * @license MIT */
+
+;(function(root, factory) {
+
+  if (typeof define === 'function' && define.amd) {
+    define(factory);
+  } else if (typeof exports === 'object') {
+    module.exports = factory();
+  } else {
+    root.NProgress = factory();
+  }
+
+})(this, function() {
+  var NProgress = {};
+
+  NProgress.version = '0.1.6';
+
+  var Settings = NProgress.settings = {
+    minimum: 0.08,
+    easing: 'ease',
+    positionUsing: '',
+    speed: 200,
+    trickle: true,
+    trickleRate: 0.02,
+    trickleSpeed: 800,
+    showSpinner: true,
+    barSelector: '[role="bar"]',
+    spinnerSelector: '[role="spinner"]',
+    parent: 'body',
+    template: '<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'
+  };
+
+  /**
+   * Updates configuration.
+   *
+   *     NProgress.configure({
+   *       minimum: 0.1
+   *     });
+   */
+  NProgress.configure = function(options) {
+    var key, value;
+    for (key in options) {
+      value = options[key];
+      if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value;
+    }
+
+    return this;
+  };
+
+  /**
+   * Last number.
+   */
+
+  NProgress.status = null;
+
+  /**
+   * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.
+   *
+   *     NProgress.set(0.4);
+   *     NProgress.set(1.0);
+   */
+
+  NProgress.set = function(n) {
+    var started = NProgress.isStarted();
+
+    n = clamp(n, Settings.minimum, 1);
+    NProgress.status = (n === 1 ? null : n);
+
+    var progress = NProgress.render(!started),
+        bar      = progress.querySelector(Settings.barSelector),
+        speed    = Settings.speed,
+        ease     = Settings.easing;
+
+    progress.offsetWidth; /* Repaint */
+
+    queue(function(next) {
+      // Set positionUsing if it hasn't already been set
+      if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();
+
+      // Add transition
+      css(bar, barPositionCSS(n, speed, ease));
+
+      if (n === 1) {
+        // Fade out
+        css(progress, { 
+          transition: 'none', 
+          opacity: 1 
+        });
+        progress.offsetWidth; /* Repaint */
+
+        setTimeout(function() {
+          css(progress, { 
+            transition: 'all ' + speed + 'ms linear', 
+            opacity: 0 
+          });
+          setTimeout(function() {
+            NProgress.remove();
+            next();
+          }, speed);
+        }, speed);
+      } else {
+        setTimeout(next, speed);
+      }
+    });
+
+    return this;
+  };
+
+  NProgress.isStarted = function() {
+    return typeof NProgress.status === 'number';
+  };
+
+  /**
+   * Shows the progress bar.
+   * This is the same as setting the status to 0%, except that it doesn't go backwards.
+   *
+   *     NProgress.start();
+   *
+   */
+  NProgress.start = function() {
+    if (!NProgress.status) NProgress.set(0);
+
+    var work = function() {
+      setTimeout(function() {
+        if (!NProgress.status) return;
+        NProgress.trickle();
+        work();
+      }, Settings.trickleSpeed);
+    };
+
+    if (Settings.trickle) work();
+
+    return this;
+  };
+
+  /**
+   * Hides the progress bar.
+   * This is the *sort of* the same as setting the status to 100%, with the
+   * difference being `done()` makes some placebo effect of some realistic motion.
+   *
+   *     NProgress.done();
+   *
+   * If `true` is passed, it will show the progress bar even if its hidden.
+   *
+   *     NProgress.done(true);
+   */
+
+  NProgress.done = function(force) {
+    if (!force && !NProgress.status) return this;
+
+    return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);
+  };
+
+  /**
+   * Increments by a random amount.
+   */
+
+  NProgress.inc = function(amount) {
+    var n = NProgress.status;
+
+    if (!n) {
+      return NProgress.start();
+    } else {
+      if (typeof amount !== 'number') {
+        amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);
+      }
+
+      n = clamp(n + amount, 0, 0.994);
+      return NProgress.set(n);
+    }
+  };
+
+  NProgress.trickle = function() {
+    return NProgress.inc(Math.random() * Settings.trickleRate);
+  };
+
+  /**
+   * Waits for all supplied jQuery promises and
+   * increases the progress as the promises resolve.
+   * 
+   * @param $promise jQUery Promise
+   */
+  (function() {
+    var initial = 0, current = 0;
+    
+    NProgress.promise = function($promise) {
+      if (!$promise || $promise.state() == "resolved") {
+        return this;
+      }
+      
+      if (current == 0) {
+        NProgress.start();
+      }
+      
+      initial++;
+      current++;
+      
+      $promise.always(function() {
+        current--;
+        if (current == 0) {
+            initial = 0;
+            NProgress.done();
+        } else {
+            NProgress.set((initial - current) / initial);
+        }
+      });
+      
+      return this;
+    };
+    
+  })();
+
+  /**
+   * (Internal) renders the progress bar markup based on the `template`
+   * setting.
+   */
+
+  NProgress.render = function(fromStart) {
+    if (NProgress.isRendered()) return document.getElementById('nprogress');
+
+    addClass(document.documentElement, 'nprogress-busy');
+    
+    var progress = document.createElement('div');
+    progress.id = 'nprogress';
+    progress.innerHTML = Settings.template;
+
+    var bar      = progress.querySelector(Settings.barSelector),
+        perc     = fromStart ? '-100' : toBarPerc(NProgress.status || 0),
+        parent   = document.querySelector(Settings.parent),
+        spinner;
+    
+    css(bar, {
+      transition: 'all 0 linear',
+      transform: 'translate3d(' + perc + '%,0,0)'
+    });
+
+    if (!Settings.showSpinner) {
+      spinner = progress.querySelector(Settings.spinnerSelector);
+      spinner && removeElement(spinner);
+    }
+
+    if (parent != document.body) {
+      addClass(parent, 'nprogress-custom-parent');
+    }
+
+    parent.appendChild(progress);
+    return progress;
+  };
+
+  /**
+   * Removes the element. Opposite of render().
+   */
+
+  NProgress.remove = function() {
+    removeClass(document.documentElement, 'nprogress-busy');
+    removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent')
+    var progress = document.getElementById('nprogress');
+    progress && removeElement(progress);
+  };
+
+  /**
+   * Checks if the progress bar is rendered.
+   */
+
+  NProgress.isRendered = function() {
+    return !!document.getElementById('nprogress');
+  };
+
+  /**
+   * Determine which positioning CSS rule to use.
+   */
+
+  NProgress.getPositioningCSS = function() {
+    // Sniff on document.body.style
+    var bodyStyle = document.body.style;
+
+    // Sniff prefixes
+    var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :
+                       ('MozTransform' in bodyStyle) ? 'Moz' :
+                       ('msTransform' in bodyStyle) ? 'ms' :
+                       ('OTransform' in bodyStyle) ? 'O' : '';
+
+    if (vendorPrefix + 'Perspective' in bodyStyle) {
+      // Modern browsers with 3D support, e.g. Webkit, IE10
+      return 'translate3d';
+    } else if (vendorPrefix + 'Transform' in bodyStyle) {
+      // Browsers without 3D support, e.g. IE9
+      return 'translate';
+    } else {
+      // Browsers without translate() support, e.g. IE7-8
+      return 'margin';
+    }
+  };
+
+  /**
+   * Helpers
+   */
+
+  function clamp(n, min, max) {
+    if (n < min) return min;
+    if (n > max) return max;
+    return n;
+  }
+
+  /**
+   * (Internal) converts a percentage (`0..1`) to a bar translateX
+   * percentage (`-100%..0%`).
+   */
+
+  function toBarPerc(n) {
+    return (-1 + n) * 100;
+  }
+
+
+  /**
+   * (Internal) returns the correct CSS for changing the bar's
+   * position given an n percentage, and speed and ease from Settings
+   */
+
+  function barPositionCSS(n, speed, ease) {
+    var barCSS;
+
+    if (Settings.positionUsing === 'translate3d') {
+      barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };
+    } else if (Settings.positionUsing === 'translate') {
+      barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };
+    } else {
+      barCSS = { 'margin-left': toBarPerc(n)+'%' };
+    }
+
+    barCSS.transition = 'all '+speed+'ms '+ease;
+
+    return barCSS;
+  }
+
+  /**
+   * (Internal) Queues a function to be executed.
+   */
+
+  var queue = (function() {
+    var pending = [];
+    
+    function next() {
+      var fn = pending.shift();
+      if (fn) {
+        fn(next);
+      }
+    }
+
+    return function(fn) {
+      pending.push(fn);
+      if (pending.length == 1) next();
+    };
+  })();
+
+  /**
+   * (Internal) Applies css properties to an element, similar to the jQuery 
+   * css method.
+   *
+   * While this helper does assist with vendor prefixed property names, it 
+   * does not perform any manipulation of values prior to setting styles.
+   */
+
+  var css = (function() {
+    var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ],
+        cssProps    = {};
+
+    function camelCase(string) {
+      return string.replace(/^-ms-/, 'ms-').replace(/-([\da-z])/gi, function(match, letter) {
+        return letter.toUpperCase();
+      });
+    }
+
+    function getVendorProp(name) {
+      var style = document.body.style;
+      if (name in style) return name;
+
+      var i = cssPrefixes.length,
+          capName = name.charAt(0).toUpperCase() + name.slice(1),
+          vendorName;
+      while (i--) {
+        vendorName = cssPrefixes[i] + capName;
+        if (vendorName in style) return vendorName;
+      }
+
+      return name;
+    }
+
+    function getStyleProp(name) {
+      name = camelCase(name);
+      return cssProps[name] || (cssProps[name] = getVendorProp(name));
+    }
+
+    function applyCss(element, prop, value) {
+      prop = getStyleProp(prop);
+      element.style[prop] = value;
+    }
+
+    return function(element, properties) {
+      var args = arguments,
+          prop, 
+          value;
+
+      if (args.length == 2) {
+        for (prop in properties) {
+          value = properties[prop];
+          if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);
+        }
+      } else {
+        applyCss(element, args[1], args[2]);
+      }
+    }
+  })();
+
+  /**
+   * (Internal) Determines if an element or space separated list of class names contains a class name.
+   */
+
+  function hasClass(element, name) {
+    var list = typeof element == 'string' ? element : classList(element);
+    return list.indexOf(' ' + name + ' ') >= 0;
+  }
+
+  /**
+   * (Internal) Adds a class to an element.
+   */
+
+  function addClass(element, name) {
+    var oldList = classList(element),
+        newList = oldList + name;
+
+    if (hasClass(oldList, name)) return; 
+
+    // Trim the opening space.
+    element.className = newList.substring(1);
+  }
+
+  /**
+   * (Internal) Removes a class from an element.
+   */
+
+  function removeClass(element, name) {
+    var oldList = classList(element),
+        newList;
+
+    if (!hasClass(element, name)) return;
+
+    // Replace the class name.
+    newList = oldList.replace(' ' + name + ' ', ' ');
+
+    // Trim the opening and closing spaces.
+    element.className = newList.substring(1, newList.length - 1);
+  }
+
+  /**
+   * (Internal) Gets a space separated list of the class names on the element. 
+   * The list is wrapped with a single space on each end to facilitate finding 
+   * matches within the list.
+   */
+
+  function classList(element) {
+    return (' ' + (element.className || '') + ' ').replace(/\s+/gi, ' ');
+  }
+
+  /**
+   * (Internal) Removes an element from the DOM.
+   */
+
+  function removeElement(element) {
+    element && element.parentNode && element.parentNode.removeChild(element);
+  }
+
+  return NProgress;
+});
+
index 9be2c0d..a2557e6 100644 (file)
@@ -29,7 +29,7 @@ TYPO3.backendContentIframePanel = Ext.extend(TYPO3.iframePanel ,{
                        } else {
                                wrapper.getLayout().setActiveItem(this.id);
                                this.body.dom.src = source;
-                               this.setMask();
+                               this.startLoader();
                        }
                }
        },
index 903bd35..e121f71 100644 (file)
@@ -24,8 +24,7 @@ TYPO3.iframePanel = Ext.extend(Ext.Panel, {
        name: 'iframe',
        iframe: null,
        src: Ext.isIE && Ext.isSecure ? Ext.SSL_SECURE_URL : 'about:blank',
-       maskMessage: ' ',
-       doMask: true,
+       showLoadingIndicator: true,
 
                // component build
        initComponent: function() {
@@ -36,9 +35,6 @@ TYPO3.iframePanel = Ext.extend(Ext.Panel, {
                        name: this.name,
                        style: 'float:left;' // this is needed to prevent offset of 2.5 pixel, see #15771
                }
-               Ext.apply(this, {
-
-               });
                TYPO3.iframePanel.superclass.initComponent.apply(this, arguments);
 
                // apply the addListener patch for 'message:tagging'
@@ -48,14 +44,13 @@ TYPO3.iframePanel = Ext.extend(Ext.Panel, {
 
        onRender : function() {
                TYPO3.iframePanel.superclass.onRender.apply(this, arguments);
-               this.maskMessage = ' ';
                this.iframe = Ext.isIE ? this.body.dom.contentWindow : window.frames[this.name];
                this.body.dom[Ext.isIE ? 'onreadystatechange' : 'onload'] = this.loadHandler.createDelegate(this);
        },
 
        loadHandler: function() {
                this.src = this.body.dom.src;
-               this.removeMask();
+               this.finishLoader();
        },
 
        getIframe: function() {
@@ -67,7 +62,7 @@ TYPO3.iframePanel = Ext.extend(Ext.Panel, {
 
        setUrl: function(source) {
                this.body.dom.src = source;
-               this.setMask();
+               this.startLoader();
        },
 
        resetUrl: function() {
@@ -83,30 +78,27 @@ TYPO3.iframePanel = Ext.extend(Ext.Panel, {
                if (!this.isVisible()) {
             return;
         }
-        this.setMask();
+               this.startLoader();
                this.body.dom.src = this.body.dom.src;
        },
 
-       /** @private */
-       setMask: function() {
-               if (this.doMask) {
-                       this.el.mask(this.maskMessage, 'x-mask-loading-message');
-                       this.el.addClass('t3-mask-loading');
-                               // add an onClick handler to remove the mask while clicking on the loading message
-                               // useful if user cancels loading and wants to access the content again
-                       this.el.child('.x-mask-loading-message').on(
-                               'click',
-                               function() {
-                                       this.el.unmask();
-                               },
-                               this
-                       );
+       /**
+        * wrapper function for nprogress
+        */
+       startLoader: function() {
+               if (this.showLoadingIndicator) {
+                       require(['nprogress'], function(NProgress) {
+                               NProgress.configure({parent: '#typo3-contentContainer', showSpinner: false});
+                               NProgress.start();
+                       });
                }
        },
 
-       removeMask: function() {
-               if (this.doMask) {
-                       this.el.unmask();
+       finishLoader: function() {
+               if (this.showLoadingIndicator) {
+                       require(['nprogress'], function(NProgress) {
+                               NProgress.done();
+                       });
                }
        }
 });
index fc450e6..632fd7f 100644 (file)
@@ -64,15 +64,17 @@ var inline = {
 
                var $currentObject = TYPO3.jQuery('#' + escapedObjectId + '_div');
                // if content is not loaded yet, get it now from server
-               if (inline.isLoading || (TYPO3.jQuery('#' + escapedObjectId + '_fields').length > 0 && TYPO3.jQuery("#irre-loading-indicator" + escapedObjectId).length > 0)) {
+               if (inline.isLoading) {
                        return false;
                } else if (TYPO3.jQuery('#' + escapedObjectId + '_fields').length > 0 && TYPO3.jQuery('#' + escapedObjectId + '_fields').html().substr(0, 16) == '<!--notloaded-->') {
                        inline.isLoading = true;
+                       var headerIdentifier = '#' + escapedObjectId + '_header';
                        // add loading-indicator
-                       if (TYPO3.jQuery('#' + escapedObjectId + '_loadingbar').length === 0) {
-                               var loadingBar = '<div id="' + objectId + '_loadingbar" class="t3-form-header-inline-loadingbar loadingbar"><div class="expand"></div></div>';
-                               TYPO3.jQuery('#' + escapedObjectId + '_header').after(loadingBar);
-                       }
+                       require(['nprogress'], function(NProgress) {
+                               inline.progress = NProgress;
+                               inline.progress.configure({parent: headerIdentifier, showSpinner: false});
+                               inline.progress.start();
+                       });
                        return this.getRecordDetails(objectId, returnURL);
                }
 
@@ -198,10 +200,16 @@ var inline = {
                                success: function (data, message, jqXHR) {
                                        inline.isLoading = false;
                                        inline.processAjaxResponse(method, jqXHR);
+                                       if (inline.progress) {
+                                               inline.progress.done();
+                                       }
                                },
                                error: function (jqXHR, statusText, errorThrown) {
                                        inline.isLoading = false;
                                        inline.showAjaxFailure(method, jqXHR);
+                                       if (inline.progress) {
+                                               inline.progress.done();
+                                       }
                                }
                        };
 
@@ -535,9 +543,6 @@ var inline = {
                        formObj[0].checked = hiddenValue;
                }
 
-               // remove loading-indicator
-               TYPO3.jQuery('#' + escapeObjectId + '_loadingbar').remove();
-
                // now that the content is loaded, set the expandState
                this.expandCollapseRecord(objectId, expandSingle);
        },
index b25baf6..1b24e98 100644 (file)
@@ -1620,6 +1620,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
                        $this->requireJsConfig['paths'] = array(
                                'jquery-ui' => $this->backPath . 'contrib/jquery-ui',
                                'jquery' => $this->backPath . 'contrib/jquery',
+                               'nprogress' => $this->backPath . 'contrib/nprogress/nprogress',
                                'moment' => $this->backPath . 'contrib/moment/moment.min',
                                'twbs' => $this->backPath . 'contrib/twbs/bootstrap.min',
                                'twbs/bootstrap-datetimepicker' => $this->backPath . 'contrib/twbs/bootstrap-datetimepicker.min',
index 26fa7fa..293afb9 100644 (file)
@@ -856,10 +856,6 @@ TCEforms Inline-Relational-Record-Editing
        background-color: #cccccc;
 }
 
-.t3-form-header-inline-loadingbar {
-       border-top: 1px solid #aaaaaa;
-}
-
 .t3-form-field-container-inline-hidden,
 .t3-form-field-container-inline-placeHolder {
        opacity:0.3;
diff --git a/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_misc_loading.less b/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_misc_loading.less
deleted file mode 100644 (file)
index e7407ed..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/* - - - - - - - - - - - - - - - - - - - - -
-Loadingbar and Animations
-- - - - - - - - - - - - - - - - - - - - - */
-
-.loadingbar {
-       background-color: #f9f9f9;
-       display: block;
-       position: relative;
-}
-
-.cssanimations .loadingbar {
-       height: 5px;
-}
-
-.no-cssanimations .loadingbar {
-       height: 24px;
-       background-image: url('../../../../images/spinner/ffffff.gif');
-       background-repeat: no-repeat;
-       background-position: center center;
-}
-
-@keyframes fullexpand {
-       0% { width: 0px; }
-       100% { width: 100%; }
-}
-
-@-moz-keyframes fullexpand {
-       0% { width: 0px; }
-       100% { width: 100%; }
-}
-
-@-webkit-keyframes fullexpand {
-       0% { width: 0px; }
-       100% { width: 100%; }
-}
-
-@-o-keyframes fullexpand {
-       0% { width: 0px; }
-       100% { width: 100%; }
-}
-
-@-ms-keyframes fullexpand {
-       0% { width: 0px; }
-       100% { width: 100%; }
-}
-
-.cssanimations .loadingbar .expand {
-       width: 100%;
-       height: 5px;
-       background: #585858;
-       position: absolute;
-       animation: fullexpand 5s linear infinite;
-       -moz-animation:fullexpand 5s linear infinite;
-       -webkit-animation: fullexpand 5s linear infinite;
-       -o-animation: fullexpand 5s linear infinite;
-       -ms-animation: fullexpand 5s linear infinite;
-}
\ No newline at end of file
diff --git a/typo3/sysext/t3skin/Resources/Private/Styles/nprogress/nprogress.less b/typo3/sysext/t3skin/Resources/Private/Styles/nprogress/nprogress.less
new file mode 100644 (file)
index 0000000..92bec28
--- /dev/null
@@ -0,0 +1,82 @@
+/**
+ * original color: #29d
+ * modified for less with the @nprogress-color
+ * variable by the TYPO3 CMS team to adapt
+ * to the styles of TYPO3
+ */
+@nprogress-color: #FF8700;
+
+/* Make clicks pass-through */
+#nprogress {
+  pointer-events: none;
+}
+
+#nprogress .bar {
+  background: @nprogress-color;
+
+  position: fixed;
+  z-index: 1031;
+  top: 0;
+  left: 0;
+
+  width: 100%;
+  height: 4px;
+}
+
+/* Fancy blur effect */
+#nprogress .peg {
+  display: block;
+  position: absolute;
+  right: 0px;
+  width: 100px;
+  height: 100%;
+  box-shadow: 0 0 10px @nprogress-color, 0 0 5px @nprogress-color;
+  opacity: 1.0;
+
+  -webkit-transform: rotate(3deg) translate(0px, -4px);
+      -ms-transform: rotate(3deg) translate(0px, -4px);
+          transform: rotate(3deg) translate(0px, -4px);
+}
+
+/* Remove these to get rid of the spinner */
+#nprogress .spinner {
+  display: block;
+  position: fixed;
+  z-index: 1031;
+  top: 15px;
+  right: 15px;
+}
+
+#nprogress .spinner-icon {
+  width: 18px;
+  height: 18px;
+  box-sizing: border-box;
+
+  border: solid 2px transparent;
+  border-top-color: @nprogress-color;
+  border-left-color: @nprogress-color;
+  border-radius: 50%;
+
+  -webkit-animation: nprogress-spinner 400ms linear infinite;
+          animation: nprogress-spinner 400ms linear infinite;
+}
+
+.nprogress-custom-parent {
+  overflow: hidden;
+  position: relative;
+}
+
+.nprogress-custom-parent #nprogress .spinner,
+.nprogress-custom-parent #nprogress .bar {
+  position: absolute;
+}
+
+@-webkit-keyframes nprogress-spinner {
+  0%   { -webkit-transform: rotate(0deg); }
+  100% { -webkit-transform: rotate(360deg); }
+}
+@keyframes nprogress-spinner {
+  0%   { transform: rotate(0deg); }
+  100% { transform: rotate(360deg); }
+}
+
index f3be072..a642fa4 100644 (file)
 @import "@{composer-package-directory-prefix}/fortawesome/font-awesome/less/icons.less";
 
 /*!
+ * add nprogress styles, adapted to TYPO3 needs
+ */
+@import "nprogress/nprogress.less";
+
+/*!
  * TYPO3
  */
 
 @import "TYPO3/_main_content.less";
 @import "TYPO3/_main_form.less";
 @import "TYPO3/_main_scaffolding.less";
-@import "TYPO3/_misc_loading.less";
 @import "TYPO3/_module_menu.less";
 @import "TYPO3/_topbar.less";
 
index 77a71ae..3932ec4 100644 (file)
@@ -6806,6 +6806,84 @@ button.close {
   content: "\f20c";
 }
 /*!
+ * add nprogress styles, adapted to TYPO3 needs
+ */
+/**
+ * original color: #29d
+ * modified for less with the @nprogress-color
+ * variable by the TYPO3 CMS team to adapt
+ * to the styles of TYPO3
+ */
+/* Make clicks pass-through */
+#nprogress {
+  pointer-events: none;
+}
+#nprogress .bar {
+  background: #ff8700;
+  position: fixed;
+  z-index: 1031;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 4px;
+}
+/* Fancy blur effect */
+#nprogress .peg {
+  display: block;
+  position: absolute;
+  right: 0px;
+  width: 100px;
+  height: 100%;
+  box-shadow: 0 0 10px #ff8700, 0 0 5px #ff8700;
+  opacity: 1.0;
+  -webkit-transform: rotate(3deg) translate(0px, -4px);
+  -ms-transform: rotate(3deg) translate(0px, -4px);
+  transform: rotate(3deg) translate(0px, -4px);
+}
+/* Remove these to get rid of the spinner */
+#nprogress .spinner {
+  display: block;
+  position: fixed;
+  z-index: 1031;
+  top: 15px;
+  right: 15px;
+}
+#nprogress .spinner-icon {
+  width: 18px;
+  height: 18px;
+  box-sizing: border-box;
+  border: solid 2px transparent;
+  border-top-color: #ff8700;
+  border-left-color: #ff8700;
+  border-radius: 50%;
+  -webkit-animation: nprogress-spinner 400ms linear infinite;
+  animation: nprogress-spinner 400ms linear infinite;
+}
+.nprogress-custom-parent {
+  overflow: hidden;
+  position: relative;
+}
+.nprogress-custom-parent #nprogress .spinner,
+.nprogress-custom-parent #nprogress .bar {
+  position: absolute;
+}
+@-webkit-keyframes nprogress-spinner {
+  0% {
+    -webkit-transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+  }
+}
+@keyframes nprogress-spinner {
+  0% {
+    transform: rotate(0deg);
+  }
+  100% {
+    transform: rotate(360deg);
+  }
+}
+/*!
  * TYPO3
  */
 /*
@@ -10349,9 +10427,6 @@ TCEforms Inline-Relational-Record-Editing
 .t3-form-field-header-inline:hover {
   background-color: #cccccc;
 }
-.t3-form-header-inline-loadingbar {
-  border-top: 1px solid #aaaaaa;
-}
 .t3-form-field-container-inline-hidden,
 .t3-form-field-container-inline-placeHolder {
   opacity: 0.3;
@@ -11576,86 +11651,6 @@ iframe {
  * The TYPO3 project - inspiring people to share!
  */
 /* - - - - - - - - - - - - - - - - - - - - -
-Loadingbar and Animations
-- - - - - - - - - - - - - - - - - - - - - */
-.loadingbar {
-  background-color: #f9f9f9;
-  display: block;
-  position: relative;
-}
-.cssanimations .loadingbar {
-  height: 5px;
-}
-.no-cssanimations .loadingbar {
-  height: 24px;
-  background-image: url('../../../../images/spinner/ffffff.gif');
-  background-repeat: no-repeat;
-  background-position: center center;
-}
-@keyframes fullexpand {
-  0% {
-    width: 0px;
-  }
-  100% {
-    width: 100%;
-  }
-}
-@-moz-keyframes fullexpand {
-  0% {
-    width: 0px;
-  }
-  100% {
-    width: 100%;
-  }
-}
-@-webkit-keyframes fullexpand {
-  0% {
-    width: 0px;
-  }
-  100% {
-    width: 100%;
-  }
-}
-@-o-keyframes fullexpand {
-  0% {
-    width: 0px;
-  }
-  100% {
-    width: 100%;
-  }
-}
-@-ms-keyframes fullexpand {
-  0% {
-    width: 0px;
-  }
-  100% {
-    width: 100%;
-  }
-}
-.cssanimations .loadingbar .expand {
-  width: 100%;
-  height: 5px;
-  background: #585858;
-  position: absolute;
-  animation: fullexpand 5s linear infinite;
-  -moz-animation: fullexpand 5s linear infinite;
-  -webkit-animation: fullexpand 5s linear infinite;
-  -o-animation: fullexpand 5s linear infinite;
-  -ms-animation: fullexpand 5s linear infinite;
-}
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-/* - - - - - - - - - - - - - - - - - - - - -
 Module menu
 - - - - - - - - - - - - - - - - - - - - - */
 [id="typo3-module-menu"] {
index 7dfe557..4af8b64 100644 (file)
@@ -57,7 +57,7 @@ Ext.onReady(function() {
                                        xtype: 'iframePanel',
                                        x: 0, y:0,
                                        id: 'wsPanel',
-                                       doMask: false,
+                                       showLoadingIndicator: false,
                                        src: wsUrl,
                                        autoScroll: false
                                }]
@@ -72,7 +72,7 @@ Ext.onReady(function() {
                                        xtype: 'iframePanel',
                                        x: 0, y:0,
                                        id: 'livePanel',
-                                       doMask: false,
+                                       showLoadingIndicator: false,
                                        src: liveUrl,
                                        autoScroll: false
                                }]
@@ -92,7 +92,7 @@ Ext.onReady(function() {
                        xtype: 'iframePanel',
                        x: 0, y:0,
                        id: 'wsPanel-hbox',
-                       doMask: false,
+                       showLoadingIndicator: false,
                        src: wsUrl,
                        autoScroll: false,
                        flex: 1
@@ -100,7 +100,7 @@ Ext.onReady(function() {
                        xtype: 'iframePanel',
                        x: 0, y:0,
                        id: 'livePanel-hbox',
-                       doMask: false,
+                       showLoadingIndicator: false,
                        src: liveUrl,
                        autoScroll: false,
                        flex: 1
@@ -119,7 +119,7 @@ Ext.onReady(function() {
                        xtype: 'iframePanel',
                        x: 0, y:0,
                        id: 'wsPanel-vbox',
-                       doMask: false,
+                       showLoadingIndicator: false,
                        src: wsUrl,
                        autoScroll: false,
                        flex: 1
@@ -127,7 +127,7 @@ Ext.onReady(function() {
                        xtype: 'iframePanel',
                        x: 0, y:0,
                        id: 'livePanel-vbox',
-                       doMask: false,
+                       showLoadingIndicator: false,
                        src: liveUrl,
                        autoScroll: false,
                        flex: 1
@@ -330,7 +330,7 @@ Ext.onReady(function() {
                                items:  [{
                                        xtype: 'iframePanel',
                                        id: 'settingsPanel',
-                                       doMask: false,
+                                       showLoadingIndicator: false,
                                        src: wsSettingsUrl
                                }]
                        }]
@@ -388,4 +388,4 @@ Ext.onReady(function() {
                        }
                }
        }
-});
\ No newline at end of file
+});