<commit_before>/**
 *  GPT ad tag generator
 *  Author: Jahnavi Patel
 *  This file creates consistent
 *  ad logic to convert the
 *  generated DFP ad tags
*   to GPT ad tags.
 */

(function (window, undefined) {
    "use strict";

    var debugEnabled = '', adUnitPath = '', adSlot = '';
    var targetParamsObj = '', targetParamsStr = '', targetParams = '', targetSlot = '';
    var allSlots = [];

    /**
    * Add function to the jQuery
    */
    $.adTagInit = $.fn.adTagInit  = {

        setNetwork: function (networkCode, unitName) {
            adUnitPath = '/' + networkCode + '/' + unitName;
        },

        /**
        *   This function sets up additional debug in addition to the google console.
        *   Change the value of debug to true to turn debugging on.
        **/
        additionalDebug: function(){
            if(localStorage.getItem('debug') === null){
                localStorage.setItem('debug','false');
            }
            debugEnabled = localStorage.getItem('debug');
        },

        /**
         *  Use this function to turn on SRA or syncrendering
         *
        **/
        enableSRAandSyncRendering: function(SRA, syncRendering){
                //change the value to true to turn on SRA and syncr-endering.
                if(enableSyncRendering){
                    googletag.pubads().enableSyncRendering();
                }

                if(enableSRA){
                    googletag.pubads().enableSingleRequest();
                }

        },

        setTargettingAttributes: function(customTargettingAttributes){
            /**
            *   Convert targeting values to a array of : pair so we can
            *   feed them into setTargeting for the slot later
            */

            if(customTargettingAttributes !== undefined){
                targetParamsObj = customTargettingAttributes;
                if(typeof customTargettingAttributes === 'object'){
                    targetParamsStr = JSON.stringify(targetParamsObj);
                }
                else {
                    targetParamsStr = targetParamsObj;
                }
                targetParamsStr = targetParamsStr.replace('{','');
                targetParamsStr = targetParamsStr.replace('}','');
                targetParams = targetParamsStr.split(',');
            }

        },

        /**
        *   Create the ad slot
        **/
        createAdSlot: function(adSize, divId){
            googletag.cmd.push(function() {
                adSlot = googletag.defineSlot(adUnitPath, adSize, divId);
                adSlot.addService(googletag.pubads());
                allSlots.push(adSlot);
             });
        },

        /**
        *   Set custom targetting for all the ad slots
        **/
        setCustomTargetting: function(customTargettingAttributes){
            if(customTargettingAttributes !== undefined){
                for (var i = 0, len = targetParams.length; i < len; i++) {
                    var split = [];
                    split = targetParams[i].split(':');
                    var key = split[0];
                    var value = split[1];
                    key = key.replace('"', '');
                    value = value.replace('"', '');
                    key = key.slice(0, key.length - 1);
                    value = value.slice(0, value.length - 1);

                    adSlot.setTargeting(key, value);

                    if (debugEnabled == 'true') {
                        console.log('Supplying custom Targetting Attributes values to adSlot - ' + key + ',' + value);
                    }
                }
            }
        },

        pushAdSlotDiv: function(divId){
            googletag.cmd.push(function() {

                googletag.enableServices();
                googletag.display(divId);

                targetSlot = adSlot;

                //additional debugging to see if creative rendered callback
                if (debugEnabled == 'true') {
                    googletag.pubads().addEventListener('slotRenderEnded', function(event) {
                        if(event.slot == targetSlot){
                            console.log('################  GOOGLETAG: Creative rendered callback STARTS################');
                            console.log('divId: ' + divId + ' Creative with id: ' + event.creativeId +
                                ' is rendered to slot of size: ' + event.size[0] + 'x' + event.size[1]);
                            console.log('################  GOOGLETAG: Creative rendered callback ENDS################');
                        }
                    });
                }
            });
        },

        makeIframeVisible: function(divId){
            //special code around iframe to make it visible
            googletag.pubads().addEventListener('slotRenderEnded', function(event) {
                if(divId === 'YOUR_DIV' && event.isEmpty === false){
                    window.onload = function () {
                         var iframe = $('YOUR_DIV').find('iframe');
                        iframe.height(YOUR_HEIGHT);
                        iframe.width(YOUR_WIDTH);
                    };
                }
            });
        },

        /**
        *   Refresh all the slots
        **/
        refreshAllSlots: function(){
            console.log("Ad Slots are REFRESHED.....");
            googletag.cmd.push(function() {
                $.each( allSlots, function( index, value ){
                    googletag.pubads().refresh([allSlots][index]);
                });
            });

        },

        /**
        *   Clear out all the slots
        **/
        clearAllSlots: function() {
            console.log('Ad Slots are CLEARED.....');
            googletag.cmd.push(function() {
                googletag.pubads().clear();
            });
         },

        defineAdSlot: function (networkCode, unitName, adSize, divId, customTargettingAttributes) {
            this.setNetwork(networkCode, unitName);
            this.additionalDebug();
            this.setTargettingAttributes(customTargettingAttributes);
            if (debugEnabled == 'true') {
                console.log('----------------------------------------------------------------------');
                console.log('Setting SLOT with options -- networkCode: ' + networkCode +
                    ' -- adSize:' + adSize + ' -- divId:' + divId);
                console.log('----------------------------------------------------------------------');
            }
            this.createAdSlot(adSize, divId);
            this.setCustomTargetting(customTargettingAttributes);
            this.pushAdSlotDiv(divId);

            //uncomment the below function only if iframe is invisible due to some unforseen reason
            //this.makeIframeVisible(divId)
        }
    };
})(window);

<commit_msg>Update javascript-dfp.js<commit_after>/**
 *  GPT ad tag generator
 *  Author: Jahnavi Patel
 *  This file creates consistent
 *  ad logic to convert the
 *  generated DFP ad tags
*   to GPT ad tags.
 */

(function (window, undefined) {
    "use strict";

    var debugEnabled = '', adUnitPath = '', adSlot = '';
    var targetParamsObj = '', targetParamsStr = '', targetParams = '', targetSlot = '';
    var allSlots = [];

    /**
    * Add function to the jQuery
    */
    $.adTagInit = $.fn.adTagInit  = {

        setNetwork: function (networkCode, unitName) {
            adUnitPath = '/' + networkCode + '/' + unitName;
        },

        /**
        *   This function sets up additional debug in addition to the google console.
        *   Change the value of debug to true to turn debugging on.
        **/
        additionalDebug: function(){
            if(localStorage.getItem('debug') === null){
                localStorage.setItem('debug','false');
            }
            debugEnabled = localStorage.getItem('debug');
        },

        /**
         *  Use this function to turn on SRA or syncrendering
         *
        **/
        enableSRAandSyncRendering: function(SRA, syncRendering){
                //change the value to true to turn on SRA and syncr-endering.
                if(enableSyncRendering){
                    googletag.pubads().enableSyncRendering();
                }

                if(enableSRA){
                    googletag.pubads().enableSingleRequest();
                }

        },

        /**
        *   Convert targeting values to a array of : pair so we can
        *   feed them into setTargeting for the slot later
        */
        setTargettingAttributes: function(customTargettingAttributes){
            if(customTargettingAttributes !== undefined){
                targetParamsObj = customTargettingAttributes;
                if(typeof customTargettingAttributes === 'object'){
                    targetParamsStr = JSON.stringify(targetParamsObj);
                }
                else {
                    targetParamsStr = targetParamsObj;
                }
                targetParamsStr = targetParamsStr.replace('{','');
                targetParamsStr = targetParamsStr.replace('}','');
                targetParams = targetParamsStr.split(',');
            }

        },

        /**
        *   Create the ad slot
        **/
        createAdSlot: function(adSize, divId){
            googletag.cmd.push(function() {
                adSlot = googletag.defineSlot(adUnitPath, adSize, divId);
                adSlot.addService(googletag.pubads());
                allSlots.push(adSlot);
             });
        },

        /**
        *   Set custom targetting for all the ad slots
        **/
        setCustomTargetting: function(customTargettingAttributes){
            if(customTargettingAttributes !== undefined){
                for (var i = 0, len = targetParams.length; i < len; i++) {
                    var split = [];
                    split = targetParams[i].split(':');
                    var key = split[0];
                    var value = split[1];
                    key = key.replace('"', '');
                    value = value.replace('"', '');
                    key = key.slice(0, key.length - 1);
                    value = value.slice(0, value.length - 1);

                    adSlot.setTargeting(key, value);

                    if (debugEnabled == 'true') {
                        console.log('Supplying custom Targetting Attributes values to adSlot - ' + key + ',' + value);
                    }
                }
            }
        },

        pushAdSlotDiv: function(divId){
            googletag.cmd.push(function() {

                googletag.enableServices();
                googletag.display(divId);

                targetSlot = adSlot;

                //additional debugging to see if creative rendered callback
                if (debugEnabled == 'true') {
                    googletag.pubads().addEventListener('slotRenderEnded', function(event) {
                        if(event.slot == targetSlot){
                            console.log('################  GOOGLETAG: Creative rendered callback STARTS################');
                            console.log('divId: ' + divId + ' Creative with id: ' + event.creativeId +
                                ' is rendered to slot of size: ' + event.size[0] + 'x' + event.size[1]);
                            console.log('################  GOOGLETAG: Creative rendered callback ENDS################');
                        }
                    });
                }
            });
        },

        /**
        *   Tamper with the iframe and make it visible
        **/
        makeIframeVisible: function(divId){
            //special code around iframe to make it visible
            googletag.pubads().addEventListener('slotRenderEnded', function(event) {
                if(divId === 'YOUR_DIV' && event.isEmpty === false){
                    window.onload = function () {
                         var iframe = $('YOUR_DIV').find('iframe');
                        iframe.height(YOUR_HEIGHT);
                        iframe.width(YOUR_WIDTH);
                    };
                }
            });
        },

        /**
        *   Refresh all the slots
        **/
        refreshAllSlots: function(){
            console.log("Ad Slots are REFRESHED.....");
            googletag.cmd.push(function() {
                $.each( allSlots, function( index, value ){
                    googletag.pubads().refresh([allSlots][index]);
                });
            });

        },

        /**
        *   Clear out all the slots
        **/
        clearAllSlots: function() {
            console.log('Ad Slots are CLEARED.....');
            googletag.cmd.push(function() {
                googletag.pubads().clear();
            });
         },

        /**
        *   Define out all the slots
        **/
        defineAdSlot: function (networkCode, unitName, adSize, divId, customTargettingAttributes) {
            this.setNetwork(networkCode, unitName);
            this.additionalDebug();
            this.setTargettingAttributes(customTargettingAttributes);
            if (debugEnabled == 'true') {
                console.log('----------------------------------------------------------------------');
                console.log('Setting SLOT with options -- networkCode: ' + networkCode +
                    ' -- adSize:' + adSize + ' -- divId:' + divId);
                console.log('----------------------------------------------------------------------');
            }
            this.createAdSlot(adSize, divId);
            this.setCustomTargetting(customTargettingAttributes);
            this.pushAdSlotDiv(divId);

            //uncomment the below function only if iframe is invisible due to some unforseen reason
            //this.makeIframeVisible(divId)
        }
    };
})(window);

