<commit_before>/*
 * Module for tracking standardized analytics.
 */

var _gaq = _gaq || [];
var _sf_async_config = {};
var _comscore = _comscore || [];

var ANALYTICS = (function () {

    // Global time tracking variables
    var slideStartTime =  new Date();
    var timeOnLastSlide = null;

    /*
     * Google Analytics
     */
    var setupGoogle = function() {
        _gaq.push(['_setAccount', APP_CONFIG.GOOGLE_ANALYTICS.ACCOUNT_ID]);
        _gaq.push(['_setDomainName', APP_CONFIG.GOOGLE_ANALYTICS.DOMAIN]);
        //_gaq.push(['_setCustomVar', 1, 'BC', '', 3]);
        _gaq.push(['_setCustomVar', 2, 'Topics', APP_CONFIG.GOOGLE_ANALYTICS.TOPICS, 3]);
        //_gaq.push(['_setCustomVar', 3, 'Program ID', '', 3]);
        //_gaq.push(['_setCustomVar', 3, 'Localization', '', 1]);
        _gaq.push(['_setCustomVar', 4, 'OrgID', '1', 3]);
        _gaq.push(['_setCustomVar', 5, 'Page Types', '1', 3]);

        var orientation = 'portrait';

        if (window.orientation == 90 || window.orientation == -90) {
            orientation = 'landscape';
        }

        _gaq.push(['_setCustomVar', 6, 'Orientation', orientation, 3]);

        var viewportSize = $(window).width();
        var viewportGrouping = '1760 and higher';

        if (viewportSize < 481) {
            viewportGrouping = '0 - 480';
        } else if (viewportSize < 768) {
            viewportGrouping = '481 - 767';
        } else if (viewportSize < 1000) {
            viewportGrouping = '768 - 999';
        } else if (viewportSize < 1201) {
            viewportGrouping = '1000 - 1200';
        } else if (viewportSize < 1760) {
            viewportGrouping = '1201 - 1759';
        }

        _gaq.push(['_setCustomVar', 7, 'Viewport Size', viewportGrouping, 3]);

        if (typeof window.devicePixelRatio !== 'undefined' && window.devicePixelRatio >= 1.5) {
            _gaq.push(['_setCustomVar', 10, 'High Density Displays', 'High', 2]);
        } else {
            _gaq.push(['_setCustomVar', 10, 'High Density Displays', 'Low', 2]);
        }

        if ('ontouchstart' in document.documentElement) {
            _gaq.push(['_setCustomVar', 11, 'Touch screens', 'Touch', 2]);
        } else {
            _gaq.push(['_setCustomVar', 11, 'Touch screens', 'Traditional', 2]);
        }

        _gaq.push(['_trackPageview']);

        (function() {
            var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
            ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
            var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
        })();
    }

    /*
     * Comscore
     */
    var setupComscore = function() {
        _comscore.push({ c1: "2", c2: "17691522" });

        (function() {
            var s = document.createElement("script"), el = document.getElementsByTagName("script")[0]; s.async = true;
            s.src = (document.location.protocol == "https:" ? "https://sb" : "http://b") + ".scorecardresearch.com/beacon.js";
            el.parentNode.insertBefore(s, el);
        })();
    }

    /*
     * Nielson
     */
    var setupNielson = function() {
        (function () {
            var d = new Image(1, 1);
            d.onerror = d.onload = function () { d.onerror = d.onload = null; };
            d.src = ["//secure-us.imrworldwide.com/cgi-bin/m?ci=us-803244h&cg=0&cc=1&si=", escape(window.location.href), "&rp=", escape(document.referrer), "&ts=compact&rnd=", (new Date()).getTime()].join('');
        })();
    }

    /*
     * Chartbeat
     */
    var setupChartbeat = function() {
        /** CONFIGURATION START **/
        _sf_async_config.uid = 18888;
        _sf_async_config.domain = "npr.org";
        /** CONFIGURATION END **/
        (function(){
            function loadChartbeat() {
                window._sf_endpt=(new Date()).getTime();
                var e = document.createElement("script");
                e.setAttribute("language", "javascript");
                e.setAttribute("type", "text/javascript");
                e.setAttribute("src",
                    (("https:" == document.location.protocol) ?
                     "https://a248.e.akamai.net/chartbeat.download.akamai.com/102508/" :
                     "http://static.chartbeat.com/") +
                    "js/chartbeat.js");
                document.body.appendChild(e);
            }
            var oldonload = window.onload;
            window.onload = (typeof window.onload != "function") ?
                loadChartbeat : function() { oldonload(); loadChartbeat(); };
        })();
    }

    var setupAll = function() {
        setupGoogle();
        setupComscore();
        setupNielson();
        setupChartbeat();
    }

    /*
     * Event tracking.
     */
    var trackEvent = function(eventName, label, value, custom1, custom2) {
        var args = ['_trackEvent', APP_CONFIG.PROJECT_SLUG];

        args.push(eventName);

        if (label) {
            args.push(label);
        } else if (value || custom1 || custom2) {
            args.push('');
        }

        if (value) {
            args.push(value);
        } else if (custom1 || custom2) {
            args.push(0);
        }

        if (custom1) {
            args.push(custom1)
        } else if (custom2) {
            args.push('');
        }

        if (custom2) {
            args.push(custom2);
        }

        _gaq.push(args);
    }

    // SHARING

    var openShareDiscuss = function() {
        trackEvent('open-share-discuss');
    }

    var closeShareDiscuss = function() {
        trackEvent('close-share-discuss');
    }

    var clickTweet = function(location) {
        trackEvent('tweet', location);
    }

    var clickFacebook = function(location) {
        trackEvent('facebook', location);
    }

    var clickEmail = function(location) {
        trackEvent('email', location);
    }

    var postComment = function() {
        trackEvent('new-comment');
    }

    var actOnFeaturedTweet = function(action, tweet_url) {
        trackEvent('featured-tweet-action', action, null, tweet_url);
    }

    var actOnFeaturedFacebook = function(action, post_url) {
        trackEvent('featured-facebook-action', action, null, post_url);
    }

    var copySummary = function() {
        trackEvent('summary-copied');
    }

    // NAVIGATION
    var usedKeyboardNavigation = false;

    var useKeyboardNavigation = function() {
        if (!usedKeyboardNavigation) {
            trackEvent('keyboard-nav');
            usedKeyboardNavigation = true;
        }
    }

    var completeTwentyFivePercent =  function() {
        trackEvent('completion', '0.25');
    }

    var completeFiftyPercent =  function() {
        trackEvent('completion', '0.5');
    }

    var completeSeventyFivePercent =  function() {
        trackEvent('completion', '0.75');
    }

    var completeOneHundredPercent =  function() {
        trackEvent('completion', '1');
    }

    // SLIDES

    var exitSlide = function(slide_index, last_slide_exit_event) {
        var currentTime = new Date();
        timeOnLastSlide = Math.abs(currentTime - slideStartTime);
        slideStartTime = currentTime;
        trackEvent('slide-exit', slide_index, timeOnLastSlide, last_slide_exit_event);
    }

    return {
        'setupAll': setupAll,
        'trackEvent': trackEvent,
        'openShareDiscuss': openShareDiscuss,
        'closeShareDiscuss': closeShareDiscuss,
        'clickTweet': clickTweet,
        'clickFacebook': clickFacebook,
        'clickEmail': clickEmail,
        'postComment': postComment,
        'actOnFeaturedTweet': actOnFeaturedTweet,
        'actOnFeaturedFacebook': actOnFeaturedFacebook,
        'copySummary': copySummary,
        'useKeyboardNavigation': useKeyboardNavigation,
        'completeTwentyFivePercent': completeTwentyFivePercent,
        'completeFiftyPercent': completeFiftyPercent,
        'completeSeventyFivePercent': completeSeventyFivePercent,
        'completeOneHundredPercent': completeOneHundredPercent,
        'exitSlide': exitSlide
    };
}());

ANALYTICS.setupAll();
<commit_msg>new analytics events from austin. closes #536<commit_after>/*
 * Module for tracking standardized analytics.
 */

var _gaq = _gaq || [];
var _sf_async_config = {};
var _comscore = _comscore || [];

