<commit_before>/*$AMPERSAND_VERSION*/
var Store = require('key-tree-store');
var dom = require('ampersand-dom');
var matchesSelector = require('matches-selector');
var partial = require('lodash.partial');
var slice = Array.prototype.slice;

function getMatches(el, selector) {
    if (selector === '') return [el];
    var matches = [];
    if(!selector) return matches;
    if(selector.firstMatchOnly) {
        //interactar modification to retrieve only firstMatchOnly element
        if (matchesSelector(el, selector.firstMatchOnly)) return [el];
        return matches.concat(slice.call([el.querySelector(selector.firstMatchOnly) || el]));
    }else{
        if (matchesSelector(el, selector)) matches.push(el);
        return matches.concat(slice.call(el.querySelectorAll(selector)));
    }
}
function setAttributes(el, attrs) {
    for (var name in attrs) {
        dom.setAttribute(el, name, attrs[name]);
    }
}

function removeAttributes(el, attrs) {
    for (var name in attrs) {
        dom.removeAttribute(el, name);
    }
}

function makeArray(val) {
    return Array.isArray(val) ? val : [val];
}

function switchHandler(binding, el, value) {
    // the element selector to show
    var showValue = binding.cases[value];
    // hide all the other elements with a different value
    for (var item in binding.cases) {
        var curValue = binding.cases[item];
        if (value !== item && curValue !== showValue) {
            getMatches(el, curValue).forEach(function (match) {
                dom.hide(match);
            });
        }
    }
    getMatches(el, showValue).forEach(function (match) {
        dom.show(match);
    });
}

function getSelector(binding) {
    if(binding.firstMatchOnly !== undefined && binding.firstMatchOnly === true) {
        if (typeof binding.selector === 'string') {
            return {firstMatchOnly:binding.selector};
        } else if (binding.hook) {
            return {firstMatchOnly:'[data-hook~="' + binding.hook + '"]'};
        } else {
            return {firstMatchOnly:''};
        }
    }else{
        if (typeof binding.selector === 'string') {
          return binding.selector;
        } else if (binding.hook) {
          return '[data-hook~="' + binding.hook + '"]';
        } else {
          return '';
        }
    }
}

function getBindingFunc(binding, context) {
    var type = binding.type || 'text';
    var isCustomBinding = typeof type === 'function';
    var selector = getSelector(binding);
    var yes = binding.yes;
    var no = binding.no;
    var hasYesNo = !!(yes || no);

    // storage variable for previous if relevant
    var previousValue;

    if (isCustomBinding) {
        return function (el, value) {
            getMatches(el, selector).forEach(function (match) {
                type.call(context, match, value, previousValue);
            });
            previousValue = value;
        };
    } else if (type === 'text') {
        return function (el, value) {
            getMatches(el, selector).forEach(function (match) {
                dom.text(match, value);
            });
        };
    } else if (type === 'class') {
        return function (el, value) {
            getMatches(el, selector).forEach(function (match) {
                dom.switchClass(match, previousValue, value);
            });
            previousValue = value;
        };
    } else if (type === 'attribute') {
        if (!binding.name) throw Error('attribute bindings must have a "name"');
        return function (el, value) {
            var names = makeArray(binding.name);
            getMatches(el, selector).forEach(function (match) {
                names.forEach(function (name) {
                    dom.setAttribute(match, name, value);
                });
            });
            previousValue = value;
        };
    } else if (type === 'value') {
        return function (el, value) {
            getMatches(el, selector).forEach(function (match) {
                if (!value && value !== 0) value = '';
                // only apply bindings if element is not currently focused
                if (document.activeElement !== match) match.value = value;
            });
            previousValue = value;
        };
    } else if (type === 'booleanClass') {
        // if there's a `no` case this is actually a switch
        if (hasYesNo) {
            yes = makeArray(yes || '');
            no = makeArray(no || '');
            return function (el, value) {
                var prevClass = value ? no : yes;
                var newClass = value ? yes : no;
                getMatches(el, selector).forEach(function (match) {
                    prevClass.forEach(function (pc) {
                        dom.removeClass(match, pc);
                    });
                    newClass.forEach(function (nc) {
                        dom.addClass(match, nc);
                    });
                });
            };
        } else {
            return function (el, value, keyName) {
                var name = makeArray(binding.name || keyName);
                var invert = (binding.invert || false);
                value = (invert ? (value ? false : true) : value);
                getMatches(el, selector).forEach(function (match) {
                    name.forEach(function (className) {
                        dom[value ? 'addClass' : 'removeClass'](match, className);
                    });
                });
            };
        }
    } else if (type === 'booleanAttribute') {
        // if there are `yes` and `no` selectors, this swaps between them
        if (hasYesNo) {
            yes = makeArray(yes || '');
            no = makeArray(no || '');
            return function (el, value) {
                var prevAttribute = value ? no : yes;
                var newAttribute = value ? yes : no;
                getMatches(el, selector).forEach(function (match) {
                    prevAttribute.forEach(function (pa) {
                        if (pa) {
                            dom.removeAttribute(match, pa);
                        }
                    });
                    newAttribute.forEach(function (na) {
                        if (na) {
                            dom.addAttribute(match, na);
                        }
                    });
                });
            };
        } else {
            return function (el, value, keyName) {
                var name = makeArray(binding.name || keyName);
                var invert = (binding.invert || false);
                value = (invert ? (value ? false : true) : value);
                getMatches(el, selector).forEach(function (match) {
                    name.forEach(function (attr) {
                        dom[value ? 'addAttribute' : 'removeAttribute'](match, attr);
                    });
                });
            };
        }
    } else if (type === 'toggle') {
        var mode = (binding.mode || 'display');
        var invert = (binding.invert || false);
        // this doesn't require a selector since we can pass yes/no selectors
        if (hasYesNo) {
            return function (el, value) {
                getMatches(el, yes).forEach(function (match) {
                    dom[value ? 'show' : 'hide'](match, mode);
                });
                getMatches(el, no).forEach(function (match) {
                    dom[value ? 'hide' : 'show'](match, mode);
                });
            };
        } else {
            return function (el, value) {
                value = (invert ? (value ? false : true) : value);
                getMatches(el, selector).forEach(function (match) {
                    dom[value ? 'show' : 'hide'](match, mode);
                });
            };
        }
    } else if (type === 'switch') {
        if (!binding.cases) throw Error('switch bindings must have "cases"');
        return partial(switchHandler, binding);
    } else if (type === 'innerHTML') {
        return function (el, value) {
            getMatches(el, selector).forEach(function (match) {
                dom.html(match, value);
            });
        };
    } else if (type === 'switchClass') {
        if (!binding.cases) throw Error('switchClass bindings must have "cases"');
        return function (el, value, keyName) {
            var name = makeArray(binding.name || keyName);
            for (var item in binding.cases) {
                getMatches(el, binding.cases[item]).forEach(function (match) {
                    name.forEach(function (className) {
                        dom[value === item ? 'addClass' : 'removeClass'](match, className);
                    });
                });
            }
        };
    } else if (type === 'switchAttribute') {
        if (!binding.cases) throw Error('switchAttribute bindings must have "cases"');
        return function (el, value, keyName) {
            getMatches(el, selector).forEach(function (match) {
                if (previousValue) {
                    removeAttributes(match, previousValue);
                }

                if (value in binding.cases) {
                    var attrs = binding.cases[value];
                    if (typeof attrs === 'string') {
                        attrs = {};
                        attrs[binding.name || keyName] = binding.cases[value];
                    }
                    setAttributes(match, attrs);

                    previousValue = attrs;
                }
            });
        };
    } else {
        throw new Error('no such binding type: ' + type);
    }
}

// returns a key-tree-store of functions
// that can be applied to any element/model.

// all resulting functions should be called
// like func(el, value, lastKeyName)
module.exports = function (bindings, context) {
    var store = new Store();
    var key, current;

    for (key in bindings) {
        current = bindings[key];
        if (typeof current === 'string') {
            store.add(key, getBindingFunc({
                type: 'text',
                selector: current
            }));
        } else if (current.forEach) {
            current.forEach(function (binding) {
                store.add(key, getBindingFunc(binding, context));
            });
        } else {
            store.add(key, getBindingFunc(current, context));
        }
    }

    return store;
};
<commit_msg>Refactor for PR as proposed on:<commit_after>/*$AMPERSAND_VERSION*/
var Store = require('key-tree-store');
var dom = require('ampersand-dom');
var matchesSelector = require('matches-selector');
var partial = require('lodash.partial');
var slice = Array.prototype.slice;

function getMatches(el, selector, firstOnly) {
    if (selector === '') return [el];
    var matches = [];
    if(!selector) return matches;
    if(firstOnly) {
        if (matchesSelector(el, selector)) return [el];
        return matches.concat(slice.call([el.querySelector(selector) || el]));
    }else{
        if (matchesSelector(el, selector)) matches.push(el);
        return matches.concat(slice.call(el.querySelectorAll(selector)));
    }
}
function setAttributes(el, attrs) {
    for (var name in attrs) {
        dom.setAttribute(el, name, attrs[name]);
    }
}