<|endoftext|>


<commit_before>/*===============================================================================
************   Fast Clicks   ************
************   Inspired by https://github.com/ftlabs/fastclick   ************
===============================================================================*/
app.initFastClicks = function () {
    if (app.params.activeState) {
        $('html').addClass('watch-active-state');
    }

    var touchStartX, touchStartY, touchStartTime, targetElement, trackClick, activeSelection, scrollParent, lastClickTime, isMoved;
    var activableElement, activeTimeout, needsFastClick;

    function findActivableElement(e) {
        var target = $(e.target);
        var parents = target.parents(app.params.activeStateElements);

        return (parents.length > 0) ? parents : target;
    }
    function isInsideScrollableView() {
        var pageContent = activableElement.parents('.page-content, .panel');

        if (pageContent.length === 0) {
            return false;
        }

        // This event handler covers the "tap to stop scrolling".
        if (pageContent.prop('scrollHandlerSet') !== 'yes') {
            pageContent.on('scroll', function() {
              clearTimeout(activeTimeout);
            });
            pageContent.prop('scrollHandlerSet', 'yes');
        }

        return true;
    }
    function addActive() {
        activableElement.addClass('active-state');
    }
    function removeActive(el) {
        activableElement.removeClass('active-state');
    }

    function androidNeedsBlur(el) {
        var noBlur = ('button checkbox file image radio submit input textarea').split(' ');
        if (document.activeElement && el !== document.activeElement && document.activeElement !== document.body) {
            if (noBlur.indexOf(el.nodeName.toLowerCase()) >= 0) {
                return false;
            }
            else {
                return true;
            }
        }
        else {
            return false;
        }
    }
    function targetNeedsFastClick(el) {
        var $el = $(el);
        if (el.nodeName.toLowerCase() === 'input' && el.type === 'file') return false;
        if ($el.hasClass('no-fastclick') || $el.parents('.no-fastclick').length > 0) return false;
        return true;
    }
    function targetNeedsFocus(el) {
        if (document.activeElement === el) {
            return false;
        }
        var tag = el.nodeName.toLowerCase();
        var skipInputs = ('button checkbox file image radio submit').split(' ');
        if (el.disabled || el.readOnly) return false;
        if (tag === 'textarea') return true;
        if (tag === 'select') {
            if (app.device.os === 'android') return false;
            else return true;
        }
        if (tag === 'input' && skipInputs.indexOf(el.type) < 0) return true;
    }
    function targetNeedsPrevent(el) {
        el = $(el);
        if (el.is('label') || el.parents('label').length > 0) {
            if (app.device.os === 'android') {
                var osv = app.device.osVersion.split('.');
                if (osv[0] * 1 > 4 || (osv[0] * 1 === 4 && osv[1] * 1 >= 4)) {
                    return false;
                }
                else return true;
            }
            else return false;
        }
        return true;
    }

    // Mouse Handlers
    function handleMouseDown (e) {
        findActivableElement(e).addClass('active-state');
        if ('which' in e && e.which === 3) {
            setTimeout(function () {
                $('.active-state').removeClass('active-state');
            }, 0);
        }
    }
    function handleMouseMove (e) {
        $('.active-state').removeClass('active-state');
    }
    function handleMouseUp (e) {
        $('.active-state').removeClass('active-state');
    }

    // Touch Handlers
    function handleTouchStart(e) {
        isMoved = false;
        if (e.targetTouches.length > 1) {
            return true;
        }
        needsFastClick = targetNeedsFastClick(e.target);

        if (!needsFastClick) {
            trackClick = false;
            return true;
        }
        if (app.device.os === 'ios') {
            var selection = window.getSelection();
            if (selection.rangeCount && selection.focusNode !== document.body && (!selection.isCollapsed || document.activeElement === selection.focusNode)) {
                activeSelection = true;
                return true;
            }
            else {
                activeSelection = false;
            }
        }
        if (app.device.os === 'android')  {
            if (androidNeedsBlur(e.target)) {
                document.activeElement.blur();
            }
        }

        trackClick = true;
        targetElement = e.target;
        touchStartTime = (new Date()).getTime();
        touchStartX = e.targetTouches[0].pageX;
        touchStartY = e.targetTouches[0].pageY;

        // Detect scroll parent
        if (app.device.os === 'ios') {
            scrollParent = undefined;
            $(targetElement).parents().each(function () {
                var parent = this;
                if (parent.scrollHeight > parent.offsetHeight && !scrollParent) {
                    scrollParent = parent;
                    scrollParent.f7ScrollTop = scrollParent.scrollTop;
                }
            });
        }
        if ((e.timeStamp - lastClickTime) < 200) {
            e.preventDefault();
        }
        if (app.params.activeState) {
            activableElement = findActivableElement(e);
            // If it's inside a scrollable view, we don't trigger active-state yet,
            // because it can be a scroll instead. Based on the link:
            // http://labnote.beedesk.com/click-scroll-and-pseudo-active-on-mobile-webk
            if (!isInsideScrollableView(e)) {
                addActive();
            } else {
                activeTimeout = setTimeout(addActive, 80);
            }
        }
    }
    function handleTouchMove(e) {
        if (!trackClick) return;
        var _isMoved = false;
        var distance = app.params.fastClicksDistanceThreshold;
        if (distance) {
            var pageX = e.targetTouches[0].pageX;
            var pageY = e.targetTouches[0].pageY;
            if (Math.abs(pageX - touchStartX) > distance ||  Math.abs(pageY - touchStartY) > distance) {
                _isMoved = true;
            }
        }
        else {
            _isMoved = true;
        }
        if (_isMoved) {
            trackClick = false;
            targetElement = null;
            isMoved = true;
        }

        if (app.params.activeState) {
            clearTimeout(activeTimeout);
            removeActive();
        }
    }
    function handleTouchEnd(e) {
        clearTimeout(activeTimeout);

        if (!trackClick) {
            if (!activeSelection && needsFastClick) e.preventDefault();
            return true;
        }

        if (document.activeElement === e.target) {
            return true;
        }

        if (!activeSelection) {
            e.preventDefault();
        }

        if ((e.timeStamp - lastClickTime) < 200) {
            return true;
        }

        lastClickTime = e.timeStamp;

        trackClick = false;

        if (app.device.os === 'ios' && scrollParent) {
            if (scrollParent.scrollTop !== scrollParent.f7ScrollTop) {
                return false;
            }
        }

        // Add active-state here because, in a very fast tap, the timeout didn't
        // have the chance to execute. Removing active-state in a timeout gives
        // the chance to the animation execute.
        if (app.params.activeState) {
            addActive();
            setTimeout(removeActive, 0);
        }

        // Trigger focus when required
        if (targetNeedsFocus(targetElement)) {
            targetElement.focus();
        }

        // Blur active elements
        if (document.activeElement && targetElement !== document.activeElement && document.activeElement !== document.body && targetElement.nodeName.toLowerCase() !== 'label') {
            document.activeElement.blur();
        }

        // Send click
        e.preventDefault();
        var touch = e.changedTouches[0];
        var evt = document.createEvent('MouseEvents');
        var eventType = 'click';
        if (app.device.os === 'android' && targetElement.nodeName.toLowerCase() === 'select') {
            eventType = 'mousedown';
        }
        evt.initMouseEvent(eventType, true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
        evt.forwardedTouchEvent = true;
        targetElement.dispatchEvent(evt);

        return false;
    }
    function handleTouchCancel(e) {
        trackClick = false;
        targetElement = null;
    }

    function handleClick(e) {
        var allowClick = false;

        if (trackClick) {
            targetElement = null;
            trackClick = false;
            return true;
        }

        if (e.target.type === 'submit' && e.detail === 0) {
            return true;
        }

        if (!targetElement) {
            allowClick =  true;
        }
        if (document.activeElement === targetElement) {
            allowClick =  true;
        }
        if (e.forwardedTouchEvent) {
            allowClick =  true;
        }
        if (!e.cancelable) {
            allowClick =  true;
        }

        if (!allowClick) {
            e.stopImmediatePropagation();
            e.stopPropagation();
            if (targetElement) {
                if (targetNeedsPrevent(targetElement) || isMoved) {
                    e.preventDefault();
                }
            }
            else {
                e.preventDefault();
            }
            targetElement = null;
        }

        return allowClick;
    }
    if (app.support.touch) {
        document.addEventListener('click', handleClick, true);

        document.addEventListener('touchstart', handleTouchStart);
        document.addEventListener('touchmove', handleTouchMove);
        document.addEventListener('touchend', handleTouchEnd);
        document.addEventListener('touchcancel', handleTouchCancel);
    }
    else {
        if (app.params.activeState) {
            document.addEventListener('mousedown', handleMouseDown);
            document.addEventListener('mousemove', handleMouseMove);
            document.addEventListener('mouseup', handleMouseUp);
        }
    }

};
<commit_msg>Remove active state in short taps<commit_after>/*===============================================================================
************   Fast Clicks   ************
************   Inspired by https://github.com/ftlabs/fastclick   ************
===============================================================================*/
app.initFastClicks = function () {
    if (app.params.activeState) {
        $('html').addClass('watch-active-state');
    }

    var touchStartX, touchStartY, touchStartTime, targetElement, trackClick, activeSelection, scrollParent, lastClickTime, isMoved;
    var activableElement, activeTimeout, needsFastClick;

    function findActivableElement(e) {
        var target = $(e.target);
        var parents = target.parents(app.params.activeStateElements);

        return (parents.length > 0) ? parents : target;
    }
    function isInsideScrollableView() {
        var pageContent = activableElement.parents('.page-content, .panel');

        if (pageContent.length === 0) {
            return false;
        }

        // This event handler covers the "tap to stop scrolling".
        if (pageContent.prop('scrollHandlerSet') !== 'yes') {
            pageContent.on('scroll', function() {
              clearTimeout(activeTimeout);
            });
            pageContent.prop('scrollHandlerSet', 'yes');
        }

        return true;
    }
    function addActive() {
        activableElement.addClass('active-state');
    }
    function removeActive(el) {
        activableElement.removeClass('active-state');
    }

    function androidNeedsBlur(el) {
        var noBlur = ('button checkbox file image radio submit input textarea').split(' ');
        if (document.activeElement && el !== document.activeElement && document.activeElement !== document.body) {
            if (noBlur.indexOf(el.nodeName.toLowerCase()) >= 0) {
                return false;
            }
            else {
                return true;
            }
        }
        else {
            return false;
        }
    }
    function targetNeedsFastClick(el) {
        var $el = $(el);
        if (el.nodeName.toLowerCase() === 'input' && el.type === 'file') return false;
        if ($el.hasClass('no-fastclick') || $el.parents('.no-fastclick').length > 0) return false;
        return true;
    }
    function targetNeedsFocus(el) {
        if (document.activeElement === el) {
            return false;
        }
        var tag = el.nodeName.toLowerCase();
        var skipInputs = ('button checkbox file image radio submit').split(' ');
        if (el.disabled || el.readOnly) return false;
        if (tag === 'textarea') return true;
        if (tag === 'select') {
            if (app.device.os === 'android') return false;
            else return true;
        }
        if (tag === 'input' && skipInputs.indexOf(el.type) < 0) return true;
    }
    function targetNeedsPrevent(el) {
        el = $(el);
        if (el.is('label') || el.parents('label').length > 0) {
            if (app.device.os === 'android') {
                var osv = app.device.osVersion.split('.');
                if (osv[0] * 1 > 4 || (osv[0] * 1 === 4 && osv[1] * 1 >= 4)) {
                    return false;
                }
                else return true;
            }
            else return false;
        }
        return true;
    }

    // Mouse Handlers
    function handleMouseDown (e) {
        findActivableElement(e).addClass('active-state');
        if ('which' in e && e.which === 3) {
            setTimeout(function () {
                $('.active-state').removeClass('active-state');
            }, 0);
        }
    }
    function handleMouseMove (e) {
        $('.active-state').removeClass('active-state');
    }
    function handleMouseUp (e) {
        $('.active-state').removeClass('active-state');
    }

    // Touch Handlers
    function handleTouchStart(e) {
        isMoved = false;
        if (e.targetTouches.length > 1) {
            return true;
        }
        needsFastClick = targetNeedsFastClick(e.target);

        if (!needsFastClick) {
            trackClick = false;
            return true;
        }
        if (app.device.os === 'ios') {
            var selection = window.getSelection();
            if (selection.rangeCount && selection.focusNode !== document.body && (!selection.isCollapsed || document.activeElement === selection.focusNode)) {
                activeSelection = true;
                return true;
            }
            else {
                activeSelection = false;
            }
        }
        if (app.device.os === 'android')  {
            if (androidNeedsBlur(e.target)) {
                document.activeElement.blur();
            }
        }

        trackClick = true;
        targetElement = e.target;
        touchStartTime = (new Date()).getTime();
        touchStartX = e.targetTouches[0].pageX;
        touchStartY = e.targetTouches[0].pageY;

        // Detect scroll parent
        if (app.device.os === 'ios') {
            scrollParent = undefined;
            $(targetElement).parents().each(function () {
                var parent = this;
                if (parent.scrollHeight > parent.offsetHeight && !scrollParent) {
                    scrollParent = parent;
                    scrollParent.f7ScrollTop = scrollParent.scrollTop;
                }
            });
        }
        if ((e.timeStamp - lastClickTime) < 200) {
            e.preventDefault();
        }
        if (app.params.activeState) {
            activableElement = findActivableElement(e);
            // If it's inside a scrollable view, we don't trigger active-state yet,
            // because it can be a scroll instead. Based on the link:
            // http://labnote.beedesk.com/click-scroll-and-pseudo-active-on-mobile-webk
            if (!isInsideScrollableView(e)) {
                addActive();
            } else {
                activeTimeout = setTimeout(addActive, 80);
            }
        }
    }
    function handleTouchMove(e) {
        if (!trackClick) return;
        var _isMoved = false;
        var distance = app.params.fastClicksDistanceThreshold;
        if (distance) {
            var pageX = e.targetTouches[0].pageX;
            var pageY = e.targetTouches[0].pageY;
            if (Math.abs(pageX - touchStartX) > distance ||  Math.abs(pageY - touchStartY) > distance) {
                _isMoved = true;
            }
        }
        else {
            _isMoved = true;
        }
        if (_isMoved) {
            trackClick = false;
            targetElement = null;
            isMoved = true;
        }

        if (app.params.activeState) {
            clearTimeout(activeTimeout);
            removeActive();
        }
    }
    function handleTouchEnd(e) {
        clearTimeout(activeTimeout);

        if (!trackClick) {
            if (!activeSelection && needsFastClick) e.preventDefault();
            return true;
        }

        if (document.activeElement === e.target) {
            return true;
        }

        if (!activeSelection) {
            e.preventDefault();
        }

        if ((e.timeStamp - lastClickTime) < 200) {
            setTimeout(removeActive, 0);
            return true;
        }

        lastClickTime = e.timeStamp;

        trackClick = false;

        if (app.device.os === 'ios' && scrollParent) {
            if (scrollParent.scrollTop !== scrollParent.f7ScrollTop) {
                return false;
            }
        }

        // Add active-state here because, in a very fast tap, the timeout didn't
        // have the chance to execute. Removing active-state in a timeout gives
        // the chance to the animation execute.
        if (app.params.activeState) {
            addActive();
            setTimeout(removeActive, 0);
        }

        // Trigger focus when required
        if (targetNeedsFocus(targetElement)) {
            targetElement.focus();
        }

        // Blur active elements
        if (document.activeElement && targetElement !== document.activeElement && document.activeElement !== document.body && targetElement.nodeName.toLowerCase() !== 'label') {
            document.activeElement.blur();
        }

        // Send click
        e.preventDefault();
        var touch = e.changedTouches[0];
        var evt = document.createEvent('MouseEvents');
        var eventType = 'click';
        if (app.device.os === 'android' && targetElement.nodeName.toLowerCase() === 'select') {
            eventType = 'mousedown';
        }
        evt.initMouseEvent(eventType, true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
        evt.forwardedTouchEvent = true;
        targetElement.dispatchEvent(evt);

        return false;
    }
    function handleTouchCancel(e) {
        trackClick = false;
        targetElement = null;
    }

    function handleClick(e) {
        var allowClick = false;

        if (trackClick) {
            targetElement = null;
            trackClick = false;
            return true;
        }

        if (e.target.type === 'submit' && e.detail === 0) {
            return true;
        }

        if (!targetElement) {
            allowClick =  true;
        }
        if (document.activeElement === targetElement) {
            allowClick =  true;
        }
        if (e.forwardedTouchEvent) {
            allowClick =  true;
        }
        if (!e.cancelable) {
            allowClick =  true;
        }

        if (!allowClick) {
            e.stopImmediatePropagation();
            e.stopPropagation();
            if (targetElement) {
                if (targetNeedsPrevent(targetElement) || isMoved) {
                    e.preventDefault();
                }
            }
            else {
                e.preventDefault();
            }
            targetElement = null;
        }

        return allowClick;
    }
    if (app.support.touch) {
        document.addEventListener('click', handleClick, true);

        document.addEventListener('touchstart', handleTouchStart);
        document.addEventListener('touchmove', handleTouchMove);
        document.addEventListener('touchend', handleTouchEnd);
        document.addEventListener('touchcancel', handleTouchCancel);
    }
    else {
        if (app.params.activeState) {
            document.addEventListener('mousedown', handleMouseDown);
            document.addEventListener('mousemove', handleMouseMove);
            document.addEventListener('mouseup', handleMouseUp);
        }
    }

};
<|endoftext|>


<commit_before>import isEventSupported from './isEventSupported';
import capturableEvents from './capturableEvents';
import nonBubbleableEvents from './nonBubbleableEvents';
import focusEvents from './focusEvents';
import ExecutionEnvironment from '../util/ExecutionEnvironment';
import addRootDomEventListeners from './addRootDomEventListeners';
import listenerSetup from './hooks/listenerSetup';

let EventRegistry = {};

if (ExecutionEnvironment.canUseDOM) {

    let i = 0,
        type;

    for (; i < capturableEvents.length; i++) {

        type = capturableEvents[i];

        EventRegistry[type] = {
            type: type,
            bubbles: true,
            listenersCounter: 0,
            set: false
        };

        if (focusEvents[type]) {

            // IE has `focusin` and `focusout` events which bubble.
            // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
            if (isEventSupported(focusEvents[type])) {

                EventRegistry[type].setup = function() {
                    let handler = listenerSetup(this.type, e => {
                        addRootDomEventListeners(e, this.type);
                    });
                    document.addEventListener(focusEvents[this.type], handler);
                };
            }
        }
    }

    // For non-bubbleable events - e.g. scroll - we are setting the events directly on the node
    for (i = 0; i < nonBubbleableEvents.length; i++) {
        EventRegistry[nonBubbleableEvents[i]] = {
            type: type,
            bubbles: false,
            set: false
        };
    }
}

export default EventRegistry;<commit_msg>Fix focus/blur event handling<commit_after>import isEventSupported from './isEventSupported';
import capturableEvents from './capturableEvents';
import nonBubbleableEvents from './nonBubbleableEvents';
import focusEvents from './focusEvents';
import ExecutionEnvironment from '../util/ExecutionEnvironment';
import addRootDomEventListeners from './addRootDomEventListeners';
import listenerSetup from './hooks/listenerSetup';

let EventRegistry = {};

if (ExecutionEnvironment.canUseDOM) {

    let i = 0,
        type;

    for (; i < capturableEvents.length; i++) {

        type = capturableEvents[i];

        EventRegistry[type] = {
            type: type,
            bubbles: true,
            listenersCounter: 0,
            set: false
        };

        if (focusEvents[type]) {

            // IE has `focusin` and `focusout` events which bubble.
            // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
            if (isEventSupported(focusEvents[type])) {

                EventRegistry[type].setup = function() {
                    let handler = listenerSetup(this.type, e => {
                        addRootDomEventListeners(e, this.type);
                    });
                    document.addEventListener(focusEvents[this.type], handler);
                };
            } else {
                EventRegistry[type].setup = function() {
                    document.addEventListener(
                        this.type,
                        listenerSetup(this.type, addRootDomEventListeners),
                        true);
                };
            }
        }
    }

    // For non-bubbleable events - e.g. scroll - we are setting the events directly on the node
    for (i = 0; i < nonBubbleableEvents.length; i++) {
        EventRegistry[nonBubbleableEvents[i]] = {
            type: type,
            bubbles: false,
            set: false
        };
    }
}

export default EventRegistry;<|endoftext|>


<commit_before>'use strict';

/**
 * Trip Search DB Query Functions
 * @module search/query
 * @private
 */

const Agency = require('../gtfs/Agency.js');
const Route = require('../gtfs/Route.js');
const StopTime = require('../gtfs/StopTime.js');
const TripsTable = require('../query/TripsTable.js');

/**
 * Get a list of Trips that operate during the specified TripSearchDates and
 * run from the specified Stop to at least one of the provided following Stops
 * @param {RightTrackDB} db The Right Track DB to query
 * @param {Stop} stop The reference Stop
 * @param {TripSearchDate[]} tripSearchDates List of Trip Search Dates
 * @param {String[]} nextStops List of following Stops (Stop IDs)
 * @param {function} callback Callback function
 * @param {Error} callback.err Database Query Error
 * @param {Trip[]} [callback.trips] List of matching Trips
 * @private
 */
function getTripsFromStop(db, stop, tripSearchDates, nextStops, callback) {

  // List of Trips to Return
  let rtn = [];

  // Counters
  let done = 0;
  let count = tripSearchDates.length;

  // Parse each TripSearchDate separately
  for ( let i = 0; i < tripSearchDates.length; i++ ) {
    _getTripsFromStop(db, stop, tripSearchDates[i], function(err, trips) {

      // Database Query Error
      if ( err ) {
        return callback(err);
      }

      // Check each of the Trips to add
      for ( let j = 0; j < trips.length; j++ ) {
        _addTrip(trips[j]);
      }

      // Finish the TSD
      _finish();

    });
  }

  /**
   * Add the specified Trip to the return list, if it is not
   * already present and it continues to one of the next stops
   * @param {Trip} trip Trip to add
   * @private
   */
  function _addTrip(trip) {

    // Make sure trip isn't already in list
    let found = false;
    for ( let i = 0; i < rtn.length; i++ ) {
      if ( rtn[i].id === trip.id ) {
        found = true;
      }
    }

    // Process new trip
    if ( !found ) {

      // Make sure the trip stops at any of the next stops, after the current stop
      let stopFound = false;
      let add = false;
      for ( let i = 0; i < trip.stopTimes.length; i++ ) {
        let stopId = trip.stopTimes[i].stop.id;
        if ( !stopFound && stopId === stop.id ) {
          stopFound = true;
        }
        else if ( stopFound ) {
          if ( nextStops.indexOf(stopId) > -1 ) {
            add = true;
            i = trip.stopTimes.length;
          }
        }
      }

      // Add Trip
      if ( add ) {
        rtn.push(trip);
      }

    }

  }

  /**
   * Finish processing the Trip Search Dates
   * @private
   */
  function _finish() {
    done++;
    if ( done === count ) {
      return callback(null, rtn);
    }
  }

}

/**
 * Get the Trips within the TripSearchDate range from the specified Stop
 * @param {RightTrackDB} db The Right Track DB to query
 * @param {Stop} stop The reference Stop
 * @param {TripSearchDate} tripSearchDate The Trip Search Date
 * @param {function} callback Callback function(err, trips)
 * @private
 */
function _getTripsFromStop(db, stop, tripSearchDate, callback) {

  // List of trips to return
  let rtn = [];

  // Set counters
  let done = 0;
  let count = 0;

  // Build Service ID String
  let serviceIdString = "'" + tripSearchDate.serviceIds.join("', '") + "'";

  // Get Trip IDs
  let select = "SELECT gtfs_stop_times.trip_id " +
    "FROM gtfs_stop_times " +
    "INNER JOIN gtfs_trips ON gtfs_stop_times.trip_id=gtfs_trips.trip_id " +
    "WHERE stop_id='" + stop.id + "' AND " +
    "departure_time_seconds >= " + tripSearchDate.preSeconds + " AND departure_time_seconds <= " + tripSearchDate.postSeconds + " AND " +
    "pickup_type <> " + StopTime.PICKUP_TYPE_NONE + " AND " +
    "gtfs_trips.service_id IN (" + serviceIdString + ")";

  // Select the Trip IDs
  db.select(select, function(err, results) {

    // Database Query Error
    if ( err ) {
      return callback(
        new Error('Could not get Trip(s) from database')
      );
    }

    // No Results
    if ( results.length === 0 ) {
      return callback(null, rtn);
    }

    // Set the counter
    count = results.length;

    // Build the Trips
    for ( let i = 0; i < results.length; i++ ) {
      TripsTable.getTrip(db, results[i].trip_id, tripSearchDate.date, function(err, trip) {

        // Database Query Error
        if ( err ) {
          return callback(err);
        }

        // Add trip to list
        rtn.push(trip);

        // Finish Process the Trip
        _finish();

      });
    }

  });

  /**
   * Finished Processing Trip
   * @private
   */
  function _finish() {
    done++;
    if ( done === count ) {
      return callback(null, rtn);
    }
  }

}

module.exports = {
  getTripsFromStop: getTripsFromStop
};<commit_msg>Bug: Do not add undefined trips to trip results<commit_after>'use strict';

/**
 * Trip Search DB Query Functions
 * @module search/query
 * @private
 */

const Agency = require('../gtfs/Agency.js');
const Route = require('../gtfs/Route.js');
const StopTime = require('../gtfs/StopTime.js');
const TripsTable = require('../query/TripsTable.js');

/**
 * Get a list of Trips that operate during the specified TripSearchDates and
 * run from the specified Stop to at least one of the provided following Stops
 * @param {RightTrackDB} db The Right Track DB to query
 * @param {Stop} stop The reference Stop
 * @param {TripSearchDate[]} tripSearchDates List of Trip Search Dates
 * @param {String[]} nextStops List of following Stops (Stop IDs)
 * @param {function} callback Callback function
 * @param {Error} callback.err Database Query Error
 * @param {Trip[]} [callback.trips] List of matching Trips
 * @private
 */
function getTripsFromStop(db, stop, tripSearchDates, nextStops, callback) {

  // List of Trips to Return
  let rtn = [];

  // Counters
  let done = 0;
  let count = tripSearchDates.length;

  // Parse each TripSearchDate separately
  for ( let i = 0; i < tripSearchDates.length; i++ ) {
    _getTripsFromStop(db, stop, tripSearchDates[i], function(err, trips) {

      // Database Query Error
      if ( err ) {
        return callback(err);
      }

      // Check each of the Trips to add
      for ( let j = 0; j < trips.length; j++ ) {
        _addTrip(trips[j]);
      }

      // Finish the TSD
      _finish();

    });
  }

  /**
   * Add the specified Trip to the return list, if it is not
   * already present and it continues to one of the next stops
   * @param {Trip} trip Trip to add
   * @private
   */
  function _addTrip(trip) {

    // Make sure trip isn't already in list
    let found = false;
    for ( let i = 0; i < rtn.length; i++ ) {
      if ( rtn[i].id === trip.id ) {
        found = true;
      }
    }

    // Process new trip
    if ( !found ) {

      // Make sure the trip stops at any of the next stops, after the current stop
      let stopFound = false;
      let add = false;
      for ( let i = 0; i < trip.stopTimes.length; i++ ) {
        let stopId = trip.stopTimes[i].stop.id;
        if ( !stopFound && stopId === stop.id ) {
          stopFound = true;
        }
        else if ( stopFound ) {
          if ( nextStops.indexOf(stopId) > -1 ) {
            add = true;
            i = trip.stopTimes.length;
          }
        }
      }

      // Add Trip
      if ( add ) {
        rtn.push(trip);
      }

    }

  }

  /**
   * Finish processing the Trip Search Dates
   * @private
   */
  function _finish() {
    done++;
    if ( done === count ) {
      return callback(null, rtn);
    }
  }

}

/**
 * Get the Trips within the TripSearchDate range from the specified Stop
 * @param {RightTrackDB} db The Right Track DB to query
 * @param {Stop} stop The reference Stop
 * @param {TripSearchDate} tripSearchDate The Trip Search Date
 * @param {function} callback Callback function(err, trips)
 * @private
 */
function _getTripsFromStop(db, stop, tripSearchDate, callback) {

  // List of trips to return
  let rtn = [];

  // Set counters
  let done = 0;
  let count = 0;

  // Build Service ID String
  let serviceIdString = "'" + tripSearchDate.serviceIds.join("', '") + "'";

  // Get Trip IDs
  let select = "SELECT gtfs_stop_times.trip_id " +
    "FROM gtfs_stop_times " +
    "INNER JOIN gtfs_trips ON gtfs_stop_times.trip_id=gtfs_trips.trip_id " +
    "WHERE stop_id='" + stop.id + "' AND " +
    "departure_time_seconds >= " + tripSearchDate.preSeconds + " AND departure_time_seconds <= " + tripSearchDate.postSeconds + " AND " +
    "pickup_type <> " + StopTime.PICKUP_TYPE_NONE + " AND " +
    "gtfs_trips.service_id IN (" + serviceIdString + ")";

  // Select the Trip IDs
  db.select(select, function(err, results) {

    // Database Query Error
    if ( err ) {
      return callback(
        new Error('Could not get Trip(s) from database')
      );
    }

    // No Results
    if ( results.length === 0 ) {
      return callback(null, rtn);
    }

    // Set the counter
    count = results.length;

    // Build the Trips
    for ( let i = 0; i < results.length; i++ ) {
      TripsTable.getTrip(db, results[i].trip_id, tripSearchDate.date, function(err, trip) {

        // Database Query Error
        if ( err ) {
          return callback(err);
        }

        // Add trip to list
        if ( trip ) {
          rtn.push(trip);
        }

        // Finish Process the Trip
        _finish();

      });
    }

  });

  /**
   * Finished Processing Trip
   * @private
   */
  function _finish() {
    done++;
    if ( done === count ) {
      return callback(null, rtn);
    }
  }

}

module.exports = {
  getTripsFromStop: getTripsFromStop
};<|endoftext|>


<commit_before>import React from 'react';

import UserList from './scopes.user-list';

class Main extends React.Component {
  render() {
    return (
      <main className="s-main">
        <UserList/>
        <UserList/>
      </main>
    );
  }

  // functions.
}

export default Main;
<commit_msg>create test data<commit_after>import React from 'react';

import UserList from './scopes.user-list';

class Main extends React.Component {
  render() {
    let chats = [
      {
        id: 1,
        firstName: 'Joshua',
        lastName: 'Torres',
        lastMessage: 'Nam porttitor blandit accu...',
        imageSource: 'http://placehold.it/50x50',
        lastMessageDate: '17:03',
        unreadMessagesLength: 7,
      },
      {
        id: 2,
        firstName: 'Vincent',
        lastName: 'Gray',
        lastMessage: 'Accusamus, ducimus hic qui...',
        imageSource: 'http://placehold.it/50x50',
        lastMessageDate: '17:03',
        unreadMessagesLength: 4,
      },
      {
        id: 3,
        firstName: 'Marthia',
        lastName: 'Diaz',
        lastMessage: 'Cupiditate sit laudantium ...',
        imageSource: 'http://placehold.it/50x50',
        lastMessageDate: '17:03',
        unreadMessagesLength: 2,
      },
    ];

    let contacts = [
      {
        id: 4,
        firstName: 'John',
        lastName: 'Doe',
        description: 'Frontend Developer',
        imageSource: 'http://placehold.it/50x50',
        lastSeenDate: '17:03',
      },
      {
        id: 5,
        firstName: 'Paul',
        lastName: 'Graham',
        description: 'Interaction Designer',
        imageSource: 'http://placehold.it/50x50',
        lastSeenDate: '17:03',
      },
      {
        id: 6,
        firstName: 'Shirley',
        lastName: 'Reid',
        description: 'Backend Developer',
        imageSource: 'http://placehold.it/50x50',
        lastSeenDate: '17:03',
      },
    ];

    return (
      <main className="s-main">
        <UserList users={chats} idName="chat-list"/>
        <UserList users={contacts} idName="contact-list"/>
      </main>
    );
  }

  // functions.
}

export default Main;
<|endoftext|>


<commit_before>
/* DOM 3 Event: KeyboardEvent:UIEvent
 * http://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents
 */

(function () {
  var keyboardevent_properties,
      isEvent = doodle.Event.isEvent,
      check_boolean_type = doodle.utils.types.check_boolean_type,
      check_number_type = doodle.utils.types.check_number_type,
      check_string_type = doodle.utils.types.check_string_type;

  /* Super constructor
   * @param {String} type
   * @param {Boolean} bubbles
   * @param {Boolean} cancelable
   * @param {DOM Object} view
   * @param {String} keyIdentifier
   * @param {Number} keyLocation
   * @param {String} modifiersList White-space separated list of key modifiers.
   * @param {Boolean} repeat
   *
   * @alternative instantiation
   * @param {Event} initializer event to wrap
   *
   * @return {KeyboardEvent}
   */
  doodle.KeyboardEvent = function (type, bubbles, cancelable, view,
                                   keyIdentifier, keyLocation, modifiersList, repeat) {
    var arg_len = arguments.length,
        initializer, //if passed another event object
        keyboardevent, //this super-object we'll be constructing
        //read-only properties
        ctrlKey = false,
        shiftKey = false,
        altKey = false,
        metaKey = false;

    //check if given an init event to wrap
    if (arg_len === 1 && isEvent(arguments[0])) {
      initializer = arguments[0]; //event object

      //copy event properties to our args that'll be used for initialization
      //initKeyboardEvent() will typecheck these
      type = initializer.type;
      bubbles = initializer.bubbles;
      cancelable = initializer.cancelable;
      view = initializer.view;
      keyIdentifier = initializer.keyIdentifier;
      keyLocation = initializer.keyLocation;
      repeat = initializer.repeat;
      //get modifiers, use defaults to avoid contructing a new modifiers list string
      //initKeyboardEvent() won't touch these
      ctrlKey = initializer.ctrlKey || false;
      shiftKey = initializer.shiftKey || false;
      altKey = initializer.altKey || false;
      metaKey = initializer.metaKey || false;

      //pass on the event arg to init our uievent prototype
      keyboardevent = Object.create(doodle.UIEvent(initializer));

    } else if (arg_len === 0 || arg_len > 8) {
      //check arg count
      throw new SyntaxError("[object KeyboardEvent]: Invalid number of parameters.");
    } else {
      //regular instantiation of our prototype
      bubbles = bubbles === true; //false
      cancelable = cancelable === true;
      view = (view === undefined) ? null : view;
      check_string_type(type, '[object KeyboardEvent].constructor', 'type');
      check_boolean_type(bubbles, '[object KeyboardEvent].constructor', 'bubbles');
      check_boolean_type(cancelable, '[object KeyboardEvent].constructor', 'cancelable');
      keyboardevent = Object.create(doodle.UIEvent(type, bubbles, cancelable, view));
    }

    Object.defineProperties(keyboardevent, keyboardevent_properties);
    Object.defineProperties(keyboardevent, {
      /* PROPERTIES
       */

      'keyIdentifier': {
        enumerable: true,
        configurable: false,
        get: function () { return keyIdentifier; }
      },

      'keyLocation': {
        enumerable: true,
        configurable: false,
        get: function () { return keyLocation; }
      },

      'repeat': {
        enumerable: true,
        configurable: false,
        get: function () { return repeat; }
      },

      'altKey': {
        enumerable: true,
        configurable: false,
        get: function () { return altKey; }
      },

      'ctrlKey': {
        enumerable: true,
        configurable: false,
        get: function () { return ctrlKey; }
      },

      'metaKey': {
        enumerable: true,
        configurable: false,
        get: function () { return metaKey; }
      },

      'shiftKey': {
        enumerable: true,
        configurable: false,
        get: function () { return shiftKey; }
      },

      /* METHODS
       */

      'initKeyboardEvent': {
        value: function (typeArg, canBubbleArg, cancelableArg, viewArg,
                         keyIdentifierArg, keyLocationArg, modifiersListArg, repeatArg) {
          //parameter defaults, assign to outer constructor vars
          type = typeArg;
          bubbles = canBubbleArg === true; //false
          cancelable = cancelableArg === true;
          view = (viewArg === undefined) ? null : viewArg;
          keyIdentifier = (keyIdentifierArg === undefined) ? "" : keyIdentifierArg;
          keyLocation = (keyLocationArg === undefined) ? 0 : keyLocationArg;
          modifiersList = (modifiersListArg === undefined) ? "" : modifiersListArg;
          repeat = repeatArg === true;
          //type-check
          check_string_type(type, this+'.initKeyboardEvent', 'type');
          check_boolean_type(bubbles, this+'.initKeyboardEvent', 'bubbles');
          check_boolean_type(cancelable, this+'.initKeyboardEvent', 'cancelable');
          check_string_type(keyIdentifier, this+'.initKeyboardEvent', 'keyIdentifier');
          check_number_type(keyLocation, this+'.initKeyboardEvent', 'keyLocation');
          check_string_type(modifiersList, this+'.initKeyboardEvent', 'modifiersList');
          check_boolean_type(repeat, this+'.initKeyboardEvent', 'repeat');

          //parse string of white-space separated list of modifier key identifiers
          modifiersList.split(" ").forEach(function (modifier) {
            switch (modifier) {
            case 'Alt':
              altKey = true;
              break;
            case 'Control':
              ctrlKey = true;
              break;
            case 'Meta':
              metaKey = true;
              break;
            case 'Shift':
              shiftKey = true;
              break;
            }
          });

          this.initUIEvent(type, bubbles, cancelable, view);
          return this;
        }
      },

      /* Queries the state of a modifier using a key identifier.
       * @param {String} key A modifier key identifier
       * @return {Boolean} True if it is a modifier key and the modifier is activated, false otherwise.
       * This is an incomplete list of modifiers.
       */
      'getModifierState': {
        value: function (key) {
          check_string_type(key, this+'.getModifierState');
          switch (key) {
          case 'Alt':
            return altKey;
          case 'Control':
            return ctrlKey;
          case 'Meta':
            return metaKey;
          case 'Shift':
            return shiftKey;
          default:
            return false;
          }
        }
      }

    });

    //init event
    keyboardevent.initKeyboardEvent(type, bubbles, cancelable, view,
                                    keyIdentifier, keyLocation, modifiersList, repeat);

    return keyboardevent;
  };

  //static
  keyboardevent_properties = {
    'toString': {
      enumerable: true,
      writable: false,
      configurable: false,
      value: function () {
        return "[object KeyboardEvent]";
      }
    }
  };

}());//end class closure
<commit_msg>Added debug makers to KeyboardEvent.<commit_after>
/* DOM 3 Event: KeyboardEvent:UIEvent
 * http://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents
 */

(function () {
  var keyboardevent_properties,
      isEvent = doodle.Event.isEvent,
      check_boolean_type = doodle.utils.types.check_boolean_type,
      check_number_type = doodle.utils.types.check_number_type,
      check_string_type = doodle.utils.types.check_string_type;

  /* Super constructor
   * @param {String} type
   * @param {Boolean} bubbles
   * @param {Boolean} cancelable
   * @param {DOM Object} view
   * @param {String} keyIdentifier
   * @param {Number} keyLocation
   * @param {String} modifiersList White-space separated list of key modifiers.
   * @param {Boolean} repeat
   *
   * @alternative instantiation
   * @param {Event} initializer event to wrap
   *
   * @return {KeyboardEvent}
   */
  doodle.KeyboardEvent = function (type, bubbles, cancelable, view,
                                   keyIdentifier, keyLocation, modifiersList, repeat) {
    var arg_len = arguments.length,
        initializer, //if passed another event object
        keyboardevent, //this super-object we'll be constructing
        //read-only properties
        ctrlKey = false,
        shiftKey = false,
        altKey = false,
        metaKey = false;

    //check if given an init event to wrap
    if (arg_len === 1 && isEvent(arguments[0])) {
      initializer = arguments[0]; //event object

      //copy event properties to our args that'll be used for initialization
      //initKeyboardEvent() will typecheck these
      type = initializer.type;
      bubbles = initializer.bubbles;
      cancelable = initializer.cancelable;
      view = initializer.view;
      keyIdentifier = initializer.keyIdentifier;
      keyLocation = initializer.keyLocation;
      repeat = initializer.repeat;
      //get modifiers, use defaults to avoid contructing a new modifiers list string
      //initKeyboardEvent() won't touch these
      ctrlKey = initializer.ctrlKey || false;
      shiftKey = initializer.shiftKey || false;
      altKey = initializer.altKey || false;
      metaKey = initializer.metaKey || false;

      //pass on the event arg to init our uievent prototype
      keyboardevent = Object.create(doodle.UIEvent(initializer));

    } else if (arg_len === 0 || arg_len > 8) {
      //check arg count
      throw new SyntaxError("[object KeyboardEvent]: Invalid number of parameters.");
    } else {
      //regular instantiation of our prototype
      bubbles = bubbles === true; //false
      cancelable = cancelable === true;
      view = (view === undefined) ? null : view;

      /*DEBUG*/
      check_string_type(type, '[object KeyboardEvent].constructor', '*type*');
      check_boolean_type(bubbles, '[object KeyboardEvent].constructor', '*bubbles*');
      check_boolean_type(cancelable, '[object KeyboardEvent].constructor', '*cancelable*');
      /*END_DEBUG*/

      keyboardevent = Object.create(doodle.UIEvent(type, bubbles, cancelable, view));
    }

    Object.defineProperties(keyboardevent, keyboardevent_properties);
    Object.defineProperties(keyboardevent, {
      /* PROPERTIES
       */

      'keyIdentifier': {
        enumerable: true,
        configurable: false,
        get: function () { return keyIdentifier; }
      },

      'keyLocation': {
        enumerable: true,
        configurable: false,
        get: function () { return keyLocation; }
      },

      'repeat': {
        enumerable: true,
        configurable: false,
        get: function () { return repeat; }
      },

      'altKey': {
        enumerable: true,
        configurable: false,
        get: function () { return altKey; }
      },

      'ctrlKey': {
        enumerable: true,
        configurable: false,
        get: function () { return ctrlKey; }
      },

      'metaKey': {
        enumerable: true,
        configurable: false,
        get: function () { return metaKey; }
      },

      'shiftKey': {
        enumerable: true,
        configurable: false,
        get: function () { return shiftKey; }
      },

      /* METHODS
       */

      'initKeyboardEvent': {
        value: function (typeArg, canBubbleArg, cancelableArg, viewArg,
                         keyIdentifierArg, keyLocationArg, modifiersListArg, repeatArg) {
          //parameter defaults, assign to outer constructor vars
          type = typeArg;
          bubbles = canBubbleArg === true; //false
          cancelable = cancelableArg === true;
          view = (viewArg === undefined) ? null : viewArg;
          keyIdentifier = (keyIdentifierArg === undefined) ? "" : keyIdentifierArg;
          keyLocation = (keyLocationArg === undefined) ? 0 : keyLocationArg;
          modifiersList = (modifiersListArg === undefined) ? "" : modifiersListArg;
          repeat = repeatArg === true;

          /*DEBUG*/
          check_string_type(type, this+'.initKeyboardEvent', 'type');
          check_boolean_type(bubbles, this+'.initKeyboardEvent', 'bubbles');
          check_boolean_type(cancelable, this+'.initKeyboardEvent', 'cancelable');
          check_string_type(keyIdentifier, this+'.initKeyboardEvent', 'keyIdentifier');
          check_number_type(keyLocation, this+'.initKeyboardEvent', 'keyLocation');
          check_string_type(modifiersList, this+'.initKeyboardEvent', 'modifiersList');
          check_boolean_type(repeat, this+'.initKeyboardEvent', 'repeat');
          /*END_DEBUG*/

          //parse string of white-space separated list of modifier key identifiers
          modifiersList.split(" ").forEach(function (modifier) {
            switch (modifier) {
            case 'Alt':
              altKey = true;
              break;
            case 'Control':
              ctrlKey = true;
              break;
            case 'Meta':
              metaKey = true;
              break;
            case 'Shift':
              shiftKey = true;
              break;
            }
          });

          this.initUIEvent(type, bubbles, cancelable, view);
          return this;
        }
      },

      /* Queries the state of a modifier using a key identifier.
       * @param {String} key A modifier key identifier
       * @return {Boolean} True if it is a modifier key and the modifier is activated, false otherwise.
       * This is an incomplete list of modifiers.
       */
      'getModifierState': {
        value: function (key) {
          check_string_type(key, this+'.getModifierState');
          switch (key) {
          case 'Alt':
            return altKey;
          case 'Control':
            return ctrlKey;
          case 'Meta':
            return metaKey;
          case 'Shift':
            return shiftKey;
          default:
            return false;
          }
        }
      }

    });

    //init event
    keyboardevent.initKeyboardEvent(type, bubbles, cancelable, view,
                                    keyIdentifier, keyLocation, modifiersList, repeat);

    return keyboardevent;
  };

  //static
  keyboardevent_properties = {
    'toString': {
      enumerable: true,
      writable: false,
      configurable: false,
      value: function () {
        return "[object KeyboardEvent]";
      }
    }
  };

}());//end class closure
<|endoftext|>


<commit_before>// Main app module.
(function (THREE) {
    'use strict';

    var scene = new THREE.Scene();
    var renderer = window.WebGLRenderingContext ? new THREE.WebGLRenderer() : new THREE.CanvasRenderer();
    var light = new THREE.AmbientLight(0xffffff);
    var camera = ebg.initScene({
        scene: scene,
        renderer: renderer,
        light: light,
        camera: {
            type: 'PerspectiveCamera',
            angle: 45,
            aspectRatio: window.innerWidth / window.innerHeight,
            nearPlane: 1,
            farPlane: 500,
            position: {
                z: 15
            }
        },
        controls: {
            type: 'OrbitControls',
            listenFor: 'change',
            callback: function() {
                ebg.render({
                    renderer: renderer,
                    scene: scene,
                    camera: camera
                });
            }
        }
    });

    // Static spaceship.
    ebg.loadModel({
        path: '/models/spaceship/spaceship.dae',
        name: 'static-spaceship',
        scene: scene,
        position: {
            x: -5,
            z: 2
        },
        rotation: {
            x: 30
        }
    });

    // Animated spaceship.
    ebg.loadModel({
        path: '/models/spaceship/spaceship.dae',
        name: 'fast-spaceship',
        scene: scene,
        position: {
            x: 1.5,
            y: 20,
            z: -25
        },
        rotation: {
            x: 30
        }
    });

    // Animated spaceship.
    ebg.loadModel({
        path: '/models/spaceship/spaceship.dae',
        name: 'slow-spaceship',
        scene: scene,
        position: {
            x: -1,
            y: 20,
            z: -45
        },
        rotation: {
            x: 30
        }
    });

    // Render the scene.
    ebg.render({
        renderer: renderer,
        scene: scene,
        camera: camera,
        sprites: [
            {
                // This spaceship is no animated because the orbit controls are used to look at it.
                name: 'static-spaceship',
                scene: scene
            },
            {
                name: 'fast-spaceship',
                scene: scene,
                // The heartbeat of a sprite is run every tick of the main render.
                heartbeat: function (input) {
                    var name = input && input.name;
                    var scene = input && input.scene;
                    var sprite;

                    if (!name || !scene) {
                        throw new Error(ebg.err.input.required);
                    }

                    sprite = scene.getObjectByName(name);

                    if (!sprite) {
                        return; // Sprite hasn't been found yet, it has probably not finished loading.
                    }

                    // Only run code below this point once the sprite has been found in the scene.

                    if (sprite.position.y > 0) {
                        // First vector: the spaceship slowly comes into view, losing altitude.
                        sprite.position.z += 0.05;
                        sprite.position.y += -0.05;
                    } else {
                        // Second vector: the spaceship speeds away from field of camera.
                        sprite.position.z += 1;
                    }

                    if (sprite.position.z > 25) {
                        sprite.position.set(1.5, 20, -25); // back to start position.
                    }
                }
            },
            {
                name: 'slow-spaceship',
                scene: scene,
                // The heartbeat of a sprite is run every tick of the main render.
                heartbeat: function (input) {
                    var name = input && input.name;
                    var scene = input && input.scene;
                    var sprite;

                    if (!name || !scene) {
                        throw new Error(ebg.err.input.required);
                    }

                    sprite = scene.getObjectByName(name);

                    if (!sprite) {
                        return; // Sprite hasn't been found yet, it has probably not finished loading.
                    }

                    // Only run code below this point once the sprite has been found in the scene.

                    if (sprite.position.y > -2) {
                        // First vector: the spaceship slowly comes into view, losing altitude.
                        sprite.position.z += 0.05;
                        sprite.position.y += -0.05;
                    } else {
                        // Second vector: the spaceship moves away from field of camera, slower than fast-spaceship.
                        sprite.position.z += 0.33;
                    }

                    if (sprite.position.z > 25) {
                        sprite.position.set(-1, 20, -45); // back to start position.
                    }
                }
            }
        ],
        // The callback is run every tick of the main render. It co-ordinates running all sprite heartbeats.
        callback: function callback (input) {
            var sprites = input && input.sprites;

            if (!sprites) {
                throw new Error(ebg.err.input.required);
            }

            sprites.map(function (sprite) {
                if (sprite.heartbeat) {
                    sprite.heartbeat(sprite);
                }
            });
        }
    });
}(THREE));
<commit_msg>fixed path to make it relative and working on gh-pages<commit_after>// Main app module.
(function (THREE) {
    'use strict';

    var scene = new THREE.Scene();
    var renderer = window.WebGLRenderingContext ? new THREE.WebGLRenderer() : new THREE.CanvasRenderer();
    var light = new THREE.AmbientLight(0xffffff);
    var camera = ebg.initScene({
        scene: scene,
        renderer: renderer,
        light: light,
        camera: {
            type: 'PerspectiveCamera',
            angle: 45,
            aspectRatio: window.innerWidth / window.innerHeight,
            nearPlane: 1,
            farPlane: 500,
            position: {
                z: 15
            }
        },
        controls: {
            type: 'OrbitControls',
            listenFor: 'change',
            callback: function() {
                ebg.render({
                    renderer: renderer,
                    scene: scene,
                    camera: camera
                });
            }
        }
    });

    // Static spaceship.
    ebg.loadModel({
        path: 'models/spaceship/spaceship.dae',
        name: 'static-spaceship',
        scene: scene,
        position: {
            x: -5,
            z: 2
        },
        rotation: {
            x: 30
        }
    });

    // Animated spaceship.
    ebg.loadModel({
        path: 'models/spaceship/spaceship.dae',
        name: 'fast-spaceship',
        scene: scene,
        position: {
            x: 1.5,
            y: 20,
            z: -25
        },
        rotation: {
            x: 30
        }
    });

    // Animated spaceship.
    ebg.loadModel({
        path: 'models/spaceship/spaceship.dae',
        name: 'slow-spaceship',
        scene: scene,
        position: {
            x: -1,
            y: 20,
            z: -45
        },
        rotation: {
            x: 30
        }
    });

    // Render the scene.
    ebg.render({
        renderer: renderer,
        scene: scene,
        camera: camera,
        sprites: [
            {
                // This spaceship is no animated because the orbit controls are used to look at it.
                name: 'static-spaceship',
                scene: scene
            },
            {
                name: 'fast-spaceship',
                scene: scene,
                // The heartbeat of a sprite is run every tick of the main render.
                heartbeat: function (input) {
                    var name = input && input.name;
                    var scene = input && input.scene;
                    var sprite;

                    if (!name || !scene) {
                        throw new Error(ebg.err.input.required);
                    }

                    sprite = scene.getObjectByName(name);

                    if (!sprite) {
                        return; // Sprite hasn't been found yet, it has probably not finished loading.
                    }

                    // Only run code below this point once the sprite has been found in the scene.

                    if (sprite.position.y > 0) {
                        // First vector: the spaceship slowly comes into view, losing altitude.
                        sprite.position.z += 0.05;
                        sprite.position.y += -0.05;
                    } else {
                        // Second vector: the spaceship speeds away from field of camera.
                        sprite.position.z += 1;
                    }

                    if (sprite.position.z > 25) {
                        sprite.position.set(1.5, 20, -25); // back to start position.
                    }
                }
            },
            {
                name: 'slow-spaceship',
                scene: scene,
                // The heartbeat of a sprite is run every tick of the main render.
                heartbeat: function (input) {
                    var name = input && input.name;
                    var scene = input && input.scene;
                    var sprite;

                    if (!name || !scene) {
                        throw new Error(ebg.err.input.required);
                    }

                    sprite = scene.getObjectByName(name);

                    if (!sprite) {
                        return; // Sprite hasn't been found yet, it has probably not finished loading.
                    }

                    // Only run code below this point once the sprite has been found in the scene.

                    if (sprite.position.y > -2) {
                        // First vector: the spaceship slowly comes into view, losing altitude.
                        sprite.position.z += 0.05;
                        sprite.position.y += -0.05;
                    } else {
                        // Second vector: the spaceship moves away from field of camera, slower than fast-spaceship.
                        sprite.position.z += 0.33;
                    }

                    if (sprite.position.z > 25) {
                        sprite.position.set(-1, 20, -45); // back to start position.
                    }
                }
            }
        ],
        // The callback is run every tick of the main render. It co-ordinates running all sprite heartbeats.
        callback: function callback (input) {
            var sprites = input && input.sprites;

            if (!sprites) {
                throw new Error(ebg.err.input.required);
            }

            sprites.map(function (sprite) {
                if (sprite.heartbeat) {
                    sprite.heartbeat(sprite);
                }
            });
        }
    });
}(THREE));
<|endoftext|>


<commit_before>import { t, textDirection } from '../util/locale';
import { tooltip } from '../util/tooltip';
import { modeBrowse } from '../modes/index';
import { geoExtent } from '../geo/index';
import { svgIcon } from '../svg/index';
import { uiLoading } from './loading';

export function uiGeolocate(context) {
    var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ },
        locating = uiLoading(context).message(t('geolocate.locating')).blocking(true),
        timeoutId;

    function click() {
        context.enter(modeBrowse(context));
        context.container().call(locating);
        navigator.geolocation.getCurrentPosition(success, error, geoOptions);

        // This timeout ensures that we still call finish() even if
        // the user declines to share their location in Firefox
        timeoutId = setTimeout(finish, 10000 /* 10sec */ );
    }

    function success(position) {
        var map = context.map(),
            extent = geoExtent([position.coords.longitude, position.coords.latitude])
                .padByMeters(position.coords.accuracy);

        map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent)));
        finish();
    }

    function error() {
        finish();
    }

    function finish() {
        locating.close();  // unblock ui
        if (timeoutId) { clearTimeout(timeoutId); }
        timeoutId = undefined;
    }

    return function(selection) {
        if (!navigator.geolocation) return;

        selection
            .append('button')
            .attr('tabindex', -1)
            .attr('title', t('geolocate.title'))
            .on('click', click)
            .call(svgIcon('#icon-geolocate', 'light'))
            .call(tooltip()
                .placement((textDirection === 'rtl') ? 'right' : 'left'));
    };
}
<commit_msg>Don't allow geolocate while in walkthrough<commit_after>import { t, textDirection } from '../util/locale';
import { tooltip } from '../util/tooltip';
import { modeBrowse } from '../modes/index';
import { geoExtent } from '../geo/index';
import { svgIcon } from '../svg/index';
import { uiLoading } from './loading';