var ANALYTICS = (function () {

    // Global time tracking variables
    var slideStartTime =  new Date();
    var timeOnLastSlide = null;

    /*
     * Google Analytics
     */
    var setupGoogle = function() {
        _gaq.push(['_setAccount', APP_CONFIG.GOOGLE_ANALYTICS.ACCOUNT_ID]);
        _gaq.push(['_setDomainName', APP_CONFIG.GOOGLE_ANALYTICS.DOMAIN]);
        //_gaq.push(['_setCustomVar', 1, 'BC', '', 3]);
        _gaq.push(['_setCustomVar', 2, 'Topics', APP_CONFIG.GOOGLE_ANALYTICS.TOPICS, 3]);
        //_gaq.push(['_setCustomVar', 3, 'Program ID', '', 3]);
        //_gaq.push(['_setCustomVar', 3, 'Localization', '', 1]);
        _gaq.push(['_setCustomVar', 4, 'OrgID', '1', 3]);
        _gaq.push(['_setCustomVar', 5, 'Page Types', '1', 3]);

        var orientation = 'portrait';

        if (window.orientation == 90 || window.orientation == -90) {
            orientation = 'landscape';
        }

        _gaq.push(['_setCustomVar', 6, 'Orientation', orientation, 3]);

        var viewportSize = $(window).width();
        var viewportGrouping = '1760 and higher';

        if (viewportSize < 481) {
            viewportGrouping = '0 - 480';
        } else if (viewportSize < 768) {
            viewportGrouping = '481 - 767';
        } else if (viewportSize < 1000) {
            viewportGrouping = '768 - 999';
        } else if (viewportSize < 1201) {
            viewportGrouping = '1000 - 1200';
        } else if (viewportSize < 1760) {
            viewportGrouping = '1201 - 1759';
        }

        _gaq.push(['_setCustomVar', 7, 'Viewport Size', viewportGrouping, 3]);

        if (typeof window.devicePixelRatio !== 'undefined' && window.devicePixelRatio >= 1.5) {
            _gaq.push(['_setCustomVar', 10, 'High Density Displays', 'High', 2]);
        } else {
            _gaq.push(['_setCustomVar', 10, 'High Density Displays', 'Low', 2]);
        }

        if ('ontouchstart' in document.documentElement) {
            _gaq.push(['_setCustomVar', 11, 'Touch screens', 'Touch', 2]);
        } else {
            _gaq.push(['_setCustomVar', 11, 'Touch screens', 'Traditional', 2]);
        }

        _gaq.push(['_trackPageview']);

        (function() {
            var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
            ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
            var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
        })();
    }

    /*
     * Comscore
     */
    var setupComscore = function() {
        _comscore.push({ c1: "2", c2: "17691522" });

        (function() {
            var s = document.createElement("script"), el = document.getElementsByTagName("script")[0]; s.async = true;
            s.src = (document.location.protocol == "https:" ? "https://sb" : "http://b") + ".scorecardresearch.com/beacon.js";
            el.parentNode.insertBefore(s, el);
        })();
    }

    /*
     * Nielson
     */
    var setupNielson = function() {
        (function () {
            var d = new Image(1, 1);
            d.onerror = d.onload = function () { d.onerror = d.onload = null; };
            d.src = ["//secure-us.imrworldwide.com/cgi-bin/m?ci=us-803244h&cg=0&cc=1&si=", escape(window.location.href), "&rp=", escape(document.referrer), "&ts=compact&rnd=", (new Date()).getTime()].join('');
        })();
    }

    /*
     * Chartbeat
     */
    var setupChartbeat = function() {
        /** CONFIGURATION START **/
        _sf_async_config.uid = 18888;
        _sf_async_config.domain = "npr.org";
        /** CONFIGURATION END **/
        (function(){
            function loadChartbeat() {
                window._sf_endpt=(new Date()).getTime();
                var e = document.createElement("script");
                e.setAttribute("language", "javascript");
                e.setAttribute("type", "text/javascript");
                e.setAttribute("src",
                    (("https:" == document.location.protocol) ?
                     "https://a248.e.akamai.net/chartbeat.download.akamai.com/102508/" :
                     "http://static.chartbeat.com/") +
                    "js/chartbeat.js");
                document.body.appendChild(e);
            }
            var oldonload = window.onload;
            window.onload = (typeof window.onload != "function") ?
                loadChartbeat : function() { oldonload(); loadChartbeat(); };
        })();
    }

    var setupAll = function() {
        setupGoogle();
        setupComscore();
        setupNielson();
        setupChartbeat();
    }

    /*
     * Event tracking.
     */
    var trackEvent = function(eventName, label, value, custom1, custom2) {
        var args = ['_trackEvent', APP_CONFIG.PROJECT_SLUG];

        args.push(eventName);

        if (label) {
            args.push(label);
        } else if (value || custom1 || custom2) {
            args.push('');
        }

        if (value) {
            args.push(value);
        } else if (custom1 || custom2) {
            args.push(0);
        }

        if (custom1) {
            args.push(custom1)
        } else if (custom2) {
            args.push('');
        }

        if (custom2) {
            args.push(custom2);
        }

        _gaq.push(args);
    }

    // SHARING

    var openShareDiscuss = function() {
        trackEvent('open-share-discuss');
    }

    var closeShareDiscuss = function() {
        trackEvent('close-share-discuss');
    }

    var clickTweet = function(location) {
        trackEvent('tweet', location);
    }

    var clickFacebook = function(location) {
        trackEvent('facebook', location);
    }

    var clickEmail = function(location) {
        trackEvent('email', location);
    }

    var postComment = function() {
        trackEvent('new-comment');
    }

    var actOnFeaturedTweet = function(action, tweet_url) {
        trackEvent('featured-tweet-action', action, null, tweet_url);
    }

    var actOnFeaturedFacebook = function(action, post_url) {
        trackEvent('featured-facebook-action', action, null, post_url);
    }

    var copySummary = function() {
        trackEvent('summary-copied');
    }

    // NAVIGATION
    var usedKeyboardNavigation = false;

    var useKeyboardNavigation = function() {
        if (!usedKeyboardNavigation) {
            trackEvent('keyboard-nav');
            usedKeyboardNavigation = true;
        }
    }

    var completeTwentyFivePercent =  function() {
        trackEvent('completion', '0.25');
    }

    var completeFiftyPercent =  function() {
        trackEvent('completion', '0.5');
    }

    var completeSeventyFivePercent =  function() {
        trackEvent('completion', '0.75');
    }

    var completeOneHundredPercent =  function() {
        trackEvent('completion', '1');
    }

    var startFullscreen = function() {
        trackEvent('fullscreen-start');
    }

    var stopFullscreen = function() {
        trackEvent('fullscreen-stop');
    }

    var begin = function(location) {
        trackEvent('begin', location);
    }

    var readyChromecast = function() {
        trackEvent('chromecast-ready');
    }

    var startChromecast = function() {
        trackEvent('chromecast-start');
    }

    var stopChromecast = function() {
        trackEvent('chromecast-stop');
    }

    // SLIDES

    var exitSlide = function(slide_index, last_slide_exit_event) {
        var currentTime = new Date();
        timeOnLastSlide = Math.abs(currentTime - slideStartTime);
        slideStartTime = currentTime;
        trackEvent('slide-exit', slide_index, timeOnLastSlide, last_slide_exit_event);
    }

    return {
        'setupAll': setupAll,
        'trackEvent': trackEvent,
        'openShareDiscuss': openShareDiscuss,
        'closeShareDiscuss': closeShareDiscuss,
        'clickTweet': clickTweet,
        'clickFacebook': clickFacebook,
        'clickEmail': clickEmail,
        'postComment': postComment,
        'actOnFeaturedTweet': actOnFeaturedTweet,
        'actOnFeaturedFacebook': actOnFeaturedFacebook,
        'copySummary': copySummary,
        'useKeyboardNavigation': useKeyboardNavigation,
        'completeTwentyFivePercent': completeTwentyFivePercent,
        'completeFiftyPercent': completeFiftyPercent,
        'completeSeventyFivePercent': completeSeventyFivePercent,
        'completeOneHundredPercent': completeOneHundredPercent,
        'exitSlide': exitSlide,
        'startFullscreen': startFullscreen,
        'stopFullscreen': stopFullscreen,
        'begin': begin,
        'readyChromecast': readyChromecast,
        'startChromecast': startChromecast,
        'stopChromecast': stopChromecast
    };
}());

ANALYTICS.setupAll();
<|endoftext|>


<commit_before>/**
 * Modules dependencies
 */

var jsdom = require('jsdom'),
    cheerio = require('cheerio'),
    request = new require('superagent').agent(),
    fs = require('fs'),
    ScrapinodeError = require('./error/scrapinode-error'),
    http = require('http'),
    STATUS_CODES = http.STATUS_CODES;

/**
 * JQuery dependencies
 */

var jqueryExt = fs.readFileSync(__dirname + '/../deps/jquery-regex-selector.js').toString();
var jquery = fs.readFileSync(__dirname + '/../deps/jquery-1.6.2.min.js').toString() + jqueryExt;

/**
 * Build the DOM of the given page found at `options.url` or `options.html`
 *
 * @param {Object} options -
 * @param {Function} callback -
 * @param {Error} callback().err -
 * @param {Object} callback().window -
 */

exports.load = function(options,callback){
    var headers = {
        'user-agent' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.107 Safari/535.1',
        'accept' : 'text/html, application/xhtml+xml, application/xml; q=0.9',
        'accept-charset' : 'utf-8; q=1.0, ISO-8859-1; q=0.7, *; q=0.3',
        'accept-encoding' : 'gzip, deflate'
    };
    var timeout = 5000;
    var retries = 3;
    var redirects = 5;

    getRequest({
        url : options.url,
        headers : headers,
        timeout : timeout,
        retries : retries,
        redirects : redirects
    },function(err,body){
        if(err) return callback(err);
        buildDOM(body,options.engine,options.url,callback);
    });
};

/**
 * Send an HTTP GET request to `options.url`
 *
 * @param {Object} options - configuration of the HTTP GET request
 * @param {String} options.headers - set of headers
 * @param {Number} options.timeout - timeout
 * @param {Number} options.redirects - number of times the request will follow redirection instructions
 * @param {Number} options.retries - number of times the request will be resend if the request failed
 * @param {Function} callback -
 * @api private
 */

function getRequest(options,callback){
    var destroyed = false;
    var req = request.get(options.url)
        .set(options.headers)
        .timeout(options.timeout)
        .redirects(options.redirects)
        .buffer(false)
        .end(function(err,res){
            if(err) return onError(err);

            // Check HTTP status code
            var isHTTPError = isRedirect(res.status) || isClientError(res.status) || isServerError(res.status);
            if(isHTTPError) return onError(createHTTPError(res.status));

            // Attach event handlers and build the body
            var body = '';
            res.on('data',function(chunk){
                body += chunk;
            });
            res.on('end',function(){
                if(destroyed) return;
                // Check if a HTTP refresh/redirection is present into the HTML page, if yes refreshes/redirects.
                var matches = body.match(/<meta[ ]*http-equiv="REFRESH"[ ]*content="[0-9]{1,};[ ]*URL=(.*?)"[ ]*\/?>/i);
                if(matches && matches[1]){
                    options.url = matches[1];
                    return getRequest(options,callback);
                }
                callback(null,body);
            });
            res.on('error',onError);

            // Check if content-type is an image, if yes destroy the response and build a HTML page with the image in it
            if(isImage(res.headers)){
                res.destroy();
                destroyed = true;
                body = '<!DOCTYPE html>';
                return callback(null,body);
            }
        });

    // Error event handler
    function onError(err){
        if(options.retries--) return getRequest(options,callback);
        callback(err);
    }
}

/**
 * Build a DOM representation of the given HTML `body`
 *
 * @param {String} body - html page
 * @param {String} engine - name of the engine used to generate the DOM
 * @param {String} url - url of the page containing the given `body`
 * @param {Function} callback -
 *
 * @api private
 */

function buildDOM(body,engine,url,callback){
    if(!body){
        return callback(new ScrapinodeError('The HTTP response contains an empty body: "' + body +'"'));
    }

    if(engine === 'jsdom'){
        jsdom.env({
           html: body,
           src : [jquery],
           done : function(err,window){
               window.location.href = url;
               callback(err,window);
               window.close();
           }
        });
    }else if(engine === 'cheerio'){
        var $ = cheerio.load(body);
        var window = {
            $ : $,
            location : {
                href : url
            }
        };
        callback(null,window);
    }else{
        callback(new ScrapinodeError('The engine "' + engine + '" is not supported. Scrapinode only supports jsdom and cheerio.'));
    }
}

/**
 * Check if the `code` is a HTTP redirection status.
 *
 * @param {Number} code
 * @return {Boolean}
 * @api private
 */

function isRedirect(code) {
  return (code >= 300 && code < 399);
}

/**
 * Check if the `code` is a HTTP client error status.
 *
 * @param {Number} code
 * @return {Boolean}
 * @api private
 */

function isClientError(code){
    return (code >= 400 && code < 499);
}

/**
 * Check if the `code` is a HTTP server error status.
 *
 * @param {Number} code
 * @return {Boolean}
 * @api private
 */

function isServerError(code){
    return (code >= 500 && code < 599);
}

/**
 * Create an `Èrror` object for the given HTTP status `code`.
 *
 * @param {Number} code
 * @return {Error}
 * @api private
 */

