]> _ Git - fluidbook-v3.git/commitdiff
Major home page updates to handle full page scrolling and responsiveness. WIP #4
authorstephen@cubedesigners.com <stephen@cubedesigners.com@f5622870-0f3c-0410-866d-9cb505b7a8ef>
Wed, 17 Aug 2016 17:59:50 +0000 (17:59 +0000)
committerstephen@cubedesigners.com <stephen@cubedesigners.com@f5622870-0f3c-0410-866d-9cb505b7a8ef>
Wed, 17 Aug 2016 17:59:50 +0000 (17:59 +0000)
14 files changed:
framework/application/views/helpers/ContactFooter.php
framework/application/views/helpers/HomeFeatures.php
framework/application/views/helpers/HomeIntro.php
framework/application/views/helpers/HomeLayer.php
framework/application/views/scripts/common/footer.phtml
framework/application/views/scripts/templates/home.phtml
js/002-common.js
js/101-header.js
js/209-scrollify.js [new file with mode: 0644]
js/210-home.js
less/002-common.less
less/210-home.less
less/211-home-intro.less
less/212-home-features.less [new file with mode: 0644]

index c56e97582f4f95da6abd6f5ad67766294b4e0ecf..37e6a6082a2a673a015fbc56a6267acbad5295cb 100644 (file)
@@ -21,6 +21,9 @@ class Fluidbook_View_Helper_ContactFooter extends CubeIT_View_Helper_Abstract {
                $res = $this->htmlElement($res, 'div', array('class' => 'grid'));\r
                $res = $this->backgroundBlock($res, $cf, array('content-wrapper'));\r
 \r
-               return $this->htmlElement($res, 'section', array('class' => 'contactFooter section'));\r
+               return $this->htmlElement($res, 'section', array(\r
+                   'class' => 'contactFooter section',\r
+            'data-themecolor' => '#8aab41', // Todo: possibly set this via the admin?\r
+            'data-section-name' => 'contact'));\r
        }\r
 }