function removeAttributes(el, attrs) {
    for (var name in attrs) {
        dom.removeAttribute(el, name);
    }
}

function makeArray(val) {
    return Array.isArray(val) ? val : [val];
}

function switchHandler(binding, el, value) {
    // the element selector to show
    var showValue = binding.cases[value];
    // hide all the other elements with a different value
    for (var item in binding.cases) {
        var curValue = binding.cases[item];
        if (value !== item && curValue !== showValue) {
            getMatches(el, curValue, binding.firstMatchOnly).forEach(function (match) {
                dom.hide(match);
            });
        }
    }
    getMatches(el, showValue).forEach(function (match) {
        dom.show(match);
    });
}

function getSelector(binding) {
    if (typeof binding.selector === 'string') {
        return binding.selector;
    } else if (binding.hook) {
        return '[data-hook~="' + binding.hook + '"]';
    } else {
        return '';
    }
}

function getBindingFunc(binding, context) {
    var type = binding.type || 'text';
    var isCustomBinding = typeof type === 'function';
    var selector = getSelector(binding);
    var firstMatchOnly = binding.firstMatchOnly;
    var yes = binding.yes;
    var no = binding.no;
    var hasYesNo = !!(yes || no);

    // storage variable for previous if relevant
    var previousValue;

    if (isCustomBinding) {
        return function (el, value) {
            getMatches(el, selector, firstMatchOnly).forEach(function (match) {
                type.call(context, match, value, previousValue);
            });
            previousValue = value;
        };
    } else if (type === 'text') {
        return function (el, value) {
            getMatches(el, selector, firstMatchOnly).forEach(function (match) {
                dom.text(match, value);
            });
        };
    } else if (type === 'class') {
        return function (el, value) {
            getMatches(el, selector, firstMatchOnly).forEach(function (match) {
                dom.switchClass(match, previousValue, value);
            });
            previousValue = value;
        };
    } else if (type === 'attribute') {
        if (!binding.name) throw Error('attribute bindings must have a "name"');
        return function (el, value) {
            var names = makeArray(binding.name);
            getMatches(el, selector, firstMatchOnly).forEach(function (match) {
                names.forEach(function (name) {
                    dom.setAttribute(match, name, value);
                });
            });
            previousValue = value;
        };
    } else if (type === 'value') {
        return function (el, value) {
            getMatches(el, selector, firstMatchOnly).forEach(function (match) {
                if (!value && value !== 0) value = '';
                // only apply bindings if element is not currently focused
                if (document.activeElement !== match) match.value = value;
            });
            previousValue = value;
        };
    } else if (type === 'booleanClass') {
        // if there's a `no` case this is actually a switch
        if (hasYesNo) {
            yes = makeArray(yes || '');
            no = makeArray(no || '');
            return function (el, value) {
                var prevClass = value ? no : yes;
                var newClass = value ? yes : no;
                getMatches(el, selector, firstMatchOnly).forEach(function (match) {
                    prevClass.forEach(function (pc) {
                        dom.removeClass(match, pc);
                    });
                    newClass.forEach(function (nc) {
                        dom.addClass(match, nc);
                    });
                });
            };
        } else {
            return function (el, value, keyName) {
                var name = makeArray(binding.name || keyName);
                var invert = (binding.invert || false);
                value = (invert ? (value ? false : true) : value);
                getMatches(el, selector, firstMatchOnly).forEach(function (match) {
                    name.forEach(function (className) {
                        dom[value ? 'addClass' : 'removeClass'](match, className);
                    });
                });
            };
        }
    } else if (type === 'booleanAttribute') {
        // if there are `yes` and `no` selectors, this swaps between them
        if (hasYesNo) {
            yes = makeArray(yes || '');
            no = makeArray(no || '');
            return function (el, value) {
                var prevAttribute = value ? no : yes;
                var newAttribute = value ? yes : no;
                getMatches(el, selector, firstMatchOnly).forEach(function (match) {
                    prevAttribute.forEach(function (pa) {
                        if (pa) {
                            dom.removeAttribute(match, pa);
                        }
                    });
                    newAttribute.forEach(function (na) {
                        if (na) {
                            dom.addAttribute(match, na);
                        }
                    });
                });
            };
        } else {
            return function (el, value, keyName) {
                var name = makeArray(binding.name || keyName);
                var invert = (binding.invert || false);
                value = (invert ? (value ? false : true) : value);
                getMatches(el, selector, firstMatchOnly).forEach(function (match) {
                    name.forEach(function (attr) {
                        dom[value ? 'addAttribute' : 'removeAttribute'](match, attr);
                    });
                });
            };
        }
    } else if (type === 'toggle') {
        var mode = (binding.mode || 'display');
        var invert = (binding.invert || false);
        // this doesn't require a selector since we can pass yes/no selectors
        if (hasYesNo) {
            return function (el, value) {
                getMatches(el, yes, firstMatchOnly).forEach(function (match) {
                    dom[value ? 'show' : 'hide'](match, mode);
                });
                getMatches(el, no, firstMatchOnly).forEach(function (match) {
                    dom[value ? 'hide' : 'show'](match, mode);
                });
            };
        } else {
            return function (el, value) {
                value = (invert ? (value ? false : true) : value);
                getMatches(el, selector, firstMatchOnly).forEach(function (match) {
                    dom[value ? 'show' : 'hide'](match, mode);
                });
            };
        }
    } else if (type === 'switch') {
        if (!binding.cases) throw Error('switch bindings must have "cases"');
        return partial(switchHandler, binding);
    } else if (type === 'innerHTML') {
        return function (el, value) {
            getMatches(el, selector, firstMatchOnly).forEach(function (match) {
                dom.html(match, value);
            });
        };
    } else if (type === 'switchClass') {
        if (!binding.cases) throw Error('switchClass bindings must have "cases"');
        return function (el, value, keyName) {
            var name = makeArray(binding.name || keyName);
            for (var item in binding.cases) {
                getMatches(el, binding.cases[item], firstMatchOnly).forEach(function (match) {
                    name.forEach(function (className) {
                        dom[value === item ? 'addClass' : 'removeClass'](match, className);
                    });
                });
            }
        };
    } else if (type === 'switchAttribute') {
        if (!binding.cases) throw Error('switchAttribute bindings must have "cases"');
        return function (el, value, keyName) {
            getMatches(el, selector, firstMatchOnly).forEach(function (match) {
                if (previousValue) {
                    removeAttributes(match, previousValue);
                }

                if (value in binding.cases) {
                    var attrs = binding.cases[value];
                    if (typeof attrs === 'string') {
                        attrs = {};
                        attrs[binding.name || keyName] = binding.cases[value];
                    }
                    setAttributes(match, attrs);

                    previousValue = attrs;
                }
            });
        };
    } else {
        throw new Error('no such binding type: ' + type);
    }
}

// returns a key-tree-store of functions
// that can be applied to any element/model.

// all resulting functions should be called
// like func(el, value, lastKeyName)
module.exports = function (bindings, context) {
    var store = new Store();
    var key, current;

    for (key in bindings) {
        current = bindings[key];
        if (typeof current === 'string') {
            store.add(key, getBindingFunc({
                type: 'text',
                selector: current
            }));
        } else if (current.forEach) {
            current.forEach(function (binding) {
                store.add(key, getBindingFunc(binding, context));
            });
        } else {
            store.add(key, getBindingFunc(current, context));
        }
    }

    return store;
};
<|endoftext|>


<commit_before>/* Analytics code that needs to run before page load and analytics.ready */

if (!location.pathname.match(/^\/article/) && !sd.VERTICAL){
  debugger;
  PARSELY = {autotrack: false};
} /* Disable Parsely firing on non-article/vertical pages */
<commit_msg>Remove debugger :/<commit_after>/* Analytics code that needs to run before page load and analytics.ready */

if (!location.pathname.match(/^\/article/) && !sd.VERTICAL){
  PARSELY = {autotrack: false};
} /* Disable Parsely firing on non-article/vertical pages */
<|endoftext|>