function createHTTPError(code){
    var description = STATUS_CODES[code] || 'Unknown status code';
    var message = 'HTTP Error ' + code + ' - ' + description;
    return new Error(message);
}

/**
 * Check if the content of the HTTP body is an image
 *
 * @param {Object} headers -
 * @return {Boolean}
 * @api private
 */
var regexImage = /image\//i;
function isImage(headers){
    var contentType = headers ?  headers['content-type'] : '';
    return regexImage.test(contentType);
}<commit_msg>NEW: Use HTTPError class.<commit_after>/**
 * Modules dependencies
 */

var jsdom = require('jsdom'),
    cheerio = require('cheerio'),
    request = new require('superagent').agent(),
    fs = require('fs'),
    ScrapinodeError = require('./error/scrapinode-error'),
    HTTPError = require('httperror');

/**
 * JQuery dependencies
 */

var jqueryExt = fs.readFileSync(__dirname + '/../deps/jquery-regex-selector.js').toString();
var jquery = fs.readFileSync(__dirname + '/../deps/jquery-1.6.2.min.js').toString() + jqueryExt;

/**
 * Build the DOM of the given page found at `options.url` or `options.html`
 *
 * @param {Object} options -
 * @param {Function} callback -
 * @param {Error} callback().err -
 * @param {Object} callback().window -
 */

exports.load = function(options,callback){
    var headers = {
        'user-agent' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.107 Safari/535.1',
        'accept' : 'text/html, application/xhtml+xml, application/xml; q=0.9',
        'accept-charset' : 'utf-8; q=1.0, ISO-8859-1; q=0.7, *; q=0.3',
        'accept-encoding' : 'gzip, deflate'
    };
    var timeout = 5000;
    var retries = 3;
    var redirects = 5;

    getRequest({
        url : options.url,
        headers : headers,
        timeout : timeout,
        retries : retries,
        redirects : redirects
    },function(err,body){
        if(err) return callback(err);
        buildDOM(body,options.engine,options.url,callback);
    });
};

/**
 * Send an HTTP GET request to `options.url`
 *
 * @param {Object} options - configuration of the HTTP GET request
 * @param {String} options.headers - set of headers
 * @param {Number} options.timeout - timeout
 * @param {Number} options.redirects - number of times the request will follow redirection instructions
 * @param {Number} options.retries - number of times the request will be resend if the request failed
 * @param {Function} callback -
 * @api private
 */

function getRequest(options,callback){
    var destroyed = false;
    var req = request.get(options.url)
        .set(options.headers)
        .timeout(options.timeout)
        .redirects(options.redirects)
        .buffer(false)
        .end(function(err,res){
            if(err) return onError(err);

            // Check HTTP status code
            var isHTTPError = isRedirect(res.status) || isClientError(res.status) || isServerError(res.status);
            if(isHTTPError) return onError(new HTTPError(res.status));

            // Attach event handlers and build the body
            var body = '';
            res.on('data',function(chunk){
                body += chunk;
            });
            res.on('end',function(){
                if(destroyed) return;
                // Check if a HTTP refresh/redirection is present into the HTML page, if yes refreshes/redirects.
                var matches = body.match(/<meta[ ]*http-equiv="REFRESH"[ ]*content="[0-9]{1,};[ ]*URL=(.*?)"[ ]*\/?>/i);
                if(matches && matches[1]){
                    options.url = matches[1];
                    return getRequest(options,callback);
                }
                callback(null,body);
            });
            res.on('error',onError);

            // Check if content-type is an image, if yes destroy the response and build a HTML page with the image in it
            if(isImage(res.headers)){
                res.destroy();
                destroyed = true;
                body = '<!DOCTYPE html>';
                return callback(null,body);
            }
        });

    // Error event handler
    function onError(err){
        if(options.retries--) return getRequest(options,callback);
        callback(err);
    }
}

/**
 * Build a DOM representation of the given HTML `body`
 *
 * @param {String} body - html page
 * @param {String} engine - name of the engine used to generate the DOM
 * @param {String} url - url of the page containing the given `body`
 * @param {Function} callback -
 *
 * @api private
 */

function buildDOM(body,engine,url,callback){
    if(!body){
        return callback(new ScrapinodeError('The HTTP response contains an empty body: "' + body +'"'));
    }

    if(engine === 'jsdom'){
        jsdom.env({
           html: body,
           src : [jquery],
           done : function(err,window){
               window.location.href = url;
               callback(err,window);
               window.close();
           }
        });
    }else if(engine === 'cheerio'){
        var $ = cheerio.load(body);
        var window = {
            $ : $,
            location : {
                href : url
            }
        };
        callback(null,window);
    }else{
        callback(new ScrapinodeError('The engine "' + engine + '" is not supported. Scrapinode only supports jsdom and cheerio.'));
    }
}

/**
 * Check if the `code` is a HTTP redirection status.
 *
 * @param {Number} code
 * @return {Boolean}
 * @api private
 */

function isRedirect(code) {
  return (code >= 300 && code < 399);
}

/**
 * Check if the `code` is a HTTP client error status.
 *
 * @param {Number} code
 * @return {Boolean}
 * @api private
 */

function isClientError(code){
    return (code >= 400 && code < 499);
}

/**
 * Check if the `code` is a HTTP server error status.
 *
 * @param {Number} code
 * @return {Boolean}
 * @api private
 */

function isServerError(code){
    return (code >= 500 && code < 599);
}

/**
 * Check if the content of the HTTP body is an image
 *
 * @param {Object} headers -
 * @return {Boolean}
 * @api private
 */
var regexImage = /image\//i;
function isImage(headers){
    var contentType = headers ?  headers['content-type'] : '';
    return regexImage.test(contentType);
}<|endoftext|>