export function uiGeolocate(context) {
    var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ },
        locating = uiLoading(context).message(t('geolocate.locating')).blocking(true),
        timeoutId;

    function click() {
        if (context.inIntro()) return;
        context.enter(modeBrowse(context));
        context.container().call(locating);
        navigator.geolocation.getCurrentPosition(success, error, geoOptions);

        // This timeout ensures that we still call finish() even if
        // the user declines to share their location in Firefox
        timeoutId = setTimeout(finish, 10000 /* 10sec */ );
    }

    function success(position) {
        var map = context.map(),
            extent = geoExtent([position.coords.longitude, position.coords.latitude])
                .padByMeters(position.coords.accuracy);

        map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent)));
        finish();
    }

    function error() {
        finish();
    }

    function finish() {
        locating.close();  // unblock ui
        if (timeoutId) { clearTimeout(timeoutId); }
        timeoutId = undefined;
    }

    return function(selection) {
        if (!navigator.geolocation) return;

        selection
            .append('button')
            .attr('tabindex', -1)
            .attr('title', t('geolocate.title'))
            .on('click', click)
            .call(svgIcon('#icon-geolocate', 'light'))
            .call(tooltip()
                .placement((textDirection === 'rtl') ? 'right' : 'left'));
    };
}
<|endoftext|>