<commit_before>/*

    Name: angular-gsapify-router
    Description: Angular UI-Router animation directive allowing configuration of [GSAP](http://www.greensock.com/gsap-js/) state transitions based on priority
    Author: jameshomer85@gmail.com
    Licence: MIT
    Usage: http://github.com/homerjam/angular-gsapify-router

*/
(function() {
    'use strict';

    angular.module('hj.gsapifyRouter', ['ngAnimate'])

    .constant('TweenMax', TweenMax)

    .provider('gsapifyRouter', function() {
        var self = this;

        self.transitions = {};

        self.transitions.slideFromAbove = {
            active: {
                duration: 1,
                cssOrigin: {
                    y: '-100%'
                },
                cssEnd: {
                    y: '0%'
                }
            },
            inactive: {
                duration: 1,
                cssOrigin: {
                    y: '100%'
                },
                cssEnd: {
                    y: '0%'
                }
            }
        };

        self.transitions.crossfade = {
            active: {
                duration: 0.5,
                cssOrigin: {
                    opacity: 0
                },
                cssEnd: {
                    opacity: 1
                }
            },
            inactive: {
                duration: 0.5,
                cssOrigin: {
                    opacity: 0
                },
                cssEnd: {
                    opacity: 1
                }
            }
        };

        self.transitions.fade = {
            active: {
                duration: 0.5,
                delay: 0.5,
                cssOrigin: {
                    opacity: 0
                },
                cssEnd: {
                    opacity: 1
                }
            },
            inactive: {
                duration: 0.5,
                cssOrigin: {
                    opacity: 0
                },
                cssEnd: {
                    opacity: 1
                }
            }
        };

        self.transitions.none = {
            active: {
                duration: 0,
                cssOrigin: {},
                cssEnd: {}
            },
            inactive: {
                duration: 0,
                cssOrigin: {},
                cssEnd: {}
            }
        };

        self.default = {
            transition: 'none',
            priority: 0
        };

        self.transition = function(transitionName, transitionOptions) {
            self.transitions[transitionName] = transitionOptions;
        };

        self.$get = ['$rootScope', '$state', '$document', '$timeout', '$q', 'TweenMax',
            function($rootScope, $state, $document, $timeout, $q, TweenMax) {
                var enter = function(element, duration) {
                    var deferred = $q.defer();

                    var currentOptions = self.default,
                        previousOptions = self.default,
                        current = $state.current,
                        previous = $state.previous;

                    if (current.data) {
                        if (current.data.gsapifyRouter) {
                            currentOptions = current.data.gsapifyRouter;
                        }
                    }

                    if (previous.data) {
                        if (previous.data.gsapifyRouter) {
                            previousOptions = previous.data.gsapifyRouter;
                        }
                    }

                    var transition = currentOptions.priority >= previousOptions.priority ?
                        self.transitions[currentOptions.transition].active : self.transitions[previousOptions.transition].inactive;

                    var from = {}, to = {};

                    from.css = transition.cssOrigin;
                    to.css = transition.cssEnd;

                    if (currentOptions.priority >= previousOptions.priority) {
                        to.delay = transition.delay || 0;
                    }

                    duration = duration !== undefined ? duration : transition.duration;

                    if (angular.equals(from.css, to.css) || Object.keys(to).length === 0) {
                        $timeout(deferred.resolve, duration * 1000);

                        return deferred.promise;
                    }

                    to.onComplete = function() {
                        deferred.resolve();
                    };

                    TweenMax.fromTo(element, duration, from, to);

                    return deferred.promise;
                };

                var leave = function(element, duration) {
                    var deferred = $q.defer();

                    var currentOptions = self.default,
                        previousOptions = self.default,
                        current = $state.current,
                        previous = $state.previous;

                    if (current.data) {
                        if (current.data.gsapifyRouter) {
                            currentOptions = current.data.gsapifyRouter;
                        }
                    }

                    if (previous.data) {
                        if (previous.data.gsapifyRouter) {
                            previousOptions = previous.data.gsapifyRouter;
                        }
                    }

                    var transition = previousOptions.priority >= currentOptions.priority ?
                        self.transitions[previousOptions.transition].active : self.transitions[currentOptions.transition].inactive;

                    var from = {}, to = {};

                    from.css = transition.cssEnd;
                    to.css = transition.cssOrigin;

                    if (previousOptions.priority >= currentOptions.priority) {
                        to.delay = transition.delay || 0;
                    }

                    duration = duration !== undefined ? duration : transition.duration;

                    if (angular.equals(from.css, to.css) || Object.keys(to).length === 0) {
                        $timeout(deferred.resolve, duration * 1000);

                        return deferred.promise;
                    }

                    to.onComplete = function() {
                        deferred.resolve();
                    };

                    TweenMax.fromTo(element, duration, from, to);

                    return deferred.promise;
                };

                return {
                    enter: enter,
                    leave: leave,
                    transitions: self.transitions,
                    default: self.default
                };
            }
        ];
    })

    .animation('.gsapify-router', ['gsapifyRouter',
        function(gsapifyRouter) {
            return {
                enter: function(element, done) {
                    gsapifyRouter.enter(element).then(function(){
                        done();
                    });

                    return function(cancelled) {
                        if (!cancelled) {

                        }
                    };
                },
                leave: function(element, done) {
                    gsapifyRouter.leave(element).then(function(){
                        done();
                    });
                }
            };
        }
    ]);

})();
<commit_msg>don't delay outgoing state<commit_after>/*

    Name: angular-gsapify-router
    Description: Angular UI-Router animation directive allowing configuration of [GSAP](http://www.greensock.com/gsap-js/) state transitions based on priority
    Author: jameshomer85@gmail.com
    Licence: MIT
    Usage: http://github.com/homerjam/angular-gsapify-router

*/
(function() {
    'use strict';

    angular.module('hj.gsapifyRouter', ['ngAnimate'])

    .constant('TweenMax', TweenMax)

    .provider('gsapifyRouter', function() {
        var self = this;

        self.transitions = {};

        self.transitions.slideFromAbove = {
            active: {
                duration: 1,
                cssOrigin: {
                    y: '-100%'
                },
                cssEnd: {
                    y: '0%'
                }
            },
            inactive: {
                duration: 1,
                cssOrigin: {
                    y: '100%'
                },
                cssEnd: {
                    y: '0%'
                }
            }
        };

        self.transitions.crossfade = {
            active: {
                duration: 0.5,
                cssOrigin: {
                    opacity: 0
                },
                cssEnd: {
                    opacity: 1
                }
            },
            inactive: {
                duration: 0.5,
                cssOrigin: {
                    opacity: 0
                },
                cssEnd: {
                    opacity: 1
                }
            }
        };

        self.transitions.fade = {
            active: {
                duration: 0.5,
                delay: 0.5,
                cssOrigin: {
                    opacity: 0
                },
                cssEnd: {
                    opacity: 1
                }
            },
            inactive: {
                duration: 0.5,
                cssOrigin: {
                    opacity: 0
                },
                cssEnd: {
                    opacity: 1
                }
            }
        };

        self.transitions.none = {
            active: {
                duration: 0,
                cssOrigin: {},
                cssEnd: {}
            },
            inactive: {
                duration: 0,
                cssOrigin: {},
                cssEnd: {}
            }
        };

        self.default = {
            transition: 'none',
            priority: 0
        };

        self.transition = function(transitionName, transitionOptions) {
            self.transitions[transitionName] = transitionOptions;
        };

        self.$get = ['$rootScope', '$state', '$document', '$timeout', '$q', 'TweenMax',
            function($rootScope, $state, $document, $timeout, $q, TweenMax) {
                var enter = function(element, duration) {
                    var deferred = $q.defer();

                    var currentOptions = self.default,
                        previousOptions = self.default,
                        current = $state.current,
                        previous = $state.previous;

                    if (current.data) {
                        if (current.data.gsapifyRouter) {
                            currentOptions = current.data.gsapifyRouter;
                        }
                    }

                    if (previous.data) {
                        if (previous.data.gsapifyRouter) {
                            previousOptions = previous.data.gsapifyRouter;
                        }
                    }

                    var transition = currentOptions.priority >= previousOptions.priority ?
                        self.transitions[currentOptions.transition].active : self.transitions[previousOptions.transition].inactive;

                    var from = {}, to = {};

                    from.css = transition.cssOrigin;
                    to.css = transition.cssEnd;

                    if (currentOptions.priority >= previousOptions.priority) {
                        to.delay = transition.delay || 0;
                    }

                    duration = duration !== undefined ? duration : transition.duration;

                    if (angular.equals(from.css, to.css) || Object.keys(to).length === 0) {
                        $timeout(deferred.resolve, duration * 1000);

                        return deferred.promise;
                    }

                    to.onComplete = function() {
                        deferred.resolve();
                    };

                    TweenMax.fromTo(element, duration, from, to);

                    return deferred.promise;
                };

                var leave = function(element, duration) {
                    var deferred = $q.defer();

                    var currentOptions = self.default,
                        previousOptions = self.default,
                        current = $state.current,
                        previous = $state.previous;

                    if (current.data) {
                        if (current.data.gsapifyRouter) {
                            currentOptions = current.data.gsapifyRouter;
                        }
                    }

                    if (previous.data) {
                        if (previous.data.gsapifyRouter) {
                            previousOptions = previous.data.gsapifyRouter;
                        }
                    }

                    var transition = previousOptions.priority > currentOptions.priority ?
                        self.transitions[previousOptions.transition].active : self.transitions[currentOptions.transition].inactive;

                    var from = {}, to = {};

                    from.css = transition.cssEnd;
                    to.css = transition.cssOrigin;

                    if (previousOptions.priority > currentOptions.priority) {
                        to.delay = transition.delay || 0;
                    }

                    duration = duration !== undefined ? duration : transition.duration;

                    if (angular.equals(from.css, to.css) || Object.keys(to).length === 0) {
                        $timeout(deferred.resolve, duration * 1000);

                        return deferred.promise;
                    }

                    to.onComplete = function() {
                        deferred.resolve();
                    };

                    TweenMax.fromTo(element, duration, from, to);

                    return deferred.promise;
                };

                return {
                    enter: enter,
                    leave: leave,
                    transitions: self.transitions,
                    default: self.default
                };
            }
        ];
    })

    .animation('.gsapify-router', ['gsapifyRouter',
        function(gsapifyRouter) {
            return {
                enter: function(element, done) {
                    gsapifyRouter.enter(element).then(function(){
                        done();
                    });

                    return function(cancelled) {
                        if (!cancelled) {

                        }
                    };
                },
                leave: function(element, done) {
                    gsapifyRouter.leave(element).then(function(){
                        done();
                    });
                }
            };
        }
    ]);

})();
<|endoftext|>


<commit_before>import {
  SELECT_LANGUAGE,
  FINISH_TUTORIAL,
  FINISH_PRIVACY,
  FINISH_SPVCHOICE,
  DAEMONSTART_ATTEMPT,
  DAEMONSTART_SUCCESS,
  CONNECTDAEMON_ATTEMPT,
  CONNECTDAEMON_SUCCESS,
  CONNECTDAEMON_FAILURE,
  DAEMONSYNCING_START,
  DAEMONSYNCING_PROGRESS,
  DAEMONSYNCED,
  DAEMONSTOPPED,
  WALLETREADY,
  SHUTDOWN_REQUESTED,
  AVAILABLE_WALLETS,
  DECREDITON_VERSION,
  DAEMON_ERROR,
  DAEMON_WARNING,
  WALLET_WARNING,
  CLOSEDAEMON_ATTEMPT,
  CLOSEDAEMON_FAILED,
  CLOSEDAEMON_SUCCESS,
  CHECK_NETWORKMATCH_ATTEMPT,
  CHECK_NETWORKMATCH_SUCCESS,
  CHECK_NETWORKMATCH_FAILED
} from "../actions/DaemonActions";
import {
  CLOSEWALLET_SUCCESS,
  CLOSEWALLET_FAILED
} from "../actions/WalletLoaderActions";
import { UPDATEHIDDENACCOUNTS } from "../actions/ClientActions";

export default function version(state = {}, action) {
  switch (action.type) {
    case DECREDITON_VERSION:
      return { ...state, updateAvailable: action.msg };
    case SELECT_LANGUAGE:
      return { ...state, locale: action.language, setLanguage: false };
    case FINISH_TUTORIAL:
      return { ...state, tutorial: false };
    case FINISH_SPVCHOICE:
      return { ...state, showSpvChoice: false };
    case FINISH_PRIVACY:
      return { ...state, showPrivacy: false };
    case DAEMONSTART_ATTEMPT:
      return {
        ...state,
        // we consider it as started here, because dcrd can start a long process
        // like upgrading its db, before having valid peers (which is when we consider)
        // dcrd as started and ready to run.
        daemonStarting: true
      };
    case DAEMONSTART_SUCCESS:
      return {
        ...state,
        daemonStarted: true,
        daemonStopped: false,
        credentials: action.credentials,
        daemonRemote: action.daemonRemote,
        appdata: action.appdata,
        daemonError: null
      };
    case CONNECTDAEMON_ATTEMPT:
      return { ...state, daemonConnected: false, daemonError: null };
    case CONNECTDAEMON_SUCCESS:
      return { ...state, daemonConnected: true, daemonError: null };
    case CONNECTDAEMON_FAILURE:
      return {
        ...state,
        daemonConnected: false,
        daemonError: action.error,
        daemonTimeout: action.daemonTimeout
      };
    case CLOSEDAEMON_ATTEMPT:
      return { ...state, daemonCloseRequestAttempt: true };
    case CLOSEDAEMON_FAILED:
      return {
        ...state,
        daemonCloseError: String(action.error),
        daemonCloseRequestAttempt: false
      };
    case CLOSEDAEMON_SUCCESS:
      return {
        ...state,
        daemonCloseError: null,
        daemonCloseRequestAttempt: false,
        daemonCloseResponse: action.response,
        daemonStarted: false,
        daemonStopped: true,
        credentials: null,
        appdata: null,
        daemonSynced: false,
        currentBlockCount: null,
        timeLeftEstimate: null,
        timeStart: null,
        blockStart: null
      };
    case DAEMONSYNCING_START:
      return {
        ...state,
        daemonStarted: true,
        currentBlockCount: action.currentBlockCount,
        timeStart: action.timeStart,
        blockStart: action.blockStart,
        neededBlocks: action.syncHeight,
        daemonWarning: null
      };
    case DAEMONSYNCING_PROGRESS:
      return {
        ...state,
        currentBlockCount: action.currentBlockCount,
        timeLeftEstimate: action.timeLeftEstimate,
        neededBlocks: action.syncHeight
      };
    case DAEMONSYNCED:
      return {
        ...state,
        neededBlocks: action.syncHeight,
        currentBlockCount: action.blockCount,
        daemonSynced: true,
        daemonWarning: null
      };
    case WALLETREADY:
      return {
        ...state,
        selectCreateWalletInputRequest: false,
        walletReady: true,
        walletName: action.walletName,
        hiddenAccounts: action.hiddenAccounts
      };
    case SHUTDOWN_REQUESTED:
      return { ...state, shutdownRequested: true };
    case DAEMONSTOPPED:
      return { ...state, daemonStarted: false, daemonStopped: true };
    case AVAILABLE_WALLETS:
      return {
        ...state,
        availableWallets: action.availableWallets,
        previousWallet: action.previousWallet,
        selectCreateWalletInputRequest: !action.previousWallet
      };
    case UPDATEHIDDENACCOUNTS:
      return {
        ...state,
        hiddenAccounts: action.hiddenAccounts
      };
    case DAEMON_ERROR:
      return {
        ...state,
        daemonError: action.error
      };
    case DAEMON_WARNING:
      return {
        ...state,
        daemonWarning: action.warning
      };
    case WALLET_WARNING:
      return {
        ...state,
        walletWarning: action.warning
      };
    case CLOSEWALLET_SUCCESS:
      return {
        ...state,
        hiddenAccounts: [],
        walletReady: false,
        walletName: null,
        daemonWarning: null
      };
    case CLOSEWALLET_FAILED:
      return {
        ...state,
        walletError: action.error
      };
    case CHECK_NETWORKMATCH_ATTEMPT:
      return { ...state, daemonError: null, networkMatch: null };
    case CHECK_NETWORKMATCH_SUCCESS:
      return { ...state, networkMatch: true, daemonError: null };
    case CHECK_NETWORKMATCH_FAILED:
      return { ...state, daemonError: action.error };
    default:
      return state;
  }
}
<commit_msg>[launcher] fix dcrd not starting after daemon started once (#2836)<commit_after>import {
  SELECT_LANGUAGE,
  FINISH_TUTORIAL,
  FINISH_PRIVACY,
  FINISH_SPVCHOICE,
  DAEMONSTART_ATTEMPT,
  DAEMONSTART_SUCCESS,
  CONNECTDAEMON_ATTEMPT,
  CONNECTDAEMON_SUCCESS,
  CONNECTDAEMON_FAILURE,
  DAEMONSYNCING_START,
  DAEMONSYNCING_PROGRESS,
  DAEMONSYNCED,
  DAEMONSTOPPED,
  WALLETREADY,
  SHUTDOWN_REQUESTED,
  AVAILABLE_WALLETS,
  DECREDITON_VERSION,
  DAEMON_ERROR,
  DAEMON_WARNING,
  WALLET_WARNING,
  CLOSEDAEMON_ATTEMPT,
  CLOSEDAEMON_FAILED,
  CLOSEDAEMON_SUCCESS,
  CHECK_NETWORKMATCH_ATTEMPT,
  CHECK_NETWORKMATCH_SUCCESS,
  CHECK_NETWORKMATCH_FAILED
} from "../actions/DaemonActions";
import {
  CLOSEWALLET_SUCCESS,
  CLOSEWALLET_FAILED
} from "../actions/WalletLoaderActions";
import { UPDATEHIDDENACCOUNTS } from "../actions/ClientActions";

export default function version(state = {}, action) {
  switch (action.type) {
    case DECREDITON_VERSION:
      return { ...state, updateAvailable: action.msg };
    case SELECT_LANGUAGE:
      return { ...state, locale: action.language, setLanguage: false };
    case FINISH_TUTORIAL:
      return { ...state, tutorial: false };
    case FINISH_SPVCHOICE:
      return { ...state, showSpvChoice: false };
    case FINISH_PRIVACY:
      return { ...state, showPrivacy: false };
    case DAEMONSTART_ATTEMPT:
      return {
        ...state,
        // we consider it as started here, because dcrd can start a long process
        // like upgrading its db, before having valid peers (which is when we consider)
        // dcrd as started and ready to run.
        daemonStarting: true
      };
    case DAEMONSTART_SUCCESS:
      return {
        ...state,
        daemonStarted: true,
        daemonStopped: false,
        credentials: action.credentials,
        daemonRemote: action.daemonRemote,
        appdata: action.appdata,
        daemonError: null
      };
    case CONNECTDAEMON_ATTEMPT:
      return { ...state, daemonConnected: false, daemonError: null };
    case CONNECTDAEMON_SUCCESS:
      return { ...state, daemonConnected: true, daemonError: null };
    case CONNECTDAEMON_FAILURE:
      return {
        ...state,
        daemonConnected: false,
        daemonError: action.error,
        daemonTimeout: action.daemonTimeout
      };
    case CLOSEDAEMON_ATTEMPT:
      return { ...state, daemonCloseRequestAttempt: true };
    case CLOSEDAEMON_FAILED:
      return {
        ...state,
        daemonCloseError: String(action.error),
        daemonCloseRequestAttempt: false
      };
    case CLOSEDAEMON_SUCCESS:
      return {
        ...state,
        daemonCloseError: null,
        daemonCloseRequestAttempt: false,
        daemonCloseResponse: action.response,
        daemonStarted: false,
        daemonStarting: false,
        daemonStopped: true,
        credentials: null,
        appdata: null,
        daemonSynced: false,
        currentBlockCount: null,
        timeLeftEstimate: null,
        timeStart: null,
        blockStart: null
      };
    case DAEMONSYNCING_START:
      return {
        ...state,
        daemonStarted: true,
        currentBlockCount: action.currentBlockCount,
        timeStart: action.timeStart,
        blockStart: action.blockStart,
        neededBlocks: action.syncHeight,
        daemonWarning: null
      };
    case DAEMONSYNCING_PROGRESS:
      return {
        ...state,
        currentBlockCount: action.currentBlockCount,
        timeLeftEstimate: action.timeLeftEstimate,
        neededBlocks: action.syncHeight
      };
    case DAEMONSYNCED:
      return {
        ...state,
        neededBlocks: action.syncHeight,
        currentBlockCount: action.blockCount,
        daemonSynced: true,
        daemonWarning: null
      };
    case WALLETREADY:
      return {
        ...state,
        selectCreateWalletInputRequest: false,
        walletReady: true,
        walletName: action.walletName,
        hiddenAccounts: action.hiddenAccounts
      };
    case SHUTDOWN_REQUESTED:
      return { ...state, shutdownRequested: true };
    case DAEMONSTOPPED:
      return {
        ...state,
        daemonStarted: false,
        daemonStarting: false,
        daemonStopped: true
      };
    case AVAILABLE_WALLETS:
      return {
        ...state,
        availableWallets: action.availableWallets,
        previousWallet: action.previousWallet,
        selectCreateWalletInputRequest: !action.previousWallet
      };
    case UPDATEHIDDENACCOUNTS:
      return {
        ...state,
        hiddenAccounts: action.hiddenAccounts
      };
    case DAEMON_ERROR:
      return {
        ...state,
        daemonError: action.error
      };
    case DAEMON_WARNING:
      return {
        ...state,
        daemonWarning: action.warning
      };
    case WALLET_WARNING:
      return {
        ...state,
        walletWarning: action.warning
      };
    case CLOSEWALLET_SUCCESS:
      return {
        ...state,
        hiddenAccounts: [],
        walletReady: false,
        walletName: null,
        daemonWarning: null
      };
    case CLOSEWALLET_FAILED:
      return {
        ...state,
        walletError: action.error
      };
    case CHECK_NETWORKMATCH_ATTEMPT:
      return { ...state, daemonError: null, networkMatch: null };
    case CHECK_NETWORKMATCH_SUCCESS:
      return { ...state, networkMatch: true, daemonError: null };
    case CHECK_NETWORKMATCH_FAILED:
      return { ...state, daemonError: action.error };
    default:
      return state;
  }
}
<|endoftext|>


<commit_before>var User = require('../lib/users');

module.exports = function (server) {

  server.post('/messages', function (req, res, next) {
    var phoneNumber = req.params.From;
    var message = req.params.Body;
    var responseMessage = '';

    console.log('Received');

    User.findOrCreate(phoneNumber, function (err, user) {

      if (err) { res.send(500, err), process.stdout.write(err) };

      responseMessage = user.status === 'Hello, new friend.' : 'Welcome back, old friend.';

      user.message(responseMessage, function () {
        console.log('Message (theoretically) sent.');
        res.send(200, { from: phoneNumber, user: user, response: responseMessage });
      });

    });
  });

};<commit_msg>Simplify a stupid trick I never should have used<commit_after>var User = require('../lib/users');

module.exports = function (server) {

  server.post('/messages', function (req, res, next) {
    var phoneNumber = req.params.From;
    var message = req.params.Body;
    var responseMessage = '';

    console.log('Received');

    User.findOrCreate(phoneNumber, function (err, user) {

      if (err) { res.send(500, err), process.stdout.write(err) };

      responseMessage = user.status ? 'Hello, new friend.' : 'Welcome back, old friend.';

      user.message(responseMessage, function () {
        console.log('Message (theoretically) sent.');
        res.send(200, { from: phoneNumber, user: user, response: responseMessage });
      });

    });
  });

};<|endoftext|>


<commit_before>(function (container) {
  'use strict';

  const OTHERS_KEY = 'Others';
  const MIN_USAGE_THRESHOLD = 5.0;

  /* eslint-disable camelcase */
  const BROWSERS = {
    ie: 'Internet Explorer',
    ios_saf: 'Safari (iOS)',
    op_mini: 'Opera Mini',
    and_chr: 'Chrome (Android)',
    and_uc: 'UC Browser (Android)'
  };
  /* eslint-enable camelcase */

  function handleFetchErrors(response) {
    if (!response.ok) {
      return Promise.reject(new Error(response.statusText));
    }
    return Promise.resolve(response);
  }

  let capitalizeFirst = str => str.substr(0, 1).toUpperCase() + str.substr(1);
  let sum = arr => arr.reduce((x, y) => (x || 0) + (y || 0));

  class CaniuseReport {
    constructor(feature, supportData, browserUsage) {
      this.$browserUsage = browserUsage;

      this.feature = feature;

      let allBrowsers = this.$compileBrowserReports(supportData);
      this.browsers = [...this.$rollupRarelyUsedBrowsers(allBrowsers)].reverse();
    }

    $compileBrowserReports(supportData) {
      let browserStats = (supportData || {}).stats;
      return Object.keys(browserStats)
        .map(browserKey => this.$getBrowserReport(browserKey, browserStats[browserKey], this.$browserUsage.usageOf(browserKey)));
    }

    $rollupRarelyUsedBrowsers(browsers) {
      let rollup = {
        browserName: OTHERS_KEY,
        noSupport: {share: 0},
        partialSupport: {share: 0},
        hasSupport: {share: 0}
      };

      let result = [];

      for (let report of browsers) {
        if (this.$browserUsage.isAboveThreshold(report.browserKey)) {
          result.push(report);
        } else {
          rollup.noSupport.share += report.noSupport.share || 0;
          rollup.partialSupport.share += report.partialSupport.share || 0;
          rollup.hasSupport.share += report.hasSupport.share || 0;
        }
      }

      result.push(rollup);
      return result;
    }

    static $normalizeSupportFlag(key) {
      return ['n', 'y'].indexOf(key) !== -1 ? key : 'p';
    }

    $getBrowserReport(browserKey, browserVersions, versionsUsage) {
      let info = {};

      // workaround for https://github.com/Fyrd/caniuse/issues/1939
      let useSingleVersionWorkaround = Object.keys(browserVersions).length === 1;

      for (let version of Object.keys(browserVersions)) {
        let flag = CaniuseReport.$normalizeSupportFlag(browserVersions[version]);

        // collect total share values
        info[flag] = info[flag] || {min: version, max: version, share: 0};
        info[flag].share += versionsUsage[version] || (useSingleVersionWorkaround && versionsUsage['0']) || 0;

        // find min and max version with given support flag
        if (compareVersions(info[flag].min, version) === 1) {
          info[flag].min = version;
        } else if (compareVersions(info[flag].max, version) === -1) {
          info[flag].max = version;
        }
      }

      return {
        browserKey,
        browserName: BROWSERS[browserKey] || capitalizeFirst(browserKey),
        noSupport: info.n || {},
        partialSupport: info.p || {},
        hasSupport: info.y || {}
      };
    }

    static $seriesValue(label, supportData) {
      let series = {value: 0, meta: label};

      if (supportData) {
        if (supportData.share) {
          series.value += supportData.share;
        }
        if (supportData.min && supportData.max) {
          if (supportData.min === supportData.max) {
            series.meta += ` in version ${supportData.min}`;
          } else {
            series.meta += ` in versions ${supportData.min} - ${supportData.max}`;
          }
        }
      }

      return series;
    }

    $initBrowsersChart(selector) {
      let chartData = {
        labels: this.browsers.map(browserInfo => browserInfo.browserName),
        series: [
          this.browsers.map(browserInfo => CaniuseReport.$seriesValue('No support', browserInfo.noSupport)),
          this.browsers.map(browserInfo => CaniuseReport.$seriesValue('Partial support', browserInfo.partialSupport)),
          this.browsers.map(browserInfo => CaniuseReport.$seriesValue('Supported', browserInfo.hasSupport))
        ]
      };

      let chartOptions = {
        horizontalBars: true,
        stackBars: true,
        plugins: [
          Chartist.plugins.tooltip({
            tooltipFnc: (meta, value) => `${meta}<br/>Global market share: ${parseFloat(value).toFixed(2)}%`
          }),
          Chartist.plugins.ctAxisTitle({
            axisX: {
              axisTitle: 'Global market share (%)',
              offset: {x: 0, y: 30}
            }
          })
        ],
        axisY: {
          showGrid: false
        }
      };

      return new Chartist.Bar(selector, chartData, chartOptions);
    }

    $initOverallChart(selector) {
      let shares = [
        sum(this.browsers.map(b => b.noSupport.share)),
        sum(this.browsers.map(b => b.partialSupport.share)),
        sum(this.browsers.map(b => b.hasSupport.share))
      ];

      let createLabel = (info, share) => share > 0 ? `${info} - ${share.toFixed(2)}%` : '';

      let chartData = {
        series: shares,
        labels: [
          createLabel('No support', shares[0]),
          createLabel('Partial support', shares[1]),
          createLabel('Supported', shares[2])
        ]
      };

      return new Chartist.Pie(selector, chartData);
    }

    initVisuals() {
      this.$initBrowsersChart('.browsers-chart');
      this.$initOverallChart('.overall-chart');
    }
  }

  class CaniuseBrowserUsage {
    constructor(rawData = {}) {
      this.$data = rawData.data || {};
    }

    usageOf(browser) {
      return this.$data[browser];
    }

    isAboveThreshold(browser) {
      return sum(Object.values(this.$data[browser])) >= MIN_USAGE_THRESHOLD;
    }
  }

  let fetchCaniuseBrowserUsage = memoize(() => {
    return fetch('https://raw.githubusercontent.com/Fyrd/caniuse/master/region-usage-json/alt-ww.json')
      .then(result => handleFetchErrors(result))
      .then(result => result.json())
      .then(data => new CaniuseBrowserUsage(data));
  });

  class CaniuseReportFetch {
    constructor(feature) {
      this.$feature = feature;
    }

    fetch() {
      if (this.$feature.caniuseReport) {
        return new Promise(resolve => resolve()); // run once
      }

      let caniuseFeatureReport = fetch(`https://raw.githubusercontent.com/Fyrd/caniuse/master/features-json/${this.$feature.caniuseKey}.json`)
        .then(result => handleFetchErrors(result))
        .then(result => result.json());

      return Promise.all([caniuseFeatureReport, fetchCaniuseBrowserUsage()])
        .then(([featureReport, usageReport]) => {
          Object.defineProperty(this.$feature, 'caniuseReport', {
            enumerable: false,
            value: new CaniuseReport(this.$feature.caniuseKey, featureReport, usageReport)
          });
        })
        .catch(err => {
          console.warn(err);
          throw err;
        });
    }
  }

  container.configure(register => register.singleton('CaniuseReportFetch', CaniuseReportFetch));

})(WWCD.container);
<commit_msg>Fix for empty values shown in caniuse pie charts<commit_after>(function (container) {
  'use strict';

  const OTHERS_KEY = 'Others';
  const MIN_USAGE_THRESHOLD = 5.0;

  /* eslint-disable camelcase */
  const BROWSERS = {
    ie: 'Internet Explorer',
    ios_saf: 'Safari (iOS)',
    op_mini: 'Opera Mini',
    and_chr: 'Chrome (Android)',
    and_uc: 'UC Browser (Android)'
  };
  /* eslint-enable camelcase */

  function handleFetchErrors(response) {
    if (!response.ok) {
      return Promise.reject(new Error(response.statusText));
    }
    return Promise.resolve(response);
  }

  let capitalizeFirst = str => str.substr(0, 1).toUpperCase() + str.substr(1);
  let sum = arr => arr.reduce((x, y) => (x || 0) + (y || 0));

  class CaniuseReport {
    constructor(feature, supportData, browserUsage) {
      this.$browserUsage = browserUsage;

      this.feature = feature;

      let allBrowsers = this.$compileBrowserReports(supportData);
      this.browsers = [...this.$rollupRarelyUsedBrowsers(allBrowsers)].reverse();
    }

    $compileBrowserReports(supportData) {
      let browserStats = (supportData || {}).stats;
      return Object.keys(browserStats)
        .map(browserKey => this.$getBrowserReport(browserKey, browserStats[browserKey], this.$browserUsage.usageOf(browserKey)));
    }

    $rollupRarelyUsedBrowsers(browsers) {
      let rollup = {
        browserName: OTHERS_KEY,
        noSupport: {share: 0},
        partialSupport: {share: 0},
        hasSupport: {share: 0}
      };

      let result = [];

      for (let report of browsers) {
        if (this.$browserUsage.isAboveThreshold(report.browserKey)) {
          result.push(report);
        } else {
          rollup.noSupport.share += report.noSupport.share || 0;
          rollup.partialSupport.share += report.partialSupport.share || 0;
          rollup.hasSupport.share += report.hasSupport.share || 0;
        }
      }

      result.push(rollup);
      return result;
    }

    static $normalizeSupportFlag(key) {
      return ['n', 'y'].indexOf(key) !== -1 ? key : 'p';
    }

    $getBrowserReport(browserKey, browserVersions, versionsUsage) {
      let info = {};

      // workaround for https://github.com/Fyrd/caniuse/issues/1939
      let useSingleVersionWorkaround = Object.keys(browserVersions).length === 1;

      for (let version of Object.keys(browserVersions)) {
        let flag = CaniuseReport.$normalizeSupportFlag(browserVersions[version]);

        // collect total share values
        info[flag] = info[flag] || {min: version, max: version, share: 0};
        info[flag].share += versionsUsage[version] || (useSingleVersionWorkaround && versionsUsage['0']) || 0;

        // find min and max version with given support flag
        if (compareVersions(info[flag].min, version) === 1) {
          info[flag].min = version;
        } else if (compareVersions(info[flag].max, version) === -1) {
          info[flag].max = version;
        }
      }

      return {
        browserKey,
        browserName: BROWSERS[browserKey] || capitalizeFirst(browserKey),
        noSupport: info.n || {},
        partialSupport: info.p || {},
        hasSupport: info.y || {}
      };
    }

    static $seriesValue(label, supportData) {
      let series = {value: 0, meta: label};

      if (supportData) {
        if (supportData.share) {
          series.value += supportData.share;
        }
        if (supportData.min && supportData.max) {
          if (supportData.min === supportData.max) {
            series.meta += ` in version ${supportData.min}`;
          } else {
            series.meta += ` in versions ${supportData.min} - ${supportData.max}`;
          }
        }
      }

      return series;
    }

    $initBrowsersChart(selector) {
      let chartData = {
        labels: this.browsers.map(browserInfo => browserInfo.browserName),
        series: [
          this.browsers.map(browserInfo => CaniuseReport.$seriesValue('No support', browserInfo.noSupport)),
          this.browsers.map(browserInfo => CaniuseReport.$seriesValue('Partial support', browserInfo.partialSupport)),
          this.browsers.map(browserInfo => CaniuseReport.$seriesValue('Supported', browserInfo.hasSupport))
        ]
      };

      let chartOptions = {
        horizontalBars: true,
        stackBars: true,
        plugins: [
          Chartist.plugins.tooltip({
            tooltipFnc: (meta, value) => `${meta}<br/>Global market share: ${parseFloat(value).toFixed(2)}%`
          }),
          Chartist.plugins.ctAxisTitle({
            axisX: {
              axisTitle: 'Global market share (%)',
              offset: {x: 0, y: 30}
            }
          })
        ],
        axisY: {
          showGrid: false
        }
      };

      return new Chartist.Bar(selector, chartData, chartOptions);
    }

    $initOverallChart(selector) {
      let shares = [
        sum(this.browsers.map(b => b.noSupport.share)),
        sum(this.browsers.map(b => b.partialSupport.share)),
        sum(this.browsers.map(b => b.hasSupport.share))
      ];

      let createLabel = (info, share) => share > 0 ? `${info} - ${share.toFixed(2)}%` : '';

      let chartData = {
        series: shares,
        labels: [
          createLabel('No support', shares[0]),
          createLabel('Partial support', shares[1]),
          createLabel('Supported', shares[2])
        ]
      };

      return new Chartist.Pie(selector, chartData, {ignoreEmptyValues: true});
    }

    initVisuals() {
      this.$initBrowsersChart('.browsers-chart');
      this.$initOverallChart('.overall-chart');
    }
  }

  class CaniuseBrowserUsage {
    constructor(rawData = {}) {
      this.$data = rawData.data || {};
    }

    usageOf(browser) {
      return this.$data[browser];
    }

    isAboveThreshold(browser) {
      return sum(Object.values(this.$data[browser])) >= MIN_USAGE_THRESHOLD;
    }
  }

  let fetchCaniuseBrowserUsage = memoize(() => {
    return fetch('https://raw.githubusercontent.com/Fyrd/caniuse/master/region-usage-json/alt-ww.json')
      .then(result => handleFetchErrors(result))
      .then(result => result.json())
      .then(data => new CaniuseBrowserUsage(data));
  });

  class CaniuseReportFetch {
    constructor(feature) {
      this.$feature = feature;
    }

    fetch() {
      if (this.$feature.caniuseReport) {
        return new Promise(resolve => resolve()); // run once
      }

      let caniuseFeatureReport = fetch(`https://raw.githubusercontent.com/Fyrd/caniuse/master/features-json/${this.$feature.caniuseKey}.json`)
        .then(result => handleFetchErrors(result))
        .then(result => result.json());

      return Promise.all([caniuseFeatureReport, fetchCaniuseBrowserUsage()])
        .then(([featureReport, usageReport]) => {
          Object.defineProperty(this.$feature, 'caniuseReport', {
            enumerable: false,
            value: new CaniuseReport(this.$feature.caniuseKey, featureReport, usageReport)
          });
        })
        .catch(err => {
          console.warn(err);
          throw err;
        });
    }
  }

  container.configure(register => register.singleton('CaniuseReportFetch', CaniuseReportFetch));

})(WWCD.container);
<|endoftext|>


<commit_before>'use strict';

angular.module('Lunch.profile', ['openfb', 'Lunch.factory.Geo', 'Lunch.factory.requests', 'Lunch.service.matchData'])
.config(function($stateProvider) {
  $stateProvider
  .state('app.profile', {
    url: '/profile',
    views: {
      'menuContent' :{
        templateUrl: 'templates/profile.html',
        controller: 'ProfileCtrl'
      }
    }
  });
})

.controller('ProfileCtrl', function($q, $rootScope, $scope, $ionicSlideBoxDelegate, $window, storedUserData, OpenFB, Geo, localStore, requests, matchData) {
  // Store data in scope
  $scope.userData = storedUserData;

  $scope.getLikes = function() {
    OpenFB.get('/me/likes')
      .success(function(fbLikeObj){
        // need to keep track of old ids
        var idTrack = {};
        angular.forEach(fbLikeObj.data, function(value){
          //if a new like / id
          if(value.name){
            //inform the database if a new id
            //add the new id and like data locally
            $scope.userData.likes[value.id] = value.name;

            postLikes(value);
          }
          //track id
          idTrack[value.id] = true;
        });
        //check ids fetched from fb to local ids.  if like stored locally no longer
        //avaiable from fb, inform the db and (then) delete locally
        for(var like in $scope.userData.likes) {
          if(!idTrack[like]){
            console.info('Deleteing like: ' + like + '; no longer in facebook');
            requests.deleteLike(like.id, {'userId': $scope.userData.id});
            delete $scope.userData.likes[like]; // since the like no longer exists
            //inform database using like.id and user.id and like.name ($scope.userData.likes[likeId])
          }
        }
      $rootScope.$emit('userDataChanged', $scope.userData);
      });
  };

  var postLikes = function(like) {
    requests.postLike({
      'userId' : $scope.userData.id,
      'id': like.id,
      'name': like.name
    });
  };

  var postTag = function(tagName) {
    requests.postTag({
      'userId' : $scope.userData.id,
      'id': tagName
    });
  };

  var postTags = function() {
    angular.forEach(storedUserData.tags, function(value, key){
        // only post tags that are pressed currently
        if(value){
          postTag(key);
        }
    });
  };

  var deleteTag = function(tagName) {
    requests.deleteTag({
      'userId' : $scope.userData.id,
      'id': tagName
    });
  };

  var getPicture = function() {
    OpenFB.get('/me/picture?redirect=0&height=133&type=normal&width=100')//'/me/picture')
    .success(function(data){
      if(data !== $scope.userData.photo_url){
        var image = "

";
        angular.element(document.querySelector('#userimage')).html(image);
        $scope.userData.photo_url = data.data.url;
        //tell the database the image associated with the user has changed
        postUser();
        $rootScope.$emit('userDataChanged', $scope.userData);
      }
    });
  };

  var getDetails = function() {
    var deferredPost = $q.defer();

    if ($scope.userData.id) {
      deferredPost.resolve();
    } else {
      OpenFB.get('/me')
      .success(function(data){
        angular.extend($scope.userData, data);
        //store updates to data locally
        $rootScope.$emit('userDataChanged', $scope.userData);
        deferredPost.resolve();
      })
      .error(function(err){
        $window.alert('Unable to reach Facebook');
        deferredPost.reject();
      });
    }

    return deferredPost.promise;
  };

  $scope.tagClick = function(e){
    var clickedText = e.toElement.innerText;
    var pressed = $scope.userData.tags[clickedText];
    // toggle pressed state
    if(pressed){
      // TODO - delete Tag when unpressed
      deleteTag(clickedText);
      $scope.userData.tags[clickedText] = false;
    } else {
      postTag(clickedText);
      $scope.userData.tags[clickedText] = true;
    }
    $rootScope.$emit('userDataChanged', $scope.userData);
  };

  var postUser = function(){
    return getDetails().then(function() {
      return requests.postBasicDetails({
        'id' : $scope.userData.id,
        'firstname': $scope.userData.first_name,
        'lastname': $scope.userData.last_name,
        'profileImage': $scope.userData.photo_url
      });
    });
  };

  var postLocation = function(pos) {
    $scope.userData.geolocation = pos.coords;
      OpenFB.checkLogin().then(function(id) {
        requests.postLocation({
          'userId': id,
          'lat': pos.coords.latitude,
          'lng': pos.coords.longitude
        }).then(function(res) {
          console.info('You are in ' + angular.fromJson(res).data.city);
          $scope.userData.location = angular.fromJson(res).data.city;
          $rootScope.$emit('userDataChanged', $scope.userData);
        });
    });
  };

  $scope.$on('$stateChangeSuccess', function(e, state) { // this triggers every time we go to the profile page, may need something else
    postUser().then(function() {
      getPicture();
      $scope.getLikes();

      //post tags on initialisation
      postTags();

      Geo.getCurrentPosition()
        .then(function(pos) { postLocation(pos); })
        .catch(function(err) { console.error(err); });
      });
  });
});
<commit_msg>Renamed button press variable name<commit_after>'use strict';

angular.module('Lunch.profile', ['openfb', 'Lunch.factory.Geo', 'Lunch.factory.requests', 'Lunch.service.matchData'])
.config(function($stateProvider) {
  $stateProvider
  .state('app.profile', {
    url: '/profile',
    views: {
      'menuContent' :{
        templateUrl: 'templates/profile.html',
        controller: 'ProfileCtrl'
      }
    }
  });
})

.controller('ProfileCtrl', function($q, $rootScope, $scope, $ionicSlideBoxDelegate, $window, storedUserData, OpenFB, Geo, localStore, requests, matchData) {
  // Store data in scope
  $scope.userData = storedUserData;

  $scope.getLikes = function() {
    OpenFB.get('/me/likes')
      .success(function(fbLikeObj){
        // need to keep track of old ids
        var idTrack = {};
        angular.forEach(fbLikeObj.data, function(value){
          //if a new like / id
          if(value.name){
            //inform the database if a new id
            //add the new id and like data locally
            $scope.userData.likes[value.id] = value.name;

            postLikes(value);
          }
          //track id
          idTrack[value.id] = true;
        });
        //check ids fetched from fb to local ids.  if like stored locally no longer
        //avaiable from fb, inform the db and (then) delete locally
        for(var like in $scope.userData.likes) {
          if(!idTrack[like]){
            console.info('Deleteing like: ' + like + '; no longer in facebook');
            requests.deleteLike(like.id, {'userId': $scope.userData.id});
            delete $scope.userData.likes[like]; // since the like no longer exists
            //inform database using like.id and user.id and like.name ($scope.userData.likes[likeId])
          }
        }
      $rootScope.$emit('userDataChanged', $scope.userData);
      });
  };

  var postLikes = function(like) {
    requests.postLike({
      'userId' : $scope.userData.id,
      'id': like.id,
      'name': like.name
    });
  };

  var postTag = function(tagName) {
    requests.postTag({
      'userId' : $scope.userData.id,
      'id': tagName
    });
  };

  var postTags = function() {
    angular.forEach(storedUserData.tags, function(value, key){
        // only post tags that are pressed currently
        if(value){
          postTag(key);
        }
    });
  };

  var deleteTag = function(tagName) {
    requests.deleteTag({
      'userId' : $scope.userData.id,
      'id': tagName
    });
  };

  var getPicture = function() {
    OpenFB.get('/me/picture?redirect=0&height=133&type=normal&width=100')//'/me/picture')
    .success(function(data){
      if(data !== $scope.userData.photo_url){
        var image = "

";
        angular.element(document.querySelector('#userimage')).html(image);
        $scope.userData.photo_url = data.data.url;
        //tell the database the image associated with the user has changed
        postUser();
        $rootScope.$emit('userDataChanged', $scope.userData);
      }
    });
  };

  var getDetails = function() {
    var deferredPost = $q.defer();

    if ($scope.userData.id) {
      deferredPost.resolve();
    } else {
      OpenFB.get('/me')
      .success(function(data){
        angular.extend($scope.userData, data);
        //store updates to data locally
        $rootScope.$emit('userDataChanged', $scope.userData);
        deferredPost.resolve();
      })
      .error(function(err){
        $window.alert('Unable to reach Facebook');
        deferredPost.reject();
      });
    }

    return deferredPost.promise;
  };

  $scope.tagClick = function(e){
    var clickedText = e.toElement.innerText;
    var wasPressed = $scope.userData.tags[clickedText];

    // toggle the state of the tag
    //if it was pressed, and is now not pressed, delete the tag
    if(wasPressed){
      deleteTag(clickedText);
      $scope.userData.tags[clickedText] = false;
    //if it was not pressed, and is now pressed, create the tag
    } else {
      postTag(clickedText);
      $scope.userData.tags[clickedText] = true;
    }
    $rootScope.$emit('userDataChanged', $scope.userData);
  };

  var postUser = function(){
    return getDetails().then(function() {
      return requests.postBasicDetails({
        'id' : $scope.userData.id,
        'firstname': $scope.userData.first_name,
        'lastname': $scope.userData.last_name,
        'profileImage': $scope.userData.photo_url
      });
    });
  };

  var postLocation = function(pos) {
    $scope.userData.geolocation = pos.coords;
      OpenFB.checkLogin().then(function(id) {
        requests.postLocation({
          'userId': id,
          'lat': pos.coords.latitude,
          'lng': pos.coords.longitude
        }).then(function(res) {
          console.info('You are in ' + angular.fromJson(res).data.city);
          $scope.userData.location = angular.fromJson(res).data.city;
          $rootScope.$emit('userDataChanged', $scope.userData);
        });
    });
  };

  $scope.$on('$stateChangeSuccess', function(e, state) { // this triggers every time we go to the profile page, may need something else
    postUser().then(function() {
      getPicture();
      $scope.getLikes();

      //post tags on initialisation
      postTags();

      Geo.getCurrentPosition()
        .then(function(pos) { postLocation(pos); })
        .catch(function(err) { console.error(err); });
      });
  });
});
<|endoftext|>


<commit_before>import moment from 'moment';
import { createSelector } from 'reselect';

export const getRace = (state, props) =>
  state.races.find(race => race.id === parseInt(props.match.params.raceId, 10));

export const getBikeIndex = (_, props) => props.bikeIndex;

export const getRacers = state => state.racers.present;

/**
 * @returns {Object|undefined}
 */
export const getRacer = (state, props) =>
  state.racers.present.find(
    racer => racer.id === getRace(state, props).bikeRacerMap[props.bikeIndex]
  );

export const getBike = (state, props) => state.bikes[props.bikeIndex];

export const getDistance = createSelector(
  [getRace, getBikeIndex, getBike],
  (race, bikeIndex, bike) => {
    let coEf = 0;
    if (bike.rollerDiameter.unit === 'centimeter') {
      if (race.measurementSystem === 'metric') {
        coEf = 100000; // 100000 cm === 1 km
      } else {
        coEf = 160934; // 160934 cm === 1 mile
      }
    } else if (race.measurementSystem === 'imperial') {
      coEf = 63360; // 63360 in === 1 mile
    } else {
      coEf = 39370.1; // 39370.1 in === 1 km
    }
    // coefficient turns roller circumferences (computed in inches or centimeters) into
    // desired output of miles or kilometers
    return race.bikeTicks[bikeIndex] > 0 ?
      (race.bikeTicks[bikeIndex] * (bike.rollerDiameter.value * Math.PI)) / coEf : 0;
  }
);

export const getCircumference = (race, bike) => {
  let coEf = 0;
  if (bike.rollerDiameter.unit === 'centimeter') {
    if (race.measurementSystem === 'metric') {
      coEf = 100000; // 100000 cm === 1 km
    } else {
      coEf = 160934; // 160934 cm === 1 mile
    }
  } else if (race.measurementSystem === 'imperial') {
    coEf = 63360; // 63360 in === 1 mile
  } else {
    coEf = 39370.1; // 39370.1 in === 1 km
  }
  // coefficient turns roller circumferences (computed in inches or centimeters) into
  // desired output of miles or kilometers

  return (bike.rollerDiameter.value * Math.PI) / coEf;
};

export const getTicksToComplete = (race, bike) =>
  Math.ceil(race.raceDistance /
     (race.measurementSystem === 'metric' ? 1000 : 5280) / getCircumference(race, bike));

export const getRaceDuration = createSelector(
  [getRace],
  race => moment.duration(moment().diff(race.startTime, 'milliseconds'))
);

// milliseconds in an hour multiplied by the milliseconds in race
// (mi or km) / hr
export const getSpeed = (distance, duration) => (
  distance > 0 ? (distance * 3600000) / duration.asMilliseconds() : 0
);

/**
 * Returns the current color selected for the bike
 * @param state
 * @param props needs props.bikeIndex
 */
export const getBikeColor = (state, props) => state.bikes[props.bikeIndex].color;

// 360 degrees * ticks / (number of ticks in a race) = current needle rotation
export const getIndicatorRotation = (distance, race) => (distance * 360) / (
  race.raceDistance / (race.measurementSystem === 'metric' ? 1000 : 5280)
);
<commit_msg>Adding #FIXME to selector that is broken<commit_after>import moment from 'moment';
import { createSelector } from 'reselect';

export const getRace = (state, props) =>
  state.races.find(race => race.id === parseInt(props.match.params.raceId, 10));

export const getBikeIndex = (_, props) => props.bikeIndex;

export const getRacers = state => state.racers.present;

/**
 * @returns {Object|undefined}
 */
export const getRacer = (state, props) =>
  state.racers.present.find(
    racer => racer.id === getRace(state, props).bikeRacerMap[props.bikeIndex]
  );

export const getBike = (state, props) => state.bikes[props.bikeIndex];

// FIXME: bikeTicks was moved from race object in redux to the race component
export const getDistance = createSelector(
  [getRace, getBikeIndex, getBike],
  (race, bikeIndex, bike) => {
    let coEf = 0;
    if (bike.rollerDiameter.unit === 'centimeter') {
      if (race.measurementSystem === 'metric') {
        coEf = 100000; // 100000 cm === 1 km
      } else {
        coEf = 160934; // 160934 cm === 1 mile
      }
    } else if (race.measurementSystem === 'imperial') {
      coEf = 63360; // 63360 in === 1 mile
    } else {
      coEf = 39370.1; // 39370.1 in === 1 km
    }
    // coefficient turns roller circumferences (computed in inches or centimeters) into
    // desired output of miles or kilometers
    return race.bikeTicks[bikeIndex] > 0 ?
      (race.bikeTicks[bikeIndex] * (bike.rollerDiameter.value * Math.PI)) / coEf : 0;
  }
);

export const getCircumference = (race, bike) => {
  let coEf = 0;
  if (bike.rollerDiameter.unit === 'centimeter') {
    if (race.measurementSystem === 'metric') {
      coEf = 100000; // 100000 cm === 1 km
    } else {
      coEf = 160934; // 160934 cm === 1 mile
    }
  } else if (race.measurementSystem === 'imperial') {
    coEf = 63360; // 63360 in === 1 mile
  } else {
    coEf = 39370.1; // 39370.1 in === 1 km
  }
  // coefficient turns roller circumferences (computed in inches or centimeters) into
  // desired output of miles or kilometers

  return (bike.rollerDiameter.value * Math.PI) / coEf;
};

export const getTicksToComplete = (race, bike) =>
  Math.ceil(race.raceDistance /
     (race.measurementSystem === 'metric' ? 1000 : 5280) / getCircumference(race, bike));

export const getRaceDuration = createSelector(
  [getRace],
  race => moment.duration(moment().diff(race.startTime, 'milliseconds'))
);

// milliseconds in an hour multiplied by the milliseconds in race
// (mi or km) / hr
export const getSpeed = (distance, duration) => (
  distance > 0 ? (distance * 3600000) / duration.asMilliseconds() : 0
);

/**
 * Returns the current color selected for the bike
 * @param state
 * @param props needs props.bikeIndex
 */
export const getBikeColor = (state, props) => state.bikes[props.bikeIndex].color;

// 360 degrees * ticks / (number of ticks in a race) = current needle rotation
export const getIndicatorRotation = (distance, race) => (distance * 360) / (
  race.raceDistance / (race.measurementSystem === 'metric' ? 1000 : 5280)
);
<|endoftext|>