<commit_before>var SQLite3JS = (function () {
  "use strict";

  var SQLite3JS, Database, ItemDataSource, GroupDataSource;

  SQLite3JS = {
    /// Set this to true to get some more logging output
    debug: false,
    logger: {
      trace: console.log.bind(console),
      warn: console.warn.bind(console),
      error: console.error.bind(console),
      info: console.info.bind(console)
    }
  };

  function PromiseQueue() {
    this._items = [];
    this._busy = false;
  }

  PromiseQueue.prototype.append = function (createPromise) {
    var wrappingPromise,
        queueItem = { createPromise: createPromise },
        _this = this;

    wrappingPromise = new WinJS.Promise(function (complete, error) {
      queueItem.complete = complete;
      queueItem.error = error;
    }, function () {
      if (queueItem.promise) {
        queueItem.promise.cancel();
      } else {
        queueItem.cancelled = true;
      }

      _this._handleNext();
    });

    this._items.push(queueItem);
    if (!this._busy) {
      this._handleNext();
    }

    return wrappingPromise;
  };

  PromiseQueue.prototype._handleNext = function () {
    var _this = this;
    /* shorten call stack */
    this._busy = true;
    setImmediate(function () {
      if (_this._items.length > 0) {
        var nextItem = _this._items[0];
        _this._items = _this._items.slice(1);
        _this._handleItem(nextItem);
      } else {
        _this._busy = false;
      }
    });
  };

  PromiseQueue.prototype._handleItem = function (queueItem) {
    var _this = this;

    if (!queueItem.cancelled) {
      queueItem.promise = queueItem.createPromise();
      queueItem.promise.done(function (result) {
        _this._handleNext();
        queueItem.complete(result);
      }, function (error) {
        _this._handleNext();
        queueItem.error(error);
      });
    } else {
      this._handleNext();
    }
  };

  function toPropertySet(object) {
    var key, propertySet = new Windows.Foundation.Collections.PropertySet();

    for (key in object) {
      if (object.hasOwnProperty(key)) {
        propertySet.insert(key, object[key]);
      }
    }

    return propertySet;
  }

  function prepareArgs(args) {
    args = args || [];
    return (args instanceof Array) ? args : toPropertySet(args);
  }

  function formatStatementAndArgs(sql, args) {
    var argString = args ? ' ' + args.toString() : '';
    return '"' + sql + '", ' + argString;
  }

  function wrapException(exception, detailedMessage, functionName, sql, args) {
    var error, message, resultCode, number;

    if (exception.hasOwnProperty('number')) {
      // Convert the COM error to an unsigned hex value that we can check in JS like E_FAIL == 0x80004005
      number = 0xffffffff + exception.number + 1;
      resultCode = number & 0x20000000 ? exception.number & 0xffff : 0;
      message = (resultCode > 0 ? resultCode : "0x" + number.toString(16)) + ": ";
      if (functionName) {
        message += functionName;

        if (sql) {
          message += '(' + formatStatementAndArgs(sql, args) + ') ';
        } else {
          message += " ";
        }
      }
      if (detailedMessage) {
        message += detailedMessage;
      }
      error = new WinJS.ErrorFromName("SQLiteError", message);
      error.resultCode = resultCode;
      error.number = number;
      error.sql = sql;
      error.args = args;
      error.functionName = functionName;
    } else {
      error = exception;
    }

    return WinJS.Promise.wrapError(error);
  }

  function wrapDatabase(connection) {
    var that, queue = new PromiseQueue();

    function callNativeAsync(funcName, sql, args, callback) {
      var argString, preparedArgs, fullFuncName;

      if (SQLite3JS.debug) {
        SQLite3JS.logger.trace(funcName + ': ' + formatStatementAndArgs(sql, args));
      }

      return queue.append(function () {
        preparedArgs = prepareArgs(args);
        fullFuncName =
          preparedArgs instanceof Windows.Foundation.Collections.PropertySet
          ? funcName + "Map"
          : funcName + "Vector";

        return connection[fullFuncName](sql, preparedArgs, callback).then(null, function (error) {
          return wrapException(error, that.lastError, funcName, sql, args);
        });
      });
    }

    that = {
      runAsync: function (sql, args) {
        return callNativeAsync('runAsync', sql, args).then(function (affectedRowCount) {
          return affectedRowCount;
        });
      },
      oneAsync: function (sql, args) {
        return callNativeAsync('oneAsync', sql, args).then(function (row) {
          return row ? JSON.parse(row) : null;
        });
      },
      allAsync: function (sql, args) {
        return callNativeAsync('allAsync', sql, args).then(function (rows) {
          return rows ? JSON.parse(rows) : null;
        });
      },
      eachAsync: function (sql, args, callback) {
        if (!callback && typeof args === 'function') {
          callback = args;
          args = undefined;
        }

        return callNativeAsync('eachAsync', sql, args, function (row) {
          callback(JSON.parse(row));
        }).then(function () {
          return that;
        });
      },
      mapAsync: function (sql, args, callback) {
        if (!callback && typeof args === 'function') {
          callback = args;
          args = undefined;
        }

        var results = [];

        return that.eachAsync(sql, args, function (row) {
          results.push(callback(row));
        }).then(function () {
          return results;
        });
      },
      itemDataSource: function (sql, args, keyColumnName, groupKeyColumnName) {
        if (typeof args === 'string') {
          groupKeyColumnName = keyColumnName;
          keyColumnName = args;
          args = undefined;
        }

        return new ItemDataSource(that, sql, args, keyColumnName, groupKeyColumnName);
      },
      groupDataSource: function (sql, args, keyColumnName, sizeColumnName) {
        if (typeof args === 'string') {
          sizeColumnName = keyColumnName;
          keyColumnName = args;
          args = undefined;
        }

        return new GroupDataSource(that, sql, args, keyColumnName, sizeColumnName);
      },
      close: function () {
        connection.close();
      },
      vacuumAsync: function () {
        return new WinJS.Promise( function(complete) {
          connection.vacuumAsync();
          complete();
        });
      },
      addEventListener: connection.addEventListener.bind(connection),
      removeEventListener: connection.removeEventListener.bind(connection)
    };

    Object.defineProperties(
      that,
      WinJS.Utilities.createEventProperties('update', 'delete', 'insert')
    );

    Object.defineProperties(that, {
      "collationLanguage": {
        set: function (value) { connection.collationLanguage = value; },
        get: function () { return connection.collationLanguage; },
        enumerable: true
      },
      "fireEvents": {
        set: function (value) { connection.fireEvents = value; },
        get: function () { return connection.fireEvents; },
        enumerable: true
      },
      "lastError": {
        get: function () { return connection.lastError; },
        enumerable: true
      },
      "autoCommit": {
        get: function () { return connection.autoCommit; },
        enumerable: true
      },
      "lastInsertRowId": {
        get: function () { return connection.lastInsertRowId; },
        enumerable: true
      }
    });

    return that;
  }

  ItemDataSource = WinJS.Class.derive(WinJS.UI.VirtualizedDataSource,
    function (db, sql, args, keyColumnName, groupKeyColumnName) {
      this._dataAdapter = {
        setQuery: function (sql, args) {
          this._sql = sql;
          this._args = args;
        },
        getCount: function () {
          return db.oneAsync('SELECT COUNT(*) AS cnt FROM (' + this._sql + ')', this._args)
          .then(function (row) { return row.cnt; });
        },
        itemsFromIndex: function (requestIndex, countBefore, countAfter) {
          var items,
              limit = countBefore + 1 + countAfter,
              offset = requestIndex - countBefore,
              that = this;

          return this.getCount().then(function (totalCount) {
            return db.mapAsync(
              'SELECT * FROM (' + that._sql + ') LIMIT ' + limit + ' OFFSET ' + offset,
              that._args,
              function (row) {
                var item = {
                  key: row[keyColumnName].toString(),
                  data: row
                };
                if (groupKeyColumnName) {
                  if (!row.hasOwnProperty(groupKeyColumnName) || row[groupKeyColumnName] === null) {
                    throw "Group key property not found: " + groupKeyColumnName;
                  }
                  item.groupKey = row[groupKeyColumnName].toString();
                }
                return item;
              }).then(function (items) {
                return {
                  items: items,
                  offset: countBefore,
                  totalCount: totalCount
                };
              });
          });
        },
        setNotificationHandler: function (notificationHandler) {
          this._notificationHandler = notificationHandler;
        },
        getNotificationHandler: function () {
          return this._notificationHandler;
        }
      };

      this._dataAdapter.setQuery(sql, args);
      this._baseDataSourceConstructor(this._dataAdapter);
    }, {
      setQuery: function (sql, args) {
        this._dataAdapter.setQuery(sql, args);
        this.invalidateAll();
      },
      getNotificationHandler: function () {
        return this._dataAdapter.getNotificationHandler();
      }
    }
  );

  GroupDataSource = WinJS.Class.derive(WinJS.UI.VirtualizedDataSource,
    function (db, sql, args, keyColumnName, sizeColumnName) {
      var dataAdapter = {
        _keyIndexMap: {},
        _ensureGroupsAsync: function () {
          if (dataAdapter._groups) {
            return WinJS.Promise.wrap();
          }

          var groupIndex = 0,
              firstItemIndex = 0;
          return db.mapAsync(sql, args, function (row) {
            var item = {
              key: row[keyColumnName].toString(),
              groupSize: row[sizeColumnName],
              firstItemIndexHint: firstItemIndex,
              data: row
            };

            dataAdapter._keyIndexMap[item.key] = groupIndex;
            groupIndex += 1;
            firstItemIndex += item.groupSize;

            return item;
          }).then(function (groups) {
            dataAdapter._groups = groups.filter(function (group) { return group.groupSize > 0; });
          });
        },
        getCount: function () {
          return dataAdapter._ensureGroupsAsync().then(function () {
            return dataAdapter._groups.length;
          });
        },
        itemsFromIndex: function (requestIndex, countBefore, countAfter) {
          return dataAdapter._ensureGroupsAsync().then(function () {
            return {
              items: dataAdapter._groups.slice(),
              offset: requestIndex,
              absoluteIndex: requestIndex,
              totalCount: dataAdapter._groups.length,
              atStart: true,
              atEnd: true
            };
          });
        },
        itemsFromKey: function (key, countBefore, countAfter) {
          return dataAdapter._ensureGroupsAsync().then(function () {
            return dataAdapter.itemsFromIndex(dataAdapter._keyIndexMap[key], countBefore, countAfter);
          });
        },
        setNotificationHandler: function (notificationHandler) {
          this._notificationHandler = notificationHandler;
        },
        getNotificationHandler: function () {
          return this._notificationHandler;
        }
      };
      this._dataAdapter = dataAdapter;
      this._baseDataSourceConstructor(dataAdapter);
    }, {
      getNotificationHandler: function () {
        return this._dataAdapter.getNotificationHandler();
      }
    }
  );

  SQLite3JS.openAsync = function (dbPath) {
    /// <summary>
    /// Opens a database from disk or in memory.
    /// </summary>
    /// <param name="dbPath" type="String">
    /// Path to a file that is located in your apps local/temp/roaming storage or the string ":memory:"
    /// to create a database in memory
    /// </param>
    /// <returns>Database object upon completion of the promise</returns>
    return SQLite3.Database.openAsync(dbPath)
    .then(function opened(connection) {
      var db = wrapDatabase(connection);
      if (SQLite3JS.version) {
        return db;
      }
      return db.oneAsync("SELECT sqlite_version() || ' (' || sqlite_source_id() || ')' as version")
      .then(function (result) {
        SQLite3JS.logger.info("SQLite3 version: " + (SQLite3JS.version = result.version));
        return db;
      });
    }, function onerror(error) {
      return wrapException(error, 'Could not open database "' + dbPath + '"', "openAsync");
    });
  };

  return SQLite3JS;
}());
<commit_msg>Only log statement when it's actually executed<commit_after>var SQLite3JS = (function () {
  "use strict";

  var SQLite3JS, Database, ItemDataSource, GroupDataSource;

  SQLite3JS = {
    /// Set this to true to get some more logging output
    debug: false,
    logger: {
      trace: console.log.bind(console),
      warn: console.warn.bind(console),
      error: console.error.bind(console),
      info: console.info.bind(console)
    }
  };

  function PromiseQueue() {
    this._items = [];
    this._busy = false;
  }

  PromiseQueue.prototype.append = function (createPromise) {
    var wrappingPromise,
        queueItem = { createPromise: createPromise },
        _this = this;

    wrappingPromise = new WinJS.Promise(function (complete, error) {
      queueItem.complete = complete;
      queueItem.error = error;
    }, function () {
      if (queueItem.promise) {
        queueItem.promise.cancel();
      } else {
        queueItem.cancelled = true;
      }

      _this._handleNext();
    });

    this._items.push(queueItem);
    if (!this._busy) {
      this._handleNext();
    }

    return wrappingPromise;
  };

  PromiseQueue.prototype._handleNext = function () {
    var _this = this;
    /* shorten call stack */
    this._busy = true;
    setImmediate(function () {
      if (_this._items.length > 0) {
        var nextItem = _this._items[0];
        _this._items = _this._items.slice(1);
        _this._handleItem(nextItem);
      } else {
        _this._busy = false;
      }
    });
  };

  PromiseQueue.prototype._handleItem = function (queueItem) {
    var _this = this;

    if (!queueItem.cancelled) {
      queueItem.promise = queueItem.createPromise();
      queueItem.promise.done(function (result) {
        _this._handleNext();
        queueItem.complete(result);
      }, function (error) {
        _this._handleNext();
        queueItem.error(error);
      });
    } else {
      this._handleNext();
    }
  };

  function toPropertySet(object) {
    var key, propertySet = new Windows.Foundation.Collections.PropertySet();

    for (key in object) {
      if (object.hasOwnProperty(key)) {
        propertySet.insert(key, object[key]);
      }
    }

    return propertySet;
  }

  function prepareArgs(args) {
    args = args || [];
    return (args instanceof Array) ? args : toPropertySet(args);
  }

  function formatStatementAndArgs(sql, args) {
    var argString = args ? ' ' + args.toString() : '';
    return '"' + sql + '", ' + argString;
  }

  function wrapException(exception, detailedMessage, functionName, sql, args) {
    var error, message, resultCode, number;

    if (exception.hasOwnProperty('number')) {
      // Convert the COM error to an unsigned hex value that we can check in JS like E_FAIL == 0x80004005
      number = 0xffffffff + exception.number + 1;
      resultCode = number & 0x20000000 ? exception.number & 0xffff : 0;
      message = (resultCode > 0 ? resultCode : "0x" + number.toString(16)) + ": ";
      if (functionName) {
        message += functionName;

        if (sql) {
          message += '(' + formatStatementAndArgs(sql, args) + ') ';
        } else {
          message += " ";
        }
      }
      if (detailedMessage) {
        message += detailedMessage;
      }
      error = new WinJS.ErrorFromName("SQLiteError", message);
      error.resultCode = resultCode;
      error.number = number;
      error.sql = sql;
      error.args = args;
      error.functionName = functionName;
    } else {
      error = exception;
    }

    return WinJS.Promise.wrapError(error);
  }

  function wrapDatabase(connection) {
    var that, queue = new PromiseQueue();

    function callNativeAsync(funcName, sql, args, callback) {
      var argString, preparedArgs, fullFuncName;

      return queue.append(function () {
        if (SQLite3JS.debug) {
          SQLite3JS.logger.trace(funcName + ': ' + formatStatementAndArgs(sql, args));
        }
        preparedArgs = prepareArgs(args);
        fullFuncName =
          preparedArgs instanceof Windows.Foundation.Collections.PropertySet
          ? funcName + "Map"
          : funcName + "Vector";

        return connection[fullFuncName](sql, preparedArgs, callback).then(null, function (error) {
          return wrapException(error, that.lastError, funcName, sql, args);
        });
      });
    }

    that = {
      runAsync: function (sql, args) {
        return callNativeAsync('runAsync', sql, args).then(function (affectedRowCount) {
          return affectedRowCount;
        });
      },
      oneAsync: function (sql, args) {
        return callNativeAsync('oneAsync', sql, args).then(function (row) {
          return row ? JSON.parse(row) : null;
        });
      },
      allAsync: function (sql, args) {
        return callNativeAsync('allAsync', sql, args).then(function (rows) {
          return rows ? JSON.parse(rows) : null;
        });
      },
      eachAsync: function (sql, args, callback) {
        if (!callback && typeof args === 'function') {
          callback = args;
          args = undefined;
        }

        return callNativeAsync('eachAsync', sql, args, function (row) {
          callback(JSON.parse(row));
        }).then(function () {
          return that;
        });
      },
      mapAsync: function (sql, args, callback) {
        if (!callback && typeof args === 'function') {
          callback = args;
          args = undefined;
        }

        var results = [];

        return that.eachAsync(sql, args, function (row) {
          results.push(callback(row));
        }).then(function () {
          return results;
        });
      },
      itemDataSource: function (sql, args, keyColumnName, groupKeyColumnName) {
        if (typeof args === 'string') {
          groupKeyColumnName = keyColumnName;
          keyColumnName = args;
          args = undefined;
        }

        return new ItemDataSource(that, sql, args, keyColumnName, groupKeyColumnName);
      },
      groupDataSource: function (sql, args, keyColumnName, sizeColumnName) {
        if (typeof args === 'string') {
          sizeColumnName = keyColumnName;
          keyColumnName = args;
          args = undefined;
        }

        return new GroupDataSource(that, sql, args, keyColumnName, sizeColumnName);
      },
      close: function () {
        connection.close();
      },
      vacuumAsync: function () {
        return new WinJS.Promise( function(complete) {
          connection.vacuumAsync();
          complete();
        });
      },
      addEventListener: connection.addEventListener.bind(connection),
      removeEventListener: connection.removeEventListener.bind(connection)
    };

    Object.defineProperties(
      that,
      WinJS.Utilities.createEventProperties('update', 'delete', 'insert')
    );

    Object.defineProperties(that, {
      "collationLanguage": {
        set: function (value) { connection.collationLanguage = value; },
        get: function () { return connection.collationLanguage; },
        enumerable: true
      },
      "fireEvents": {
        set: function (value) { connection.fireEvents = value; },
        get: function () { return connection.fireEvents; },
        enumerable: true
      },
      "lastError": {
        get: function () { return connection.lastError; },
        enumerable: true
      },
      "autoCommit": {
        get: function () { return connection.autoCommit; },
        enumerable: true
      },
      "lastInsertRowId": {
        get: function () { return connection.lastInsertRowId; },
        enumerable: true
      }
    });

    return that;
  }

  ItemDataSource = WinJS.Class.derive(WinJS.UI.VirtualizedDataSource,
    function (db, sql, args, keyColumnName, groupKeyColumnName) {
      this._dataAdapter = {
        setQuery: function (sql, args) {
          this._sql = sql;
          this._args = args;
        },
        getCount: function () {
          return db.oneAsync('SELECT COUNT(*) AS cnt FROM (' + this._sql + ')', this._args)
          .then(function (row) { return row.cnt; });
        },
        itemsFromIndex: function (requestIndex, countBefore, countAfter) {
          var items,
              limit = countBefore + 1 + countAfter,
              offset = requestIndex - countBefore,
              that = this;

          return this.getCount().then(function (totalCount) {
            return db.mapAsync(
              'SELECT * FROM (' + that._sql + ') LIMIT ' + limit + ' OFFSET ' + offset,
              that._args,
              function (row) {
                var item = {
                  key: row[keyColumnName].toString(),
                  data: row
                };
                if (groupKeyColumnName) {
                  if (!row.hasOwnProperty(groupKeyColumnName) || row[groupKeyColumnName] === null) {
                    throw "Group key property not found: " + groupKeyColumnName;
                  }
                  item.groupKey = row[groupKeyColumnName].toString();
                }
                return item;
              }).then(function (items) {
                return {
                  items: items,
                  offset: countBefore,
                  totalCount: totalCount
                };
              });
          });
        },
        setNotificationHandler: function (notificationHandler) {
          this._notificationHandler = notificationHandler;
        },
        getNotificationHandler: function () {
          return this._notificationHandler;
        }
      };

      this._dataAdapter.setQuery(sql, args);
      this._baseDataSourceConstructor(this._dataAdapter);
    }, {
      setQuery: function (sql, args) {
        this._dataAdapter.setQuery(sql, args);
        this.invalidateAll();
      },
      getNotificationHandler: function () {
        return this._dataAdapter.getNotificationHandler();
      }
    }
  );

  GroupDataSource = WinJS.Class.derive(WinJS.UI.VirtualizedDataSource,
    function (db, sql, args, keyColumnName, sizeColumnName) {
      var dataAdapter = {
        _keyIndexMap: {},
        _ensureGroupsAsync: function () {
          if (dataAdapter._groups) {
            return WinJS.Promise.wrap();
          }

          var groupIndex = 0,
              firstItemIndex = 0;
          return db.mapAsync(sql, args, function (row) {
            var item = {
              key: row[keyColumnName].toString(),
              groupSize: row[sizeColumnName],
              firstItemIndexHint: firstItemIndex,
              data: row
            };

            dataAdapter._keyIndexMap[item.key] = groupIndex;
            groupIndex += 1;
            firstItemIndex += item.groupSize;

            return item;
          }).then(function (groups) {
            dataAdapter._groups = groups.filter(function (group) { return group.groupSize > 0; });
          });
        },
        getCount: function () {
          return dataAdapter._ensureGroupsAsync().then(function () {
            return dataAdapter._groups.length;
          });
        },
        itemsFromIndex: function (requestIndex, countBefore, countAfter) {
          return dataAdapter._ensureGroupsAsync().then(function () {
            return {
              items: dataAdapter._groups.slice(),
              offset: requestIndex,
              absoluteIndex: requestIndex,
              totalCount: dataAdapter._groups.length,
              atStart: true,
              atEnd: true
            };
          });
        },
        itemsFromKey: function (key, countBefore, countAfter) {
          return dataAdapter._ensureGroupsAsync().then(function () {
            return dataAdapter.itemsFromIndex(dataAdapter._keyIndexMap[key], countBefore, countAfter);
          });
        },
        setNotificationHandler: function (notificationHandler) {
          this._notificationHandler = notificationHandler;
        },
        getNotificationHandler: function () {
          return this._notificationHandler;
        }
      };
      this._dataAdapter = dataAdapter;
      this._baseDataSourceConstructor(dataAdapter);
    }, {
      getNotificationHandler: function () {
        return this._dataAdapter.getNotificationHandler();
      }
    }
  );

  SQLite3JS.openAsync = function (dbPath) {
    /// <summary>
    /// Opens a database from disk or in memory.
    /// </summary>
    /// <param name="dbPath" type="String">
    /// Path to a file that is located in your apps local/temp/roaming storage or the string ":memory:"
    /// to create a database in memory
    /// </param>
    /// <returns>Database object upon completion of the promise</returns>
    return SQLite3.Database.openAsync(dbPath)
    .then(function opened(connection) {
      var db = wrapDatabase(connection);
      if (SQLite3JS.version) {
        return db;
      }
      return db.oneAsync("SELECT sqlite_version() || ' (' || sqlite_source_id() || ')' as version")
      .then(function (result) {
        SQLite3JS.logger.info("SQLite3 version: " + (SQLite3JS.version = result.version));
        return db;
      });
    }, function onerror(error) {
      return wrapException(error, 'Could not open database "' + dbPath + '"', "openAsync");
    });
  };

  return SQLite3JS;
}());
<|endoftext|>