<commit_before>/*
Language: Less
Author:   Max Mikhailov <seven.phases.max@gmail.com>
Category: css
*/

function(hljs) {
  var IDENT_RE        = '[\\w-]+'; // yes, Less identifiers may begin with a digit
  var INTERP_IDENT_RE = '(' + IDENT_RE + '|@{' + IDENT_RE + '})';

  /* Generic Modes */

  var RULES = [], VALUE = []; // forward def. for recursive modes

  var STRING_MODE = function(c) { return {
    // Less strings are not multiline (also include '~' for more consistent coloring of "escaped" strings)
    className: 'string', begin: '~?' + c + '.*?' + c
  };};

  var IDENT_MODE = function(name, begin, relevance) { return {
    className: name, begin: begin, relevance: relevance
  };};

  var FUNCT_MODE = function(name, ident, obj) {
    return hljs.inherit({
        className: name, begin: ident + '\\(', end: '\\(',
        returnBegin: true, excludeEnd: true, relevance: 0
    }, obj);
  };

  var PARENS_MODE = {
    // used only to properly balance nested parens inside mixin call, def. arg list
    begin: '\\(', end: '\\)', contains: VALUE, relevance: 0
  };

  // generic Less highlighter (used almost everywhere except selectors):
  VALUE.push(
    hljs.C_LINE_COMMENT_MODE,
    hljs.C_BLOCK_COMMENT_MODE,
    STRING_MODE("'"),
    STRING_MODE('"'),
    hljs.CSS_NUMBER_MODE, // fixme: it does not include dot for numbers like .5em :(
    IDENT_MODE('hexcolor', '#[0-9A-Fa-f]+\\b'),
    FUNCT_MODE('function', '(url|data-uri)', {
      starts: {className: 'string', end: '[\\)\\n]', excludeEnd: true}
    }),
    FUNCT_MODE('function', IDENT_RE),
    PARENS_MODE,
    IDENT_MODE('variable', '@@?' + IDENT_RE, 10),
    IDENT_MODE('variable', '@{'  + IDENT_RE + '}'),
    IDENT_MODE('built_in', '~?`[^`]*?`'), // inline javascript (or whatever host language) *multiline* string
    { // @media features (it’s here to not duplicate things in AT_RULE_MODE with extra PARENS_MODE overriding):
      className: 'attribute', begin: IDENT_RE + '\\s*:', end: ':', returnBegin: true, excludeEnd: true
    }
  );

  var VALUE_WITH_RULESETS = VALUE.concat({
    begin: '{', end: '}', contains: RULES
  });

  var MIXIN_GUARD_MODE = {
    beginKeywords: 'when', endsWithParent: true,
    contains: [{beginKeywords: 'and not'}].concat(VALUE) // using this form to override VALUE’s 'function' match
  };

  /* Rule-Level Modes */

  var RULE_MODE = {
    className: 'attribute',
    begin: INTERP_IDENT_RE, end: ':', excludeEnd: true,
    contains: [hljs.C_LINE_COMMENT_MODE, hljs.C_BLOCK_COMMENT_MODE],
    illegal: /\S/,
    starts: {end: '[;}]', returnEnd: true, contains: VALUE, illegal: '[<=$]'}
  };

  var AT_RULE_MODE = {
    className: 'at_rule', // highlight only at-rule keyword
    begin: '@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b',
    starts: {end: '[;{}]', returnEnd: true, contains: VALUE, relevance: 0}
  };

  // variable definitions and calls
  var VAR_RULE_MODE = {
    className: 'variable',
    variants: [
      // using more strict pattern for higher relevance to increase chances of Less detection.
      // this is *the only* Less specific statement used in most of the sources, so...
      // (we’ll still often loose to the css-parser unless there's '//' comment,
      // simply because 1 variable just can't beat 99 properties :)
      {begin: '@' + IDENT_RE + '\\s*:', relevance: 15},
      {begin: '@' + IDENT_RE}
    ],
    starts: {end: '[;}]', returnEnd: true, contains: VALUE_WITH_RULESETS}
  };

  var SELECTOR_MODE = {
    // first parse unambiguous selectors (i.e. those not starting with tag)
    // then fall into the scary lookahead-discriminator variant.
    // this mode also handles mixin definitions and calls
    variants: [{
      begin: '[\\.#:&\\[]', end: '[;{}]'  // mixin calls end with ';'
      }, {
      begin: INTERP_IDENT_RE + '[^;]*{',
      end: '{'
    }],
    returnBegin: true,
    returnEnd:   true,
    illegal: '[<=\'$"]',
    contains: [
      hljs.C_LINE_COMMENT_MODE,
      hljs.C_BLOCK_COMMENT_MODE,
      MIXIN_GUARD_MODE,
      IDENT_MODE('keyword',  'all\\b'),
      IDENT_MODE('variable', '@{'  + IDENT_RE + '}'),     // otherwise it’s identified as tag
      IDENT_MODE('tag',       INTERP_IDENT_RE + '%?', 0), // '%' for more consistent coloring of @keyframes "tags"
      IDENT_MODE('id',       '#'   + INTERP_IDENT_RE),
      IDENT_MODE('class',    '\\.' + INTERP_IDENT_RE, 0),
      IDENT_MODE('keyword',  '&', 0),
      FUNCT_MODE('pseudo',   ':not'),
      FUNCT_MODE('keyword',  ':extend'),
      IDENT_MODE('pseudo',   '::?' + INTERP_IDENT_RE),
      {className: 'attr_selector', begin: '\\[', end: '\\]'},
      {begin: '\\(', end: '\\)', contains: VALUE_WITH_RULESETS}, // argument list of parametric mixins
      {begin: '!important'} // eat !important after mixin call or it will be colored as tag
    ]
  };

  RULES.push(
    hljs.C_LINE_COMMENT_MODE,
    hljs.C_BLOCK_COMMENT_MODE,
    AT_RULE_MODE,
    VAR_RULE_MODE,
    SELECTOR_MODE,
    RULE_MODE
  );

  return {
    case_insensitive: true,
    illegal: '[=>\'/<($"]',
    contains: RULES
  };
}
<commit_msg>Updated less.js to new class names.<commit_after>/*
Language: Less
Author:   Max Mikhailov <seven.phases.max@gmail.com>
Category: css
*/