\ No newline at end of file
index d6340c7d6bb9e5a21cbdd4f78512e12768980bff..a7d5ef8838ebd13cad8e67ea1d3255dcb13da0a7 100644 (file)
@@ -6,6 +6,8 @@ class Fluidbook_View_Helper_HomeFeatures extends Fluidbook_View_Helper_HomeLayer
         */\r
        public function homeFeatures($data) {\r
 \r
+        $this->headScript()->addScriptAndStyle('212-home-features');\r
+\r
                $this->data = $data;\r
 \r
                $res .= $this->_leftText();\r
index 467c25b887fde58798670be1847f6101c3540add..209053bdffae3066f588ef22776d80b41c379c83 100644 (file)
@@ -10,9 +10,11 @@ class Fluidbook_View_Helper_HomeIntro extends Fluidbook_View_Helper_HomeLayer {
 \r
         $this->data = $data;\r
 \r
-        $res=$this->_leftText();\r
+        $res  = $this->_leftText();\r
 \r
-               return $this->_layer($res, 'intro');\r
+        $arrow = $this->link(null, '#', ['class' => 'scroll-arrow']);\r
+\r
+               return $this->_layer($res, 'intro', [], $arrow);\r
        }\r
 \r
 \r
index 782de74ef76bdfd458bc9cdebff1a5290d8a35aa..c72a972d7d5094724c80994361dadf46e242981f 100644 (file)
@@ -5,9 +5,14 @@ class Fluidbook_View_Helper_HomeLayer extends CubeIT_View_Helper_Abstract {
 \r
        protected function _layer($content, $class, $attributes = array(), $outerContent = '') {\r
 \r
+           $section = $class;\r
+\r
                $class .= ' section ' . $this->data['headerstyle'];\r
 \r
-               $defaultAttributes = array('class' => $class, 'data-headerstyle' => $this->data['headerstyle']);\r
+               $defaultAttributes = array('class' => $class,\r
+                                   'data-headerstyle' => $this->data['headerstyle'],\r
+                                   'data-themecolor' => $this->data['themecolor'],\r
+                                   'data-section-name' => $section);\r
                $attributes = $this->_mergeAttributes($attributes, $defaultAttributes);\r
 \r
                $content = $this->htmlElement($content, 'div', array('class' => 'content-inner'));\r
index 2e06d828e27df98d3e33bd1c2664d154a8cfe148..5ab031f654c5a5fa4717c6f3f594c4553cdd7cb0 100644 (file)
@@ -86,4 +86,4 @@ $res .= '</div>'; // .footer-inner
 $res .= '</footer>'; // footer.legal\r
 \r
 // Output footer with Organization microdata wrapper\r
-echo $this->microdata($res, ['class' => 'section fp-auto-height'], 'Organization');
\ No newline at end of file
+echo $this->microdata($res, ['class' => 'auto-height'], 'Organization');
\ No newline at end of file
index 9c510a8cd541fab71e0f649a74bd312494974f25..896849c0f1efda5938479d0d93a6a914d5ccdb82 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 \r
-//$this->headScript()->addFullPage();\r
+$this->headScript()->addScriptAndStyle('209-scrollify'); // Patched version of Scrollify script\r
 $this->headScript()->addScriptAndStyle('210-home');\r
 \r
 echo $this->home();
\ No newline at end of file
index 217de63877c55fd4fbe748690495406e81c03ce7..0a277e90c4da952dbbca0251023a6c204c3cc4a5 100644 (file)
@@ -1,5 +1,6 @@
 registerLoader(load_common, true);\r
 var zoom = 1;\r
+var maxContentWidth = 1680;\r
 var _mobile = null;\r
 \r
 function load_common() {\r
@@ -69,7 +70,7 @@ function resize() {
     $('main').css('min-height', mainHeight);\r
 \r
     // Handle divs with background images that must have a proportional min-height\r
-    $('[data-bg-ratio]:not(.fullheight)').each(function () {\r
+    $('body:not(.home) [data-bg-ratio]').each(function () {\r
         $(this).css('min-height', Math.round($(this).outerWidth() * $(this).data('bg-ratio')));\r
     });\r
 \r
@@ -83,11 +84,22 @@ function resize() {
     $(window).trigger('fluidbookresize');\r
 }\r
 \r
-function setZoom(ww) {\r
+function calculateZoom(ww) {\r
+\r
+    if (typeof ww === 'undefined') {\r
+        ww = $(window).outerWidth();\r
+    }\r
+\r
     zoom = 1;\r
-    if (ww >= 1680) {\r
-        zoom = ww / 1680;\r
+    if (ww >= maxContentWidth) {\r
+        zoom = ww / maxContentWidth;\r
     }\r
+}\r
+\r
+function setZoom(ww) {\r
+\r
+    calculateZoom(ww);\r
+\r
     var transform = '';\r
     if (zoom > 1) {\r
         transform = 'scale(' + zoom + ')';\r
index 16a17fc101714d4308bd798bb385376b2dfef354..2ed187b5a2abba601ea853078027b9db65b113a1 100644 (file)
@@ -5,6 +5,7 @@ var scrolledDistance = 0;
 var headerPos = 0;\r
 var htl;\r
 var home = false;\r
+var fullPages = false;\r
 \r
 registerLoader(load_header, true);\r
 \r
@@ -26,13 +27,13 @@ function resizeHeader() {
 }\r
 \r
 function setHeaderAnimation() {\r
-    fb('set header information');\r
     var h = $('#h');\r
-    home = $("body").hasClass('home');\r
+    home = $('body').hasClass('home');\r
+    fullPages = $('body').hasClass('fullpages'); // Are we in full page mode?\r
 \r
     var bgcolor = "#fff";\r
     var boxshadow = '0 0 120px rgba(0,0,0,0.3)';\r
-    if (home && !isMobile()) {\r
+    if (fullPages && !isMobile()) {\r
         bgcolor = 'transparent';\r
         boxshadow = '0 0 0 rgba(0,0,0,0)';\r
     }\r
@@ -45,7 +46,7 @@ function setHeaderAnimation() {
     // Background-color & height\r
     htl.add(TweenMax.fromTo(h, 1.5, {height: 90}, {height: 75}), 0);\r
     htl.add(TweenMax.fromTo(h, 1, {backgroundColor: 'transparent', boxShadow: '0 0 0 rgba(0,0,0,0)'}, {backgroundColor: bgcolor, boxShadow: boxshadow}), 1);\r
-    if (home && isMobile()) {\r
+    if (home && (isMobile() || !fullPages)) {\r
         htl.add(TweenMax.fromTo($("#h,#nav-icon"), 1, {className: $("main section:first").data('headerstyle')}, {className: "-=light"}), 1);\r
     }\r
     htl.add(TweenMax.fromTo($(h).find('#header'), 1.5, {height: 90}, {height: 56}), 0);\r
@@ -113,7 +114,7 @@ function headerScroll() {
     }\r
     // Normalize top value\r
     var top = Math.max(-headerHeight, Math.min(adminHeight, htop + adminHeight));\r
-    if (home && !isMobile()) {\r
+    if (home && !isMobile() && fullPages) {\r
         top = adminHeight;\r
     }\r
     $(h).css('top', top);\r
@@ -124,15 +125,13 @@ function headerScroll() {
     formerScroll = s;\r
     scrollUp = goingUp;\r
 \r
-    if (home && !isMobile()) {\r
+    if (fullPages && !isMobile()) {\r
         changeHeaderStyle();\r
     }\r
 }\r
 \r
 function changeHeaderStyle() {\r
 \r
-    // Todo: rework all this to be compatible with FullPage.js - see callbacks...\r
-\r
     var scrollTop = $(window).scrollTop();\r
     var wh = $(window).height();\r
     var section;\r
diff --git a/js/209-scrollify.js b/js/209-scrollify.js
new file mode 100644 (file)
index 0000000..4019b47
--- /dev/null
@@ -0,0 +1,808 @@
+//### PATCHED VERSION TO SUPPORT CONTENT SCALING - see ~line 632 for changes  ###//
+
+/*!
+ * jQuery Scrollify
+ * Version 1.0.4
+ *
+ * Requires:
+ * - jQuery 1.6 or higher
+ *
+ * https://github.com/lukehaas/Scrollify
+ *
+ * Copyright 2016, Luke Haas
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+ If section being scrolled to is an interstitialSection and the last section on page
+
+ then value to scroll to is current position plus height of interstitialSection
+
+ */
+(function (global,factory) {
+    "use strict";
+    if (typeof define === 'function' && define.amd) {
+        // AMD. Register as an anonymous module.
+        define(['jquery'], function($) {
+            return factory($, global, global.document);
+        });
+    } else if (typeof module === 'object' && module.exports) {
+        // Node/CommonJS
+        module.exports = function( root, jQuery ) {
+            if ( jQuery === undefined ) {
+                // require('jQuery') returns a factory that requires window to
+                // build a jQuery instance, we normalize how we use modules
+                // that require this pattern but the window provided is a noop
+                // if it's defined (how jquery works)
+                if ( typeof window !== 'undefined' ) {
+                    jQuery = require('jquery');
+                }
+                else {
+                    jQuery = require('jquery')(root);
+                }
+            }
+            factory(jQuery, global, global.document);
+            return jQuery;
+        };
+    } else {
+        // Browser globals
+        factory(jQuery, global, global.document);
+    }
+}(typeof window !== 'undefined' ? window : this, function ($, window, document, undefined) {
+    "use strict";
+    var heights = [],
+        names = [],
+        elements = [],
+        overflow = [],
+        index = 0,
+        currentIndex = 0,
+        interstitialIndex = 1,
+        hasLocation = false,
+        timeoutId,
+        timeoutId2,
+        $window = $(window),
+        top = $window.scrollTop(),
+        scrollable = false,
+        locked = false,
+        scrolled = false,
+        manualScroll,
+        swipeScroll,
+        util,
+        disabled = false,
+        scrollSamples = [],
+        scrollTime = new Date().getTime(),
+        firstLoad = true,
+        initialised = false,
+        wheelEvent = 'onwheel' in document ? 'wheel' : document.onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll',
+        settings = {
+            //section should be an identifier that is the same for each section
+            section: ".section",
+            sectionName: "section-name",
+            interstitialSection: "",
+            easing: "easeOutExpo",
+            scrollSpeed: 1100,
+            offset : 0,
+            scrollbars: true,
+            axis:"y",
+            target:"html,body",
+            standardScrollElements: false,
+            setHeights: true,
+            overflowScroll:true,
+            before:function() {},
+            after:function() {},
+            afterResize:function() {},
+            afterRender:function() {}
+        };
+    function animateScroll(index,instant,callbacks) {
+        if(currentIndex===index) {
+            callbacks = false;
+        }
+        if(disabled===true) {
+            return true;
+        }
+        if(names[index]) {
+            scrollable = false;
+            if(callbacks) {
+                settings.before(index,elements);
+            }
+            interstitialIndex = 1;
+            if(settings.sectionName && !(firstLoad===true && index===0)) {
+                if(history.pushState) {
+                    try {
+                        history.replaceState(null, null, names[index]);
+                    } catch (e) {
+                        if(window.console) {
+                            console.warn("Scrollify warning: This needs to be hosted on a server to manipulate the hash value.");
+                        }
+                    }
+
+                } else {
+                    window.location.hash = names[index];
+                }
+            }
+            if(instant) {
+                $(settings.target).stop().scrollTop(heights[index]);
+                if(callbacks) {
+                    settings.after(index,elements);
+                }
+            } else {
+                locked = true;
+                if( $().velocity ) {
+                    $(settings.target).stop().velocity('scroll', {
+                        duration: settings.scrollSpeed,
+                        easing: settings.easing,
+                        offset: heights[index],
+                        mobileHA: false
+                    });
+                } else {
+
+                    //console.info(index + ' -- Scrolling to: ' + heights[index] + ' | ' + settings.scrollSpeed + ' | ' + settings.easing);
+
+                    $(settings.target).stop().animate({
+                        scrollTop: heights[index]
+                    }, settings.scrollSpeed,settings.easing);
+                }
+
+                if(window.location.hash.length && settings.sectionName && window.console) {
+                    try {
+                        if($(window.location.hash).length) {
+                            console.warn("Scrollify warning: There are IDs on the page that match the hash value - this will cause the page to anchor.");
+                        }
+                    } catch (e) {
+                        console.warn("Scrollify warning:", window.location.hash, "is not a valid jQuery expression.");
+                    }
+                }
+                $(settings.target).promise().done(function(){
+                    currentIndex = index;
+                    locked = false;
+                    firstLoad = false;
+                    if(callbacks) {
+                        settings.after(index,elements);
+                    }
+                });
+            }
+
+        }
+    }
+
+    function isAccelerating(samples) {
+        function average(num) {
+            var sum = 0;
+
+            var lastElements = samples.slice(Math.max(samples.length - num, 1));
+
+            for(var i = 0; i < lastElements.length; i++){
+                sum += lastElements[i];
+            }
+
+            return Math.ceil(sum/num);
+        }
+
+        var avEnd = average(10);
+        var avMiddle = average(70);
+
+        if(avEnd >= avMiddle) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+    $.scrollify = function(options) {
+        initialised = true;
+
+        $.easing['easeOutExpo'] = function(x, t, b, c, d) {
+            return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+        };
+
+        manualScroll = {
+            handleMousedown:function() {
+                if(disabled===true) {
+                    return true;
+                }
+                scrollable = false;
+                scrolled = false;
+            },
+            handleMouseup:function() {
+                if(disabled===true) {
+                    return true;
+                }
+                scrollable = true;
+                if(scrolled) {
+                    manualScroll.calculateNearest();
+                }
+            },
+            handleScroll:function() {
+                if(disabled===true) {
+                    return true;
+                }
+                if(timeoutId){
+                    clearTimeout(timeoutId);
+                }
+                timeoutId = setTimeout(function(){
+
+                    scrolled = true;
+                    if(scrollable===false) {
+                        return false;
+                    }
+                    scrollable = false;
+                    manualScroll.calculateNearest();
+
+                }, 200);
+            },
+            calculateNearest:function() {
+                top = $window.scrollTop();
+                var i =1,
+                    max = heights.length,
+                    closest = 0,
+                    prev = Math.abs(heights[0] - top),
+                    diff;
+                for(;i<max;i++) {
+                    diff = Math.abs(heights[i] - top);
+
+                    if(diff < prev) {
+                        prev = diff;
+                        closest = i;
+                    }
+                }
+                if(atBottom() || atTop()) {
+                    index = closest;
+                    animateScroll(closest,false,true);
+                }
+            },
+            wheelHandler:function(e,delta) {
+                if(disabled===true) {
+                    return true;
+                } else if(settings.standardScrollElements) {
+                    if($(e.target).is(settings.standardScrollElements) || $(e.target).closest(settings.standardScrollElements).length) {
+                        return true;
+                    }
+                }
+                if(!overflow[index]) {
+                    e.preventDefault();
+                }
+                var currentScrollTime = new Date().getTime();
+
+
+
+                e = e || window.event;
+                var value = e.originalEvent.wheelDelta || -e.originalEvent.deltaY || -e.originalEvent.detail;
+                var delta = Math.max(-1, Math.min(1, value));
+
+
+
+                //delta = delta || -e.originalEvent.detail / 3 || e.originalEvent.wheelDelta / 120;
+
+
+                if(scrollSamples.length > 149){
+                    scrollSamples.shift();
+                }
+                //scrollSamples.push(Math.abs(delta*10));
+                scrollSamples.push(Math.abs(value));
+
+                if((currentScrollTime-scrollTime) > 200){
+                    scrollSamples = [];
+                }
+                scrollTime = currentScrollTime;
+
+
+                if(locked) {
+                    return false;
+                }
+
+                if(delta<0) {
+                    if(index<heights.length-1) {
+                        if(atBottom()) {
+                            if(isAccelerating(scrollSamples)) {
+                                e.preventDefault();
+                                index++;
+                                locked = true;
+                                animateScroll(index,false,true);
+                            } else {
+                                return false;
+                            }
+                        }
+                    }
+                } else if(delta>0) {
+                    if(index>0) {
+                        if(atTop()) {
+                            if(isAccelerating(scrollSamples)) {
+                                e.preventDefault();
+                                index--;
+                                locked = true;
+                                animateScroll(index,false,true);
+                            } else {
+                                return false
+                            }
+                        }
+                    }
+                }
+
+            },
+            keyHandler:function(e) {
+                if(disabled===true) {
+                    return true;
+                }
+                if(locked===true) {
+                    return false;
+                }
+                if(e.keyCode==38) {
+                    if(index>0) {
+                        if(atTop()) {
+                            e.preventDefault();
+                            index--;
+                            animateScroll(index,false,true);
+                        }
+                    }
+                } else if(e.keyCode==40) {
+                    if(index<heights.length-1) {
+                        if(atBottom()) {
+                            e.preventDefault();
+                            index++;
+                            animateScroll(index,false,true);
+                        }
+                    }
+                }
+            },
+            init:function() {
+                if(settings.scrollbars) {
+                    $window.bind('mousedown', manualScroll.handleMousedown);
+                    $window.bind('mouseup', manualScroll.handleMouseup);
+                    $window.bind('scroll', manualScroll.handleScroll);
+                } else {
+                    $("body").css({"overflow":"hidden"});
+                }
+
+                $(document).bind(wheelEvent,manualScroll.wheelHandler);
+                $(document).bind('keydown', manualScroll.keyHandler);
+            }
+        };
+
+        swipeScroll = {
+            touches : {
+                "touchstart": {"y":-1,"x":-1},
+                "touchmove" : {"y":-1,"x":-1},
+                "touchend"  : false,
+                "direction" : "undetermined"
+            },
+            options:{
+                "distance" : 30,
+                "timeGap" : 800,
+                "timeStamp" : new Date().getTime()
+            },
+            touchHandler: function(event) {
+                if(disabled===true) {
+                    return true;
+                } else if(settings.standardScrollElements) {
+                    if($(event.target).is(settings.standardScrollElements) || $(event.target).closest(settings.standardScrollElements).length) {
+                        return true;
+                    }
+                }
+                var touch;
+                if (typeof event !== 'undefined'){
+                    if (typeof event.touches !== 'undefined') {
+                        touch = event.touches[0];
+                        switch (event.type) {
+                            case 'touchstart':
+                                swipeScroll.touches.touchstart.y = touch.pageY;
+                                swipeScroll.touches.touchmove.y = -1;
+
+                                swipeScroll.touches.touchstart.x = touch.pageX;
+                                swipeScroll.touches.touchmove.x = -1;
+
+                                swipeScroll.options.timeStamp = new Date().getTime();
+                                swipeScroll.touches.touchend = false;
+                            case 'touchmove':
+                                swipeScroll.touches.touchmove.y = touch.pageY;
+                                swipeScroll.touches.touchmove.x = touch.pageX;
+                                if(swipeScroll.touches.touchstart.y!==swipeScroll.touches.touchmove.y && (Math.abs(swipeScroll.touches.touchstart.y-swipeScroll.touches.touchmove.y)>Math.abs(swipeScroll.touches.touchstart.x-swipeScroll.touches.touchmove.x))) {
+                                    //if(!overflow[index]) {
+                                    event.preventDefault();
+                                    //}
+                                    swipeScroll.touches.direction = "y";
+                                    if((swipeScroll.options.timeStamp+swipeScroll.options.timeGap)<(new Date().getTime()) && swipeScroll.touches.touchend == false) {
+
+                                        swipeScroll.touches.touchend = true;
+                                        if (swipeScroll.touches.touchstart.y > -1) {
+
+                                            if(Math.abs(swipeScroll.touches.touchmove.y-swipeScroll.touches.touchstart.y)>swipeScroll.options.distance) {
+                                                if(swipeScroll.touches.touchstart.y < swipeScroll.touches.touchmove.y) {
+
+                                                    swipeScroll.up();
+
+                                                } else {
+                                                    swipeScroll.down();
+
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                                break;
+                            case 'touchend':
+                                if(swipeScroll.touches[event.type]===false) {
+                                    swipeScroll.touches[event.type] = true;
+                                    if (swipeScroll.touches.touchstart.y > -1 && swipeScroll.touches.touchmove.y > -1 && swipeScroll.touches.direction==="y") {
+
+                                        if(Math.abs(swipeScroll.touches.touchmove.y-swipeScroll.touches.touchstart.y)>swipeScroll.options.distance) {
+                                            if(swipeScroll.touches.touchstart.y < swipeScroll.touches.touchmove.y) {
+                                                swipeScroll.up();
+
+                                            } else {
+                                                swipeScroll.down();
+
+                                            }
+                                        }
+                                        swipeScroll.touches.touchstart.y = -1;
+                                        swipeScroll.touches.touchstart.x = -1;
+                                        swipeScroll.touches.direction = "undetermined";
+                                    }
+                                }
+                            default:
+                                break;
+                        }
+                    }
+                }
+            },
+            down: function() {
+                if(index<=heights.length-1) {
+
+                    if(atBottom() && index<heights.length-1) {
+
+                        index++;
+                        animateScroll(index,false,true);
+                    } else {
+                        if(Math.floor(elements[index].height()/$window.height())>interstitialIndex) {
+
+                            // interstitialScroll(parseInt(heights[index])+($window.height()*interstitialIndex));
+                            interstitialScroll(Math.round(heights[index])+($window.height()*interstitialIndex));
+                            interstitialIndex += 1;
+
+                        } else {
+                            // interstitialScroll(parseInt(heights[index])+(elements[index].height()-$window.height()));
+                            interstitialScroll(Math.round(heights[index])+(elements[index].height()-$window.height()));
+                        }
+
+                    }
+                }
+            },
+            up: function() {
+                if(index>=0) {
+                    if(atTop() && index>0) {
+
+                        index--;
+                        animateScroll(index,false,true);
+                    } else {
+
+                        if(interstitialIndex>2) {
+
+                            interstitialIndex -= 1;
+                            // interstitialScroll(parseInt(heights[index])+($window.height()*interstitialIndex));
+                            interstitialScroll(Math.round(heights[index])+($window.height()*interstitialIndex));
+
+                        } else {
+
+                            interstitialIndex = 1;
+                            // interstitialScroll(parseInt(heights[index]));
+                            interstitialScroll(Math.round(heights[index]));
+                        }
+                    }
+
+                }
+            },
+            init: function() {
+                if (document.addEventListener) {
+                    document.addEventListener('touchstart', swipeScroll.touchHandler, false);
+                    document.addEventListener('touchmove', swipeScroll.touchHandler, false);
+                    document.addEventListener('touchend', swipeScroll.touchHandler, false);
+                }
+            }
+        };
+
+
+        util = {
+            refresh:function(withCallback) {
+                clearTimeout(timeoutId2);
+                timeoutId2 = setTimeout(function() {
+                    sizePanels();
+                    calculatePositions(true);
+                    if(withCallback) {
+                        settings.afterResize();
+                    }
+                },400);
+            },
+            handleUpdate:function() {
+                util.refresh(false);
+            },
+            handleResize:function() {
+                util.refresh(true);
+            }
+        };
+        settings = $.extend(settings, options);
+
+        sizePanels();
+
+        calculatePositions(false);
+
+        if(true===hasLocation) {
+            animateScroll(index,false,true);
+        } else {
+            setTimeout(function() {
+                animateScroll(0,false,true);
+            },200);
+        }
+        if(heights.length) {
+            manualScroll.init();
+            swipeScroll.init();
+
+            $window.bind("resize",util.handleResize);
+            if (document.addEventListener) {
+                window.addEventListener("orientationchange", util.handleResize, false);
+            }
+        }
+        function interstitialScroll(pos) {
+            if( $().velocity ) {
+                $(settings.target).stop().velocity('scroll', {
+                    duration: settings.scrollSpeed,
+                    easing: settings.easing,
+                    offset: pos,
+                    mobileHA: false
+                });
+            } else {
+                $(settings.target).stop().animate({
+                    scrollTop: pos
+                }, settings.scrollSpeed,settings.easing);
+            }
+        }
+
+        function sizePanels() {
+            var selector = settings.section;
+            overflow = [];
+            if(settings.interstitialSection.length) {
+                selector += "," + settings.interstitialSection;
+            }
+            $(selector).each(function(i) {
+
+                if(settings.setHeights) {
+                    if($(this).is(settings.interstitialSection)) {
+                        overflow[i] = false;
+                    } else {
+
+                        if(($(this).css("height","auto").outerHeight()<$window.height()) || $(this).css("overflow")==="hidden") {
+                            $(this).css({"height":$window.height()});
+
+                            overflow[i] = false;
+                        } else {
+
+                            $(this).css({"height":$(this).height()});
+
+                            if(settings.overflowScroll) {
+                                overflow[i] = true;
+                            } else {
+                                overflow[i] = false;
+                            }
+                        }
+
+                    }
+
+                } else {
+
+                    if(($(this).outerHeight()<$window.height()) || (settings.overflowScroll===false)) {
+                        overflow[i] = false;
+                    } else {
+                        overflow[i] = true;
+                    }
+                }
+            });
+        }
+        function calculatePositions(resize) {
+            var selector = settings.section;
+            if(settings.interstitialSection.length) {
+                selector += "," + settings.interstitialSection;
+            }
+            heights = [];
+            names = [];
+            elements = [];
+            $(selector).each(function(i){
+                if(i>0) {
+                    // heights[i] = parseInt($(this).offset().top) + settings.offset;
+                    heights[i] = Math.round($(this).offset().top) + settings.offset;
+                } else {
+                    // heights[i] = parseInt($(this).offset().top);
+                    heights[i] = Math.round($(this).offset().top);
+                }
+                if(settings.sectionName && $(this).data(settings.sectionName)) {
+                    names[i] = "#" + $(this).data(settings.sectionName).replace(/ /g,"-");
+                } else {
+                    if($(this).is(settings.interstitialSection)===false) {
+                        names[i] = "#" + (i + 1);
+                    } else {
+                        names[i] = "#";
+                        if(i===$(selector).length-1 && i>1) { // If it's the last element, we will add its height so scroll goes right to the bottom
+
+                            //---------
+                            // ## PATCHED by Stephen to take into account the CSS scaled size of the element...
+                            //heights[i] = heights[i-1]+parseInt($(this).height()); // Original code
+                            heights[i] = heights[i-1] + Math.round($(this)[0].getBoundingClientRect().height);
+                            //---------
+                        }
+                    }
+                }
+                elements[i] = $(this);
+                try {
+                    if($(names[i]).length && window.console) {
+                        console.warn("Scrollify warning: Section names can't match IDs on the page - this will cause the browser to anchor.");
+                    }
+                } catch (e) {}
+
+                if(window.location.hash===names[i]) {
+                    index = i;
+                    hasLocation = true;
+                }
+
+            });
+
+            if(true===resize) {
+                animateScroll(index,false,false);
+            } else {
+                settings.afterRender();
+            }
+        }
+
+        function atTop() {
+            if(!overflow[index]) {
+                return true;
+            }
+            top = $window.scrollTop();
+            if(top>parseInt(heights[index])) {
+                return false;
+            } else {
+                return true;
+            }
+        }
+        function atBottom() {
+            if(!overflow[index]) {
+                return true;
+            }
+            top = $window.scrollTop();
+
+            if(top<parseInt(heights[index])+(elements[index].outerHeight()-$window.height())-28) {
+
+                return false;
+
+            } else {
+                return true;
+            }
+        }
+    }
+
+    function move(panel,instant) {
+        var z = names.length;
+        for(;z>=0;z--) {
+            if(typeof panel === 'string') {
+                if (names[z]===panel) {
+                    index = z;
+                    animateScroll(z,instant,true);
+                }
+            } else {
+                if(z===panel) {
+                    index = z;
+                    animateScroll(z,instant,true);
+                }
+            }
+        }
+    }
+    $.scrollify.move = function(panel) {
+        if(panel===undefined) {
+            return false;
+        }
+        if(panel.originalEvent) {
+            panel = $(this).attr("href");
+        }
+        move(panel,false);
+    };
+    $.scrollify.instantMove = function(panel) {
+        if(panel===undefined) {
+            return false;
+        }
+        move(panel,true);
+    };
+    $.scrollify.next = function() {
+        if(index<names.length) {
+            index += 1;
+            animateScroll(index,false,true);
+        }
+    };
+    $.scrollify.previous = function() {
+        if(index>0) {
+            index -= 1;
+            animateScroll(index,false,true);
+        }
+    };
+    $.scrollify.instantNext = function() {
+        if(index<names.length) {
+            index += 1;
+            animateScroll(index,true,true);
+        }
+    };
+    $.scrollify.instantPrevious = function() {
+        if(index>0) {
+            index -= 1;
+            animateScroll(index,true,true);
+        }
+    };
+    $.scrollify.destroy = function() {
+        if(!initialised) {
+            return false;
+        }
+        if(settings.setHeights) {
+            $(settings.section).each(function() {
+                $(this).css("height","auto");
+            });
+        }
+        $window.unbind("resize",util.handleResize);
+        if(settings.scrollbars) {
+            $window.unbind('mousedown', manualScroll.handleMousedown);
+            $window.unbind('mouseup', manualScroll.handleMouseup);
+            $window.unbind('scroll', manualScroll.handleScroll);
+        }
+        $(document).unbind(wheelEvent,manualScroll.wheelHandler);
+        $(document).unbind('keydown', manualScroll.keyHandler);
+
+        if (document.addEventListener) {
+            document.removeEventListener('touchstart', swipeScroll.touchHandler, false);
+            document.removeEventListener('touchmove', swipeScroll.touchHandler, false);
+            document.removeEventListener('touchend', swipeScroll.touchHandler, false);
+        }
+        heights = [];
+        names = [];
+        elements = [];
+        overflow = [];
+    };
+    $.scrollify.update = function() {
+        if(!initialised) {
+            return false;
+        }
+        util.handleUpdate();
+    };
+    $.scrollify.current = function() {
+        return elements[index];
+    };
+    $.scrollify.disable = function() {
+        disabled = true;
+    };
+    $.scrollify.enable = function() {
+        disabled = false;
+        if (typeof manualScroll !== 'undefined') {
+            manualScroll.calculateNearest();
+        }
+    };
+    $.scrollify.isDisabled = function() {
+        return disabled;
+    };
+    $.scrollify.setOptions = function(updatedOptions) {
+        if(!initialised) {
+            return false;
+        }
+        if(typeof updatedOptions === "object") {
+            settings = $.extend(settings, updatedOptions);
+            util.handleUpdate();
+        } else if(window.console) {
+            console.warn("Scrollify warning: Options need to be in an object.");
+        }
+    };
+}));
\ No newline at end of file
index 22058541a1a1905c3557a905c9faa9f76f41017d..bb1ffbfbec21b662e1f1ad7638c397a163f13668 100644 (file)
@@ -2,55 +2,194 @@ registerLoader(load_home, true);
 function load_home() {\r
     $(window).on('fluidbookresize', resizeHome);\r
     resizeHome();\r
+    initScrollify();\r
 \r
-    // // FullPage.js setup\r
-    // $('#contentWrapper').fullpage({\r
-    //     navigation: true,\r
-    //     navigationPosition: 'left',\r
-    //     verticalCentered: false,\r
-    //     afterRender: function() {\r
-    //         console.log('FullPage rendered.');\r
-    //     },\r
-    //     afterLoad: function(anchorLink, index) {\r
-    //         console.log('Loaded section #' + index);\r
-    //         updateHeaderStyle();\r
-    //     },\r
-    //     onSlideLeave: function(anchorLink, index, slideIndex, direction, nextSlideIndex) {\r
-    //         updateHeaderStyle();\r
-    //     }\r
-    //\r
-    // });\r
+    // Bouncing scroll down arrow\r
+    // Show scroll-down arrow after a small delay\r
+    setTimeout(function() {\r
+        $('.scroll-arrow').fadeIn(1000);\r
+        // Animate arrow\r
+        TweenMax.to($('.scroll-arrow'), 1, {bottom: "+=15px", yoyo: true, repeat: -1, ease: Linear.easeNone});\r
+    }, 2500);\r
 \r
-}\r
+    $(document).on('click', '.scroll-arrow', function(e) {\r
+        $('html,body').animate({\r
+            scrollTop: $('#contentWrapper section:nth-of-type(2)').offset().top\r
+        }, 1100, 'easeOutExpo');\r
+        e.preventDefault();\r
+    });\r
+\r
+    // Handle clicks on pagination dots\r
+    $(".pagination li").on("click",function() {\r
+        $.scrollify.move($(this).data('section'));\r
+    });\r
 \r
-// function updateHeaderStyle() {\r
-//     var headerClass = $('.fp-section.active').data('headerstyle');\r
-//     console.info(headerClass);\r
-//     if (headerClass == 'light') {\r
-//         if (!$("header").hasClass('light')) {\r
-//             console.log('adding light...');\r
-//             $("header").addClass('light').removeClass('dark');\r
-//         }\r
-//     } else {\r
-//         if (!$("header").hasClass('dark')) {\r
-//             $("header").addClass('dark').removeClass('light');\r
-//         }\r
-//     }\r
-// }\r
+    // Handle clicks to AJAX popups and disable scrollify when they open\r
+    // because it interferes with internal popup scrolling\r
+    $(document).on('click', '.popup', function() {\r
+        disableScrollify();\r
+    });\r
+    $(document).on('click', '.closePopup', function() {\r
+        resizeHome(); // Update layout and re-enable scrollify if space requirements are met\r
+    });\r
+}\r
 \r
 function resizeHome() {\r
-    // Resize sections\r
-    var wh = $(window).outerHeight() / zoom;\r
-    var ww = $(window).outerWidth() / zoom;\r
 \r
-    if (ww > 900) {\r
-        $('#contentWrapper > section').css('height', wh);\r
-    } else {\r
-        $('#contentWrapper > section').css('height', 'auto');\r
-    }\r
+    var sections = $('#contentWrapper > section');\r
+\r
+    // Since we have 100% height sections and the scroller, the standard zoom handling causes\r
+    // problems so we temporarily reset it and apply it after the sections have been sized\r
+    setZoom(0);\r
+\r
+    // Recalculate zoom value but don't apply scaling yet\r
+    calculateZoom();\r
+\r
+    // Resize sections, allowing for scale factor that will be applied to parent element\r
+    var wh = Math.ceil($(window).outerHeight() / zoom);\r
+    var ww = Math.ceil($(window).outerWidth() / zoom);\r
 \r
     resizeHomeContact(ww, wh);\r
     resizeHomeReferences(ww, wh);\r
+\r
+    if (isMobile()) {\r
+        sections.css('height', 'auto');\r
+        disableScrollify();\r
+    } else if (!isTallEnough()) {\r
+        // Size each section according to its content and background image ratio\r
+        sections.each(function() {\r
+\r
+            var bgHolder = $(this).find('[data-bg-ratio]'),\r
+                bgHeight = 0,\r
+                contentHeight = $(this).find('.content-inner').outerHeight() + 100; // + extra padding height for content\r
+\r
+            if (bgHolder.length > 0) {\r
+                bgHeight = Math.round(bgHolder.outerWidth() * bgHolder.data('bg-ratio')) + 50; // + extra space for background\r
+            }\r
+\r
+            $(this).css('height', Math.max(bgHeight, contentHeight));\r
+        });\r
+\r
+        disableScrollify();\r
+\r
+    } else {\r
+        sections.css('height', wh);\r
+        enableScrollify();\r
+    }\r
+\r
+    setZoom(); // Finally set scaling again\r
+}\r
+\r
+// Check if the window height is tall enough to contain the content of each section\r
+function isTallEnough() {\r
+\r
+    // Get available height for contents\r
+    var wh = $(window).height() - $('#h').outerHeight() - $('#adminBar').outerHeight() - 30; // 30px extra breathing space around content\r
+    var ok = true;\r
+    var bgHeight = 0;\r
+    var contentHeight;\r
+    var sectionHeight;\r
+\r
+    $('section .content-wrapper').each(function() {\r
+\r
+        // First, check if the section has a background image that forces a minimum ratio for the size\r
+        if ($(this).data('bg-ratio')) {\r
+            bgHeight = $(this).data('bg-ratio') * $(this).outerWidth();\r
+        }\r
+\r
+        // Get height of actual content\r
+        contentHeight = $(this).find('.content-inner').outerHeight();\r
+\r
+        // Largest dimension of the two wins\r
+        sectionHeight = Math.max(bgHeight, contentHeight);\r
+\r
+\r
+        //console.info(sectionHeight + ' > ' + wh + '? ' + $(this).parent().attr('class'));\r
+        if (sectionHeight > wh) {\r
+            //console.error($(this).parent().attr('class') + ' is too tall...');\r
+            ok = false;\r
+            return false;\r
+        }\r
+    });\r
+\r
+    return ok;\r
+}\r
+\r
+function initScrollify() {\r
+    $.scrollify({\r
+        scrollbars: true,\r
+        interstitialSection: '.auto-height',\r
+        setHeights: false,\r
+        before: function(index, sections) {\r
+            //fb("before: #" + index, sections.length);\r
+\r
+            // Handle scrolling to last (footer) section\r
+            // This block is shorter so the header will end up over the middle of the content\r
+            // We add the background and shadow in to give it separation\r
+            if (index + 1 == sections.length) {\r
+\r
+                $('#h').css({\r
+                    'background-color': '#fff',\r
+                    'box-shadow': '0 0 120px rgba(0,0,0,0.3)'\r
+                });\r
+\r
+                $('.pagination').css('opacity', 0);\r
+\r
+            } else {\r
+\r
+                setTimeout(function() {\r
+                    $('#h').css({\r
+                        'background-color': 'transparent',\r
+                        'box-shadow': '0 0 0 rgba(0,0,0,0)'\r
+                    });\r
+\r
+                    $('.pagination').css('opacity', 1);\r
+\r
+                }, 300);\r
+\r
+            }\r
+\r
+            // Pagination update\r
+            var ref = sections[index].attr('data-section-name');\r
+            var color = sections[index].attr('data-themecolor');\r
+            $(".pagination .active").css('color', '').removeClass('active');\r
+            $(".pagination").find('[data-section="#' + ref + '"]').css('color', color).addClass('active');\r
+        },\r
+        afterRender:function() {\r
+            var pagination = '<ul class="pagination">';\r
+\r
+            $('[data-section-name]').each(function(i) {\r
+                pagination += '<li data-section="#' + $(this).attr('data-section-name') + '"><span class="hover-text">' + $(this).attr('data-section-name').charAt(0).toUpperCase() + $(this).attr('data-section-name').slice(1) + '</span></li>';\r
+            });\r
+\r
+            pagination += "</ul>";\r
+\r
+            $('body').append(pagination);\r
+\r
+            // Highlight first dot\r
+            $('.pagination li:first-of-type').css('color', $('[data-section-name]:first-of-type').data('themecolor')).addClass('active');\r
+        }\r
+    });\r
+}\r
+\r
+function enableScrollify() {\r
+    if (typeof $.scrollify !== 'undefined') {\r
+        $('body').addClass('fullpages');\r
+        fullPages = true;\r
+        setHeaderAnimation(); // Ensure header animation settings are correct after changing modes\r
+        $.scrollify.enable();\r
+        $.scrollify.update();\r
+    }\r
+}\r
+\r
+function disableScrollify() {\r
+    if (typeof $.scrollify !== 'undefined') {\r
+        $('body').removeClass('fullpages');\r
+        fullPages = false;\r
+        $.scrollify.disable();\r
+        setHeaderAnimation(); // Update header animation settings for normal scrolling\r
+        $('html,body').animate({scrollTop: $(window).scrollTop() + 1 }, 0); // Scroll down 1px to trigger header animation update\r
+    }\r
 }\r
 \r
 function resizeHomeContact(ww, wh) {\r
index a33b3ccb37c062eac385095cc2f5bd623d2f41fd..e4fdb0f39c7ae9bd01c79d605c52184b2bacafe4 100644 (file)
@@ -33,6 +33,7 @@ main {
        background-color: #fff;\r
        max-width: @content-max-width;\r
        margin: 0 auto;\r
+    position: relative;\r
 }\r
 \r
 #z {\r
index 1183084186f3e7eff3153781e1ca86d975e0f0eb..85f87e432afccb3554cff1e518ded898ee2e0744 100644 (file)
        }\r
 \r
        .content-inner {\r
-               position: absolute;\r
-               padding: 0 5%;\r
-               top: 50%;\r
-               left: 0;\r
-               width: 100%;\r
-               transform: translateY(-50%);\r
+        position: absolute;\r
+        padding: 0 5%;\r
+        top: 50%;\r
+        left: 0;\r
+        width: 100%;\r
+        transform: translateY(-50%);\r
 \r
         @media @m900 {\r
           position: static;\r
           }\r
         }\r
        }\r
+}\r
+\r
+.pagination {\r
+  color: rgba(128,128,128,0.5);\r
+  position: fixed;\r
+  top: 50%;\r
+  left: 15px;\r
+  transform: translateY(-50%);\r
+  font-size: 30px;\r
+  line-height: 1;\r
+  transition: opacity 0.3s;\r
+  cursor: pointer;\r
+  z-index: 10;\r
+  display: none; // Displayed only when in pagination mode\r
+\r
+  .fullpages & {\r
+    display: block;\r
+  }\r
+\r
+  //li:hover span {\r
+  //  display: inline-block;\r
+  //}\r
+\r
+  span {\r
+    display: none;\r
+  }\r
 }
\ No newline at end of file
index 0c5e119200b3d3631855430cd0039a0ec309f978..bddf64301bb519c5b9001c1ae110ea21f221a098 100644 (file)
@@ -2,6 +2,23 @@
 
 section.intro {
 
+  a.scroll-arrow {
+    display: none;
+    position: absolute;
+    bottom: 10px;
+    left: 50%;
+    transform: translateX(-50%);
+
+    &:after {
+      .icon('f');
+      font-size: 40px;
+      color: #fff;
+      transform: rotate(90deg);
+      display: inline-block;
+      .font-thinning-off();
+    }
+  }
+
   @media @m900 {
       .content-wrapper.fullheight {
         background-size: 100%;
diff --git a/less/212-home-features.less b/less/212-home-features.less
new file mode 100644 (file)
index 0000000..f4e35ce
--- /dev/null
@@ -0,0 +1,13 @@
+@import "000-imports";
+
+.features {
+
+  .title {
+    max-width: 50%;
+
+    @media @m900 {
+      max-width: none;
+    }
+  }
+
+}
\ No newline at end of file