<commit_before>/*!
 *
 * Copyright (c) 2013 Sebastian Golasch
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

'use strict';

// ext. libs
var Q = require('q');

/**
 * Loads the webdriver client,
 * launches the browser,
 * initializes al object properties,
 * binds to browser events
 *
 * @param {object} opts Options needed to kick off the driver
 * @constructor
 */

var DummyBrowser = function (driver) {
  this.driver = driver;
};

/**
 * Verfies a given browser config & mimics a
 * real browser while using the Sauce infrstructure
 *
 * @module Driver
 * @class Browser
 * @namespace Dalek
 */

DummyBrowser.prototype = {

  /**
   * Sauce labs authentication realm (user:key)
   *
   * @property auth
   * @type {string|null}
   */

  auth: null,

  /**
   * Browser session config
   *
   * @property sessionConfig
   * @type {object}
   */

  sessionConfig: {},

  /**
   * Saucelabs remote webdriver path
   *
   * @property path
   * @type {string}
   * @default /wd/hub
   */

  path: '/wd/hub',

  /**
   * Saucelabs remote port
   *
   * @property port
   * @type {integer}
   * @default 80
   */

  port: 80,

  /**
   * Saucelabs remote host
   *
   * @property host
   * @type {string}
   * @default host
   */

  host: 'ondemand.saucelabs.com',

  /**
   * Available browsers with their default capabilities
   *
   * @property browsers
   * @type {object}
   */

  browsers: {
    'iphone': {platform: 'OS X 10.8', version: '6', longName: 'iOS Safari (iPhone)'},
    'ipad': {platform: 'OS X 10.8', version: '6', longName: 'iOS Safari (iPad)'},
    'android': {platform: 'Linux', version: '4.0', longName: 'Chrome on Android'},
    'firefox': {platform: 'OS X 10.6', version: '25', longName: 'Mozilla Firefox'},
    'internet explorer': {platform: 'Windows 8', version: '10', longName: 'Internet Explorer'},
    'chrome': {platform: 'OS X 10.6', version: '28', longName: 'Google Chrome'},
    'opera': {platform: 'Windows 7', version: '12', longName: 'Opera'},
    'safari': {platform: 'OS X 10.8', version: '6', longName: 'Safari'}
  },

  /**
   * Default verbose browser name
   *
   * @property longName
   * @type {string}
   */

  longName: 'Mozilla Firefox',

  /**
   * Default desired capabilities
   *
   * @property desiredCapabilities
   * @type {object}
   */

  desiredCapabilities: {
    platform: 'OS X 10.8',
    browserName: 'chrome',
    'browser-version': 'latest',
    name: 'Dalek Testsuite'
  },

  /**
   * Driver defaults
   *
   * @property driverDefaults
   * @type {object}
   */

  driverDefaults: {
    viewport: true,
    status: {
      os: {
        name: 'Linux',
        version: null,
        arch: null
      }
    },
    sessionInfo: true
  },

  /**
   * Available platforms
   *
   * @property platforms
   * @type {array}
   */

  platforms: ['Windows 8', 'Windows 7', 'Windows XP', 'OS X 10.8', 'OS X 10.7', 'OS X 10.6', 'Linux'],

  /**
   * Stores & validates the incoming browser config
   *
   * @method launch
   * @param {object} configuration Browser configuration
   * @param {EventEmitter2} events EventEmitter (Reporter Emitter instance)
   * @param {Dalek.Internal.Config} config Dalek configuration class
   * @return {object} Browser promise
   */

  launch: function (configuration, events, config) {
    var deferred = Q.defer();

    // override desired capabilities, status & browser longname
    this.desiredCapabilities = this._generateDesiredCaps(configuration.name, config);
    this.driverDefaults.status = this._generateStatusInfo(this.desiredCapabilities);
    this.longName = this._generateLongName(this.desiredCapabilities);

    // store injected configuration/log event handlers
    this.reporterEvents = events;
    this.configuration = configuration;
    this.config = config;

    // immediatly resolve the deferred
    deferred.resolve();
    return deferred.promise;
  },

  /**
   * Kills the remote browser
   * TODO: Close the remote session
   *
   * @method kill
   * @return {object} Promise
   */

  kill: function () {
    var deferred = Q.defer();
    deferred.resolve();
    return deferred.promise;
  },

  /**
   * Generates the status defaults for the OS configuration
   *
   * @method getStatusDefaults
   * @param {object} desiredCapabilities Desired capabilities
   * @param {object} desiredCapabilities Desired capabilities
   * @return {object} OS status information
   */

  getDesiredCapabilities: function (browserName, config) {
    return this._generateDesiredCaps(browserName, config);
  },

  /**
   * Generates the status defaults for the OS configuration
   *
   * @method getStatusDefaults
   * @param {object} desiredCapabilities Desired capabilities
   * @return {object} OS status information
   */

  getStatusDefaults: function (desiredCapabilities) {
    return this._generateStatusInfo(desiredCapabilities);
  },

  /**
   * Sets the sauce authentication token
   *
   * @method setAuth
   * @param {string} user Sauce labs username
   * @param {string} key Sauce labs key
   * @chainable
   */

  setAuth: function (user, key) {
    this.auth = user + ':' + key;
    return this;
  },

  /**
   * Verifies the browser config
   *
   * @method _verfiyBrowserConfig
   * @param {string} browserName Name of the browser to verify
   * @param {object} config Daleks internal config helper
   * @return {object} Browser config
   * @private
   */

  _verfiyBrowserConfig: function (browserName, config) {
    var browsers = config.get('browsers');
    var browser = browsers[0][browserName] || null;

    // check if we couldnt find a configured alias,
    // check and apply if there is a default config
    if (!browser && this.browsers[browserName]) {
      browser = this.browsers[browserName];
    }
    // check if we couldnt find a configured alias,
    // set to defaults otherwise
    if (!browser) {
      return {actAs: this.desiredCapabilities.browserName, version: this.desiredCapabilities['browser-version']};
    }

    // check if the actas property has been set, if not
    // use the given browser name
    if (!browser.actAs) {
      browser.actAs = browserName;
    }

    return browser;
  },

  /**
   * Verfies the OS platform config
   *
   * @method _verfiyPlatformConfig
   * @param {object} browser Browser information
   * @return {string} Platform
   * @private
   */

  _verfiyPlatformConfig: function (browser) {
    var bp = null;
    var isValid = this.platforms.reduce(function (previousValue, platform) {
      if (bp) {
        return bp;
      }

      if (platform === browser.platform) {
        bp = browser.platform;
        return browser.platform;
      }
    });

    return isValid || this.desiredCapabilities.platform;
  },

  /**
   * Generates the desired capabilities for this session
   *
   * @method _generateDesiredCaps
   * @param {string} browserName The browser name
   * @param {object} config Daleks internal config helper
   * @return {object} The sessions desired capabilities
   * @private
   */

  _generateDesiredCaps: function (browserName, config) {
    var browser = this._verfiyBrowserConfig(browserName, config);
    var platform = this._verfiyPlatformConfig(browser);
    var driverConfig = config.get('driver.sauce');
    var desiredCaps = {
      browserName: browser.actAs,
      platform: platform,
      'browser-version': (browser.version || this.desiredCapabilities['browser-version']),
      name: driverConfig.name || this.desiredCapabilities.name
    };

    // check if the user added tags
    if (driverConfig.tags) {
      desiredCaps.tags = driverConfig.tags;
    }

    // check if the user added a build id
    if (driverConfig.build) {
      desiredCaps.build = driverConfig.build;
    }

    return desiredCaps;
  },

  /**
   * Generates OS status information
   *
   * @method _generateStatusInfo
   * @param {object} desiredCaps The sessions desired capabilities
   * @return {object} OS status information
   * @private
   */

  _generateStatusInfo: function (desiredCaps) {
    return {os: {name: desiredCaps.platform, arch: null, version: null}};
  },

  /**
   * Generates the verbose name of the current remote browser in use
   *
   * @method _generateLongName
   * @param {object} desiredCaps The sessions desired capabilities
   * @return {string} Verbose browser name
   * @private
   */

  _generateLongName: function (desiredCaps) {
    return this.browsers[desiredCaps.browserName].longName || null;
  }
};