function(hljs) {
  var IDENT_RE        = '[\\w-]+'; // yes, Less identifiers may begin with a digit
  var INTERP_IDENT_RE = '(' + IDENT_RE + '|@{' + IDENT_RE + '})';

  /* Generic Modes */

  var RULES = [], VALUE = []; // forward def. for recursive modes

  var STRING_MODE = function(c) { return {
    // Less strings are not multiline (also include '~' for more consistent coloring of "escaped" strings)
    className: 'string', begin: '~?' + c + '.*?' + c
  };};

  var IDENT_MODE = function(name, begin, relevance) { return {
    className: name, begin: begin, relevance: relevance
  };};

  var PARENS_MODE = {
    // used only to properly balance nested parens inside mixin call, def. arg list
    begin: '\\(', end: '\\)', contains: VALUE, relevance: 0
  };

  // generic Less highlighter (used almost everywhere except selectors):
  VALUE.push(
    hljs.C_LINE_COMMENT_MODE,
    hljs.C_BLOCK_COMMENT_MODE,
    STRING_MODE("'"),
    STRING_MODE('"'),
    hljs.CSS_NUMBER_MODE, // fixme: it does not include dot for numbers like .5em :(
    {
      begin: '(url|data-uri)\\(',
      starts: {className: 'string', end: '[\\)\\n]', excludeEnd: true}
    },
    IDENT_MODE('number', '#[0-9A-Fa-f]+\\b'),
    PARENS_MODE,
    IDENT_MODE('variable', '@@?' + IDENT_RE, 10),
    IDENT_MODE('variable', '@{'  + IDENT_RE + '}'),
    IDENT_MODE('built_in', '~?`[^`]*?`'), // inline javascript (or whatever host language) *multiline* string
    { // @media features (it’s here to not duplicate things in AT_RULE_MODE with extra PARENS_MODE overriding):
      className: 'attribute', begin: IDENT_RE + '\\s*:', end: ':', returnBegin: true, excludeEnd: true
    },
    {
      className: 'meta',
      begin: '!important'
    }
  );

  var VALUE_WITH_RULESETS = VALUE.concat({
    begin: '{', end: '}', contains: RULES
  });

  var MIXIN_GUARD_MODE = {
    beginKeywords: 'when', endsWithParent: true,
    contains: [{beginKeywords: 'and not'}].concat(VALUE) // using this form to override VALUE’s 'function' match
  };

  /* Rule-Level Modes */

  var RULE_MODE = {
    className: 'attribute',
    begin: INTERP_IDENT_RE, end: ':', excludeEnd: true,
    contains: [hljs.C_LINE_COMMENT_MODE, hljs.C_BLOCK_COMMENT_MODE],
    illegal: /\S/,
    starts: {end: '[;}]', returnEnd: true, contains: VALUE, illegal: '[<=$]'}
  };

  var AT_RULE_MODE = {
    className: 'keyword',
    begin: '@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b',
    starts: {end: '[;{}]', returnEnd: true, contains: VALUE, relevance: 0}
  };

  // variable definitions and calls
  var VAR_RULE_MODE = {
    className: 'variable',
    variants: [
      // using more strict pattern for higher relevance to increase chances of Less detection.
      // this is *the only* Less specific statement used in most of the sources, so...
      // (we’ll still often loose to the css-parser unless there's '//' comment,
      // simply because 1 variable just can't beat 99 properties :)
      {begin: '@' + IDENT_RE + '\\s*:', relevance: 15},
      {begin: '@' + IDENT_RE}
    ],
    starts: {end: '[;}]', returnEnd: true, contains: VALUE_WITH_RULESETS}
  };

  var SELECTOR_MODE = {
    // first parse unambiguous selectors (i.e. those not starting with tag)
    // then fall into the scary lookahead-discriminator variant.
    // this mode also handles mixin definitions and calls
    variants: [{
      begin: '[\\.#:&\\[]', end: '[;{}]'  // mixin calls end with ';'
      }, {
      begin: INTERP_IDENT_RE + '[^;]*{',
      end: '{'
    }],
    returnBegin: true,
    returnEnd:   true,
    illegal: '[<=\'$"]',
    contains: [
      hljs.C_LINE_COMMENT_MODE,
      hljs.C_BLOCK_COMMENT_MODE,
      MIXIN_GUARD_MODE,
      IDENT_MODE('keyword',  'all\\b'),
      IDENT_MODE('variable', '@{'  + IDENT_RE + '}'),     // otherwise it’s identified as tag
      IDENT_MODE('keyword',  INTERP_IDENT_RE + '%?', 0), // '%' for more consistent coloring of @keyframes "tags"
      IDENT_MODE('name',     '#'   + INTERP_IDENT_RE),
      IDENT_MODE('name',     '\\.' + INTERP_IDENT_RE, 0),
      IDENT_MODE('keyword',  '&', 0),
      {begin: '\\[', end: '\\]'},
      {begin: '\\(', end: '\\)', contains: VALUE_WITH_RULESETS}, // argument list of parametric mixins
      {begin: '!important'} // eat !important after mixin call or it will be colored as tag
    ]
  };

  RULES.push(
    hljs.C_LINE_COMMENT_MODE,
    hljs.C_BLOCK_COMMENT_MODE,
    AT_RULE_MODE,
    VAR_RULE_MODE,
    SELECTOR_MODE,
    RULE_MODE
  );

  return {
    case_insensitive: true,
    illegal: '[=>\'/<($"]',
    contains: RULES
  };
}
<|endoftext|>