module.exports = DummyBrowser;<commit_msg>compatibility fixed<commit_after>/*!
 *
 * Copyright (c) 2013 Sebastian Golasch
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

'use strict';

// ext. libs
var Q = require('q');

/**
 * Loads the webdriver client,
 * launches the browser,
 * initializes al object properties,
 * binds to browser events
 *
 * @param {object} opts Options needed to kick off the driver
 * @constructor
 */

var DummyBrowser = function (driver) {
  this.driver = driver;
};

/**
 * Verfies a given browser config & mimics a
 * real browser while using the Sauce infrstructure
 *
 * @module Driver
 * @class Browser
 * @namespace Dalek
 */

DummyBrowser.prototype = {

  /**
   * Sauce labs authentication realm (user:key)
   *
   * @property auth
   * @type {string|null}
   */

  auth: null,

  /**
   * Browser session config
   *
   * @property sessionConfig
   * @type {object}
   */

  sessionConfig: {},

  /**
   * Saucelabs remote webdriver path
   *
   * @property path
   * @type {string}
   * @default /wd/hub
   */

  path: '/wd/hub',

  /**
   * Saucelabs remote port
   *
   * @property port
   * @type {integer}
   * @default 80
   */

  port: 80,

  /**
   * Saucelabs remote host
   *
   * @property host
   * @type {string}
   * @default host
   */

  host: 'ondemand.saucelabs.com',

  /**
   * Available browsers with their default capabilities
   *
   * @property browsers
   * @type {object}
   */

  browsers: {
    'iphone': {platform: 'OS X 10.8', version: '6', longName: 'iOS Safari (iPhone)'},
    'ipad': {platform: 'OS X 10.8', version: '6', longName: 'iOS Safari (iPad)'},
    'android': {platform: 'Linux', version: '4.0', longName: 'Chrome on Android'},
    'firefox': {platform: 'OS X 10.6', version: '25', longName: 'Mozilla Firefox'},
    'internet explorer': {platform: 'Windows 8', version: '10', longName: 'Internet Explorer'},
    'chrome': {platform: 'OS X 10.6', version: '28', longName: 'Google Chrome'},
    'opera': {platform: 'Windows 7', version: '12', longName: 'Opera'},
    'safari': {platform: 'OS X 10.8', version: '6', longName: 'Safari'}
  },

  /**
   * Default verbose browser name
   *
   * @property longName
   * @type {string}
   */

  longName: 'Mozilla Firefox',

  /**
   * Default desired capabilities
   *
   * @property desiredCapabilities
   * @type {object}
   */

  desiredCapabilities: {
    platform: 'OS X 10.8',
    browserName: 'chrome',
    'browser-version': 'latest',
    name: 'Dalek Testsuite'
  },

  /**
   * Driver defaults
   *
   * @property driverDefaults
   * @type {object}
   */

  driverDefaults: {
    viewport: false,
    status: {
      os: {
        name: 'Linux',
        version: null,
        arch: null
      }
    },
    sessionInfo: true
  },

  /**
   * Available platforms
   *
   * @property platforms
   * @type {array}
   */

  platforms: ['Windows 8.1', 'Windows 8', 'Windows 7', 'Windows XP', 'OS X 10.9', 'OS X 10.8', 'OS X 10.7', 'OS X 10.6', 'Linux'],

  /**
   * Stores & validates the incoming browser config
   *
   * @method launch
   * @param {object} configuration Browser configuration
   * @param {EventEmitter2} events EventEmitter (Reporter Emitter instance)
   * @param {Dalek.Internal.Config} config Dalek configuration class
   * @return {object} Browser promise
   */

  launch: function (configuration, events, config) {
    var deferred = Q.defer();

    // override desired capabilities, status & browser longname
    this.desiredCapabilities = this._generateDesiredCaps(configuration.name, config);
    this.driverDefaults.status = this._generateStatusInfo(this.desiredCapabilities);
    this.longName = this._generateLongName(configuration.name,config);

    // store injected configuration/log event handlers
    this.reporterEvents = events;
    this.configuration = configuration;
    this.config = config;

    // immediatly resolve the deferred
    deferred.resolve();
    return deferred.promise;
  },

  /**
   * Kills the remote browser
   * TODO: Close the remote session
   *
   * @method kill
   * @return {object} Promise
   */

  kill: function () {
    var deferred = Q.defer();
    deferred.resolve();
    return deferred.promise;
  },

  /**
   * Generates the status defaults for the OS configuration
   *
   * @method getStatusDefaults
   * @param {object} desiredCapabilities Desired capabilities
   * @param {object} desiredCapabilities Desired capabilities
   * @return {object} OS status information
   */

  getDesiredCapabilities: function (browserName, config) {
    return this._generateDesiredCaps(browserName, config);
  },

  /**
   * Generates the status defaults for the OS configuration
   *
   * @method getStatusDefaults
   * @param {object} desiredCapabilities Desired capabilities
   * @return {object} OS status information
   */

  getStatusDefaults: function (desiredCapabilities) {
    return this._generateStatusInfo(desiredCapabilities);
  },

  /**
   * Sets the sauce authentication token
   *
   * @method setAuth
   * @param {string} user Sauce labs username
   * @param {string} key Sauce labs key
   * @chainable
   */

  setAuth: function (user, key) {
    this.auth = user + ':' + key;
    return this;
  },

  /**
   * Verifies the browser config
   *
   * @method _verfiyBrowserConfig
   * @param {string} browserName Name of the browser to verify
   * @param {object} config Daleks internal config helper
   * @return {object} Browser config
   * @private
   */

  _verfiyBrowserConfig: function (browserName, config) {
    var browsers = config.get('browsers');
    var browser = browsers[0][browserName] || null;

    // check if we couldnt find a configured alias,
    // check and apply if there is a default config
    if (!browser && this.browsers[browserName]) {
      browser = this.browsers[browserName];
    }
    // check if we couldnt find a configured alias,
    // set to defaults otherwise
    if (!browser) {
      return {actAs: this.desiredCapabilities.browserName, version: this.desiredCapabilities['browser-version']};
    }

    // check if the actas property has been set, if not
    // use the given browser name
    if (!browser.actAs) {
      browser.actAs = browserName;
    }

    return browser;
  },

  /**
   * Verfies the OS platform config
   *
   * @method _verfiyPlatformConfig
   * @param {object} browser Browser information
   * @return {string} Platform
   * @private
   */

  _verfiyPlatformConfig: function (browser) {
    var bp = null;
    var isValid = this.platforms.reduce(function (previousValue, platform) {
      if (bp) {
        return bp;
      }
      if (platform === browser.platform || previousValue === browser.platform) {
        bp = browser.platform;
        return browser.platform;
      }
    });
    return isValid || this.desiredCapabilities.platform;
  },

  /**
   * Generates the desired capabilities for this session
   *
   * @method _generateDesiredCaps
   * @param {string} browserName The browser name
   * @param {object} config Daleks internal config helper
   * @return {object} The sessions desired capabilities
   * @private
   */

  _generateDesiredCaps: function (browserName, config) {
    var browser = this._verfiyBrowserConfig(browserName, config);
    var platform = this._verfiyPlatformConfig(browser);
    var driverConfig = config.get('driver.sauce');
    var desiredCaps = {
      browserName: browser.actAs,
      platform: platform,
      'screen-resolution': (browser['screen-resolution'] || null),
      version: (browser.version || this.desiredCapabilities['browser-version']),
      name: driverConfig.name || this.desiredCapabilities.name
    };

    // check if the user added tags
    if (driverConfig.tags) {
      desiredCaps.tags = driverConfig.tags;
    }

    // check if the user added a build id
    if (driverConfig.build) {
      desiredCaps.build = driverConfig.build;
    }
    return desiredCaps;
  },

  /**
   * Generates OS status information
   *
   * @method _generateStatusInfo
   * @param {object} desiredCaps The sessions desired capabilities
   * @return {object} OS status information
   * @private
   */

  _generateStatusInfo: function (desiredCaps) {
    return {os: {name: desiredCaps.platform, arch: null, version: null}};
  },

  /**
   * Generates the verbose name of the current remote browser in use
   *
   * @method _generateLongName
   * @param {object} desiredCaps The sessions desired capabilities
   * @return {string} Verbose browser name
   * @private
   */

  _generateLongName: function (browserName, config) {
    var longName = null;
    if(this.browsers.hasOwnProperty(browserName)){
      longName = this.browsers[browserName].longName;
    }
    if(config.get('browsers')[0].hasOwnProperty(browserName)){
      longName = config.get('browsers')[0][browserName].longName;
    }
    return longName;
  }
};

module.exports = DummyBrowser;<|endoftext|>


<commit_before>// @flow

export type AppConstType = {|
    api: {
        url: string
    }
|};

const appConst: AppConstType = {
    api: {
        url: 'http://localhost:3001'
    }
};

export default appConst;
<commit_msg>join room - in progress...<commit_after>// @flow
/* global window */

export type AppConstType = {|
    api: {
        url: string
    }
|};

const appConst: AppConstType = {
    api: {
        url: 'http://' + window.location.hostname + ':3001'
    }
};

export default appConst;
<|endoftext|>


<commit_before>import Base from './base';
import layout from '../../templates/components/g-map/info-window';
import { computed, get, getProperties, observer, set } from '@ember/object';
import { reads } from '@ember/object/computed';
import { schedule } from '@ember/runloop';

export default Base.extend({
  layout,

  _type: 'infoWindow',

  _ignoreAttrs: ['isOpen'],
  _requiredOptions: ['content'],

  isOpen: false,

  position: computed('lat', 'lng', function() {
    const { lat, lng } = getProperties(this, 'lat', 'lng');
    return new google.maps.LatLng(lat, lng);
  }),

  // This can be done using didReceiveAttrs + _didAddComponent, but this ends up
  // being less code.
  isOpenObserver: observer('isOpen', '_isInitialized', function() {
    if (this._isInitialized) {
      if (get(this, 'isOpen')) {
        this.open();
      } else {
        this.close();
      }
    }
  }),

  init() {
    this._super(...arguments);
    if (!get(this, 'target')) {
      this._requiredOptions = this._requiredOptions.concat(['position']);
    }
  },

  _addComponent() {
    this._prepareContent();
    let options = get(this, '_options');
    delete options.map;
    set(this, 'mapComponent', new google.maps.InfoWindow(options));
    this._didAddComponent();
  },

  _prepareContent() {
    if (!get(this, 'content')) {
      const content = document.createElement('div');
      set(this, '_targetPane', content);
      set(this, 'content', content);
    }
  },

  open() {
    schedule('actions', () => {
      if (this.mapComponent) {
        google.maps.event.addListenerOnce(this.mapComponent, 'closeclick', () => {
          set(this, 'isOpen', false);
        });
        this.mapComponent.open(get(this, 'map'), get(this, 'target'));
      }
    });
  },

  close() {
    schedule('actions', () => {
      this.mapComponent && this.mapComponent.close();
    });
  }
});
<commit_msg>Lint info-window<commit_after>import Base from './base';
import layout from '../../templates/components/g-map/info-window';
import { computed, get, getProperties, observer, set } from '@ember/object';
import { schedule } from '@ember/runloop';

export default Base.extend({
  layout,

  _type: 'infoWindow',

  _ignoreAttrs: ['isOpen'],
  _requiredOptions: ['content'],

  isOpen: false,

  position: computed('lat', 'lng', function() {
    const { lat, lng } = getProperties(this, 'lat', 'lng');
    return new google.maps.LatLng(lat, lng);
  }),

  // This can be done using didReceiveAttrs + _didAddComponent, but this ends up
  // being less code.
  isOpenObserver: observer('isOpen', '_isInitialized', function() {
    if (this._isInitialized) {
      if (get(this, 'isOpen')) {
        this.open();
      } else {
        this.close();
      }
    }
  }),

  init() {
    this._super(...arguments);
    if (!get(this, 'target')) {
      this._requiredOptions = this._requiredOptions.concat(['position']);
    }
  },

  _addComponent() {
    this._prepareContent();
    let options = get(this, '_options');
    delete options.map;
    set(this, 'mapComponent', new google.maps.InfoWindow(options));
    this._didAddComponent();
  },

  _prepareContent() {
    if (!get(this, 'content')) {
      const content = document.createElement('div');
      set(this, '_targetPane', content);
      set(this, 'content', content);
    }
  },

  open() {
    schedule('actions', () => {
      if (this.mapComponent) {
        google.maps.event.addListenerOnce(this.mapComponent, 'closeclick', () => {
          set(this, 'isOpen', false);
        });
        this.mapComponent.open(get(this, 'map'), get(this, 'target'));
      }
    });
  },

  close() {
    schedule('actions', () => {
      this.mapComponent && this.mapComponent.close();
    });
  }
});
<|endoftext|>


<commit_before>exports.config = {
	baseUrl: 'http://localhost:8080/',
	seleniumAddress: 'http://127.0.0.1:4444/wd/hub',

	specs: [
		'src/**/*.e2e-spec.js'
	],
	exclude: [],

	framework: 'jasmine2',

	allScriptsTimeout: 110000,

	jasmineNodeOpts: {
		showTiming: true,
		showColors: true,
		isVerbose: true,
		includeStackTrace: true,
		defaultTimeoutInterval: 400000
	},
	directConnect: true,

	capabilities: {
		'browserName': 'chrome'
	},

	onPrepare: function () {
		jasmine.getEnv().addReporter(
			new Jasmine2HtmlReporter({
				savePath: 'screenshots'
			})
		)
	},

	/**
	 * Angular 2 configuration
	 *
	 * useAllAngular2AppRoots: tells Protractor to wait for any angular2 apps on the page instead of just the one matching
	 * `rootEl`
	 *
	 */
	useAllAngular2AppRoots: true
};<commit_msg>protractor: Change conf<commit_after>exports.config = {
	baseUrl: 'http://localhost:8080/',

	specs: [
		'src/**/*.e2e-spec.js'
	],
	exclude: [],

	framework: 'jasmine2',

	allScriptsTimeout: 110000,

	jasmineNodeOpts: {
		showTiming: true,
		showColors: true,
		isVerbose: false,
		includeStackTrace: false,
		defaultTimeoutInterval: 400000
	},
	directConnect: true,

	capabilities: {
		'browserName': 'chrome'
	},

	onPrepare: function () {
		var SpecReporter = require('jasmine-spec-reporter').SpecReporter;
		// add jasmine spec reporter
		jasmine.getEnv().addReporter(new SpecReporter({displayStacktrace: true}));

		browser.ignoreSynchronization = true;
	},

	/**
	 * Angular 2 configuration
	 *
	 * useAllAngular2AppRoots: tells Protractor to wait for any angular2 apps on the page instead of just the one matching
	 * `rootEl`
	 *
	 */
	useAllAngular2AppRoots: true
};<|endoftext|>


<commit_before>/*
    hapi-nes WebSocket Client
    Copyright (c) 2015, Eran Hammer <eran@hammer.io> and other contributors
    BSD Licensed
*/
(function (root, factory) {

    // $lab:coverage:off$
    // Export if used as a module
    if (typeof exports === 'object' && typeof module === 'object') {
        module.exports = factory();
    } else if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports === 'object') {
        exports.nes = factory();
    } else {
        root.nes = factory();
    }
    // $lab:coverage:on$
})(this, function () {
    // Declare namespace

    var nes = {
        internals: {
            ignore: function () { },

            // Using just require here vs proper UMD binding as we assume WebSocket is available through
            // native bindings in all environments that you'd do something silly like use AMD or globals
            WebSocket: /* $lab:coverage:off$ */ (typeof WebSocket === 'undefined' ? require('ws') : WebSocket) /* $lab:coverage:on$ */
        }
    };

    nes.Client = function () {

        this._ws = null;
        this._ids = 0;                              // Id counter
        this._requests = {};                        // id -> callback

        this.onerror = nes.internals.ignore;        // General error callback (only when an error cannot be associated with a request)
    };

    nes.Client.prototype.connect = function (url, callback) {

        var self = this;

        var ws = new nes.internals.WebSocket(url);
        this._ws = ws;

        var sentCallback = false;
        ws.onopen = function () {

            if (!sentCallback) {
                sentCallback = true;
                return callback();
            }
        };

        ws.onerror = function (err) {

            if (!sentCallback) {
                sentCallback = true;
                return callback(err);
            }

            return self.onerror(err);
        };

        ws.onclose = function () {

            return self._onClose();
        };

        ws.onmessage = function (message) {

            return self._onMessage(message);
        };
    };

    nes.Client.prototype.disconnect = function () {

        if (!this._ws) {
            return;
        }

        if (this._ws.readyState === 1 ||                    // Open
            this._ws.readyState === 0) {                    // Connecting

            this._ws.close();
        }
    };

    nes.Client.prototype.request = function (method, path, callback) {

        var self = this;

        if (!this._ws ||
            this._ws.readyState !== 1) {                    // Open

            return callback(new Error('Disconnected'));
        }

        var request = {
            id: ++this._ids,
            type: 'request',
            method: method,
            path: path
        };

        nes.internals.stringify(request, function (err, encoded) {

            if (err) {
                return callback(err);
            }

            self._requests[request.id] = callback;

            try {
                self._ws.send(encoded);
            }
            catch (err) {
                delete self._requests[request.id];
                return callback(err);
            }
        });
    };

    nes.Client.prototype._onMessage = function (message) {

        var self = this;

        nes.internals.parse(message.data, function (err, update) {

            if (err) {
                return;                                     // Do something
            }

            if (update.type === 'response') {
                var callback = self._requests[update.id];
                if (!callback) {
                    return;                                 // Do something
                }

                delete self._requests[update.id];
                return callback(null, update.payload, update.statusCode, update.headers);
            }
        });
    };

    nes.Client.prototype._onClose = function () {

        // Flush pending requests

        var error = new Error('Disconnected');

        var ids = Object.keys(this._requests);
        for (var i = 0, il = ids.length; i < il; ++i) {
            var id = ids[i];
            var callback = this._requests[id];
            delete this._requests[id];
            callback(error);
        }
    };

    nes.internals.parse = function (message, next) {

        var obj = null;
        var error = null;

        try {
            obj = JSON.parse(message);
        }
        catch (err) {
            error = err;
        }

        return next(error, obj);
    };

    nes.internals.stringify = function (message, next) {

        var string = null;
        var error = null;

        try {
            string = JSON.stringify(message);
        }
        catch (err) {
            error = err;
        }

        return next(error, string);
    };

    return nes;
});
<commit_msg>Cleanup for #1<commit_after>/*
    hapi-nes WebSocket Client
    Copyright (c) 2015, Eran Hammer <eran@hammer.io> and other contributors
    BSD Licensed
*/

(function (root, factory) {

    // Export if used as a module

    // $lab:coverage:off$
    if (typeof exports === 'object' && typeof module === 'object') {
        module.exports = factory();
    }
    else if (typeof define === 'function' && define.amd) {
        define(factory);
    }
    else if (typeof exports === 'object') {
        exports.nes = factory();
    }
    else {
        root.nes = factory();
    }
    // $lab:coverage:on$
})(this, function () {

    // Declare namespace

    var nes = {
        internals: {
            ignore: function () { },

            // Using just require here vs proper UMD binding as we assume WebSocket is available through
            // native bindings in all environments that you'd do something silly like use AMD or globals
            WebSocket: /* $lab:coverage:off$ */ (typeof WebSocket === 'undefined' ? require('ws') : WebSocket) /* $lab:coverage:on$ */
        }
    };

    nes.Client = function () {

        this._ws = null;
        this._ids = 0;                              // Id counter
        this._requests = {};                        // id -> callback

        this.onerror = nes.internals.ignore;        // General error callback (only when an error cannot be associated with a request)
    };

    nes.Client.prototype.connect = function (url, callback) {

        var self = this;

        var ws = new nes.internals.WebSocket(url);
        this._ws = ws;

        var sentCallback = false;
        ws.onopen = function () {

            if (!sentCallback) {
                sentCallback = true;
                return callback();
            }
        };

        ws.onerror = function (err) {

            if (!sentCallback) {
                sentCallback = true;
                return callback(err);
            }

            return self.onerror(err);
        };

        ws.onclose = function () {

            return self._onClose();
        };

        ws.onmessage = function (message) {

            return self._onMessage(message);
        };
    };

    nes.Client.prototype.disconnect = function () {

        if (!this._ws) {
            return;
        }

        if (this._ws.readyState === 1 ||                    // Open
            this._ws.readyState === 0) {                    // Connecting

            this._ws.close();
        }
    };

    nes.Client.prototype.request = function (method, path, callback) {

        var self = this;

        if (!this._ws ||
            this._ws.readyState !== 1) {                    // Open

            return callback(new Error('Disconnected'));
        }

        var request = {
            id: ++this._ids,
            type: 'request',
            method: method,
            path: path
        };

        nes.internals.stringify(request, function (err, encoded) {

            if (err) {
                return callback(err);
            }

            self._requests[request.id] = callback;

            try {
                self._ws.send(encoded);
            }
            catch (err) {
                delete self._requests[request.id];
                return callback(err);
            }
        });
    };

    nes.Client.prototype._onMessage = function (message) {

        var self = this;

        nes.internals.parse(message.data, function (err, update) {

            if (err) {
                return;                                     // Do something
            }

            if (update.type === 'response') {
                var callback = self._requests[update.id];
                if (!callback) {
                    return;                                 // Do something
                }

                delete self._requests[update.id];
                return callback(null, update.payload, update.statusCode, update.headers);
            }
        });
    };

    nes.Client.prototype._onClose = function () {

        // Flush pending requests

        var error = new Error('Disconnected');

        var ids = Object.keys(this._requests);
        for (var i = 0, il = ids.length; i < il; ++i) {
            var id = ids[i];
            var callback = this._requests[id];
            delete this._requests[id];
            callback(error);
        }
    };

    nes.internals.parse = function (message, next) {

        var obj = null;
        var error = null;

        try {
            obj = JSON.parse(message);
        }
        catch (err) {
            error = err;
        }

        return next(error, obj);
    };

    nes.internals.stringify = function (message, next) {

        var string = null;
        var error = null;

        try {
            string = JSON.stringify(message);
        }
        catch (err) {
            error = err;
        }

        return next(error, string);
    };

    return nes;
});
<|endoftext|>


<commit_before>import Ember from 'ember';
import layout from '../templates/components/tooltip-on-parent';

const { computed, warn, run, get } = Ember;

export default Ember.Component.extend({
  attributeBindings: ['style'],
  layout,

  style: computed(function() {
    return Ember.String.htmlSafe('display:none;');
  }),

  init(...args) {
    this._super(args);

    run.schedule('afterRender', () => {
      const parentView = this.get('parentView');

      if (parentView.renderTooltip) {
        const parentHasSelector = get(parentView, 'tagName') ? true : false;
        const domTarget = get(parentView, 'domTarget');
        const target = parentHasSelector ? parentView : domTarget;
        target.renderTooltip(this);
      } else {
        warn('No renderTooltip method found on the parent view of the {{tooltip-on-parent}} component');
      }

      this.remove();
    });
  },

});
<commit_msg>still not working unles tagName is set<commit_after>import Ember from 'ember';
import layout from '../templates/components/tooltip-on-parent';

const { computed, warn, run, get } = Ember;

export default Ember.Component.extend({
  attributeBindings: ['style'],
  layout,

  style: computed(function() {
    return Ember.String.htmlSafe('display:none;');
  }),

  init(...args) {
    this._super(args);

    run.schedule('afterRender', () => {
      const parentView = this.get('parentView');
      const parentHasSelector = get(parentView, 'tagName') ? true : false;
      const domTarget = get(parentView, 'domTarget');
      const target = parentHasSelector ? parentView : domTarget;

      if (target.renderTooltip) {
        target.renderTooltip(this);
      } else {
        console.warn('No renderTooltip method found on the parent view of the {{tooltip-on-parent}} component');
      }

      this.remove();
    });
  },

});
<|endoftext|>


<commit_before>import { assign } from '@ember/polyfills'
import { serializeQueryParams } from '../utils/serialize-query-params';

/**
 * Helper function that translates the options passed to `jQuery.ajax` into a format that `fetch` expects.
 * @param {Object} _options
 * @returns {Object}
 */
export default function mungOptionsForFetch(_options) {
  const options = assign({
    credentials: 'same-origin',
  }, _options);

  // Default to 'GET' in case `type` is not passed in (mimics jQuery.ajax).
  options.method = (options.method || options.type || 'GET').toUpperCase();

  if (options.data) {
    // GET and HEAD requests can't have a `body`
    if ((options.method === 'GET' || options.method === 'HEAD')) {
      // If no options are passed, Ember Data sets `data` to an empty object, which we test for.
      if (Object.keys(options.data).length) {
        // Test if there are already query params in the url (mimics jQuey.ajax).
        const queryParamDelimiter = options.url.indexOf('?') > -1 ? '&' : '?';
        options.url += `${queryParamDelimiter}${serializeQueryParams(options.data)}`;
      }
    } else {
      // NOTE: a request's body cannot be a POJO, so we stringify it if it is.
      // JSON.stringify removes keys with values of `undefined` (mimics jQuery.ajax).
      // If the data has no constructor we assume it is a POJO created with Object.create(null).
      // If the data is not a POJO (it's a String, FormData, etc), we just set it.
      // If the data is a string, we assume it's a stringified object.
      if (!options.data.constructor || options.data.constructor === Object) {
        options.body = JSON.stringify(options.data);
      } else {
        options.body = options.data;
      }
    }
  }

  return options;
}
<commit_msg>use Object.prototype.toString for object detection<commit_after>import { assign } from '@ember/polyfills'
import { serializeQueryParams } from '../utils/serialize-query-params';

/**
 * Helper function that translates the options passed to `jQuery.ajax` into a format that `fetch` expects.
 * @param {Object} _options
 * @returns {Object}
 */
export default function mungOptionsForFetch(_options) {
  const options = assign({
    credentials: 'same-origin',
  }, _options);

  // Default to 'GET' in case `type` is not passed in (mimics jQuery.ajax).
  options.method = (options.method || options.type || 'GET').toUpperCase();

  if (options.data) {
    // GET and HEAD requests can't have a `body`
    if ((options.method === 'GET' || options.method === 'HEAD')) {
      // If no options are passed, Ember Data sets `data` to an empty object, which we test for.
      if (Object.keys(options.data).length) {
        // Test if there are already query params in the url (mimics jQuey.ajax).
        const queryParamDelimiter = options.url.indexOf('?') > -1 ? '&' : '?';
        options.url += `${queryParamDelimiter}${serializeQueryParams(options.data)}`;
      }
    } else {
      // NOTE: a request's body cannot be a POJO, so we stringify it if it is.
      // JSON.stringify removes keys with values of `undefined` (mimics jQuery.ajax).
      // If the data is not a POJO (it's a String, FormData, etc), we just set it.
      // If the data is a string, we assume it's a stringified object.
      if (Object.prototype.toString.call(options.data) === "[object Object]") {
        options.body = JSON.stringify(options.data);
      } else {
        options.body = options.data;
      }
    }
  }

  return options;
}
<|endoftext|>