<commit_before>/**
 * jQuery.MediaAlignedText
 * Copyright (c) 2012 J. Reuben Wetherbee - jreubenwetherbee(at)gmail(dot)com
 * Licensed under MIT
 *
 * @projectDescription Handles the playback of MediaFiles along with aligned text
 *
 * @todo more documentation needed
 */

(function( $ ) {

    /**
     * base JQuery function to handle public method calls
     */
    $.fn.mediaAlignedText = function( method ) {

        //call specific method and pass along additional arguments
        if(public_methods[method]) {
            return public_methods[method].apply(this, Array.prototype.slice.call( arguments, 1));
        }
        //default to init method if no method specified
        if ( typeof method === 'object' || ! method ) {

            return public_methods.init.apply( this, arguments );
        }
        //method not recognized
        else {
            $.error( 'Method ' +  method + ' does not exist in jQuery.mediaAlignedText' );
        }
    };

    /**
     * Define the following public methods
     * - init              Initialize the MediaAlignedText
     * - charGroupClicked  Handle clicking the CharGroup
     */
    var public_methods = {
        //initialize the MediaAlignedText playback
        init : function(options){

            //get default options
            var options = $.extend({
                'json_alignment'            : {},                    //json alignment object
                'jplayer_controls_id'       : 'mat_jplayer_controls',//id of the div where jplayer controls reside
                'text_viewer_id'            : 'mat_text_viewer',     //id of the div where the text is displayed
                'jplayer_options'           : {},                    //additional jplayer options to initiate
                'jplayer_control_options'   : {},                    //options to send to the jplayer control generator
                'generate_jplayer_controls' : true,                  //flag indicating if controls should be generated or not
                'highlight_function'        : _textSegmentHighlight, //the function to use to highlight - requires object and text_segment_id as arguments
                'highlight_remove_function' : _textSegmentRemoveHighlight  //function to remove highligh - requires object and text_segment_id as arguments
            }, options);

            //save options to the objects namespaced data holder
            var $this = $(this);
            var data = $this.data('mediaAlignedText');

            if(!data) {
                $(this).data('mediaAlignedText', options);
            }

            //initialized jplayer controls
            if(options.generate_jplayer_controls) {
                options.jplayer_control_options.title = options.json_alignment.media_files[0].title;
                $('#'+options.jplayer_controls_id).html(_getJplayerContainerHtml(options.jplayer_control_options));
            }

            //set the initial media file for the jplayer
            options.jplayer_options.ready = function() {
                $(this).jPlayer("setMedia", {
                    mp3: options.json_alignment.media_files[0].url
                  });
            };

            //initialize all the mappings and components
            _initTextCharGroupSegmentIdMap($this);
            _initTextSegmentOrder($this);
            _initJplayer($this, options.jplayer_options);
            _initText($this, options.text_viewer_id, options.json_alignment);

        },

        //handles advancing to the aligned time of media when charGroup div clicked
        'charGroupClicked' : function(char_group_div_id) {
            var $this = $(this);
            var data = $this.data('mediaAlignedText');

            //strip the char_group_ off of the div id to get the text and char group order
            var text_char_group_order = char_group_div_id.replace('char_group_','');

            //get the text_segment to which this charGroup belongs
            var text_segment_id = data.text_char_group_segment_id_map[text_char_group_order];

            if( text_segment_id ) {
                var text_segment = data.json_alignment.text_segments[text_segment_id];
                //go to the place in the media file
                if($this.data('jPlayer').status.paused) { //if player paused just advance
                    $this.jPlayer('pause', text_segment.time_start);
                    _setCurrentTextSegmentId($this, text_segment_id);
                }
                else { // if player not paused then go to
                    $this.jPlayer('play', text_segment.time_start);
                }

            }
        }
    };

    var _checkTimeChange = function($this){
        var data = $this.data('mediaAlignedText');
        var current_time = parseFloat($this.data("jPlayer").status.currentTime);
        var current_text_segment_invalid = false;

        var current_text_segment = data.current_text_segment;

        //get start/end times for the current_text_segment
        if(current_text_segment == undefined) {
            current_text_segment_invalid = true;
        }
        else {
            var current_segment_start = parseFloat(current_text_segment.time_start);
            var current_segment_end = parseFloat(current_text_segment.time_end);
            if(current_time < current_segment_start || current_time > current_segment_end) {

                //unset the current_text_segment if necessary
                data.current_text_segment = undefined;
                current_text_segment_invalid = true;

                //unset the current text segment to remove highlight
                if(data.current_text_segment_id) data.highlight_remove_function($this, data.current_text_segment_id);
            }
        }

        //try to find a new matching media segment
        if(current_text_segment_invalid) {
            //search for new text_segment
            //this needs to be optimized!!!!  shouldn't try to scan whole array each time
            for(var text_segment_id in data.json_alignment.text_segments) {

                //set the text_segment var for convenience
                var text_segment = data.json_alignment.text_segments[text_segment_id];

                //
                if(text_segment.time_start < current_time && text_segment.time_end > current_time) {

                    data.current_text_segment = text_segment;
                    _setCurrentTextSegmentId($this, text_segment_id);

                }
            }
        }
        //reset the data
        $this.data('mediaAlignedText', data);
    };

    //initialize the Jplayer
    var _initJplayer = function ($this, options) {

        var options = $.extend({
              swfPath: 'js',
              supplied: 'mp3',
              timeupdate: function() {_checkTimeChange($(this))}
        }, options);

        $this.jPlayer(options);
    };

    /**
     * Initialize the text in the text_viewer
     *
     * @todo clean up the html generation - different char_group_types need some thought
     *
     * @param JqueryObject  $this          The jquery object which the mediaAlignedText has been
     * @param String        text_viewer_id
     * @param Object        json_alignment
     */
    var _initText = function ($this, text_viewer_id, json_alignment) {
        var html = '';
        var char_group = null;
        var breakTag = '
';

        for(var text_order in json_alignment.texts) {
            //enter the text title
            html = html+'
'+json_alignment.texts[text_order].title+'
';

            //loop through all the characater groups for this text and add to the html
            for(var char_group_order in json_alignment.texts[text_order].character_groups) {
                char_group = json_alignment.texts[text_order].character_groups[char_group_order];

                var text_char_group_order = text_order+'_'+char_group_order;
                var text_segment_id = $this.data('mediaAlignedText').text_char_group_segment_id_map[text_char_group_order];
                var text_segment_class = (text_segment_id ? 'mat_text_segment_'+text_segment_id : '');

                //for word type characater groups wrap the character in a span tag
                if(char_group.type == 'WORD') {

                    html = html+''
                        + char_group.chars + '';
                }
                //for non-word characater_groups make sure to put in line breaks
                else if(char_group.type == 'NON_WORD') {
                    html = html+''+
                        (char_group.chars + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2')+
                        '';
                }

                //for tag character groups, just ouptut the tag
                else if(char_group.type == 'TAG') {
                    html = html+char_group.chars;
                }
            }
        }
        //populate the text in the text viewer
        $('#'+text_viewer_id).html(html);

        //add the click function to the words
        $('a.mat_char_group_word').click(function() {
            $this.mediaAlignedText('charGroupClicked', $(this).attr('id'));
        });
    };

    /**
     * initialize the mapping between char groups and text segments
     */
    var _initTextCharGroupSegmentIdMap = function($this){
        var data = $this.data('mediaAlignedText');
        var text_segment = null;
        var text_char_group_segment_id_map = {};

        //loop through all text segments to look for matches on child char groups
        for(var text_segment_key in data.json_alignment.text_segments) {
            //set the text_segment
            text_segment = data.json_alignment.text_segments[text_segment_key];
            for(i = text_segment.character_group_start; i <= text_segment.character_group_end; i++) {
                text_char_group_segment_id_map[text_segment.text_order+'_'+i] = text_segment.id;
            }
        }

        //add the text_char_group map to data object
        data.text_char_group_segment_id_map = text_char_group_segment_id_map;

        //reset updated data object
        $this.data('mediaAlignedText', data);
    };

    /**
     * initialize an ordered index of text segments
     * @todo it is assumed the text segments are listed in time order - should be checked
     */
    var _initTextSegmentOrder = function($this) {
        var data = $this.data('mediaAlignedText');
        data.text_segment_order = new Array();

        //loop through and index the media_file_segments
        for(var id in data.json_alignment.text_segments) {
            data.text_segment_order.push(id);
        }

        //write back to the data object
        $this.data('mediaAlignedText', data);
    }

    /**
     * get the default html for the jplayer media player
     *
     * @param Object   options  The options that can be used to initialize the Jplayer Controller including the following
     * - jp_container_id:  The id of the container
     * - title:            The media file title to include in the player
     * -
     */
    var _getJplayerContainerHtml = function (options) {

            var options = $.extend({
                'jp_container_id' : 'jp_container_1',  //the id for the container for the controls
                'title'           : '',  //the title of the media file
                'media_type'      : 'audio'  //the media type for the container
            }, options);

            return '
\

\

\

\

play
\

pause
\

stop
\

mute
\

unmute
\

max volume
\

\

\

\

\

\

\

\

\

\

\

\

\

\

repeat
\

repeat off
\

\

\

\

\

\

'+options.title+'
\

\

\

\
              Update Required\
              To play the media you will need to either update your browser to a recent version or update your Flash plugin.\

\

\

';
    };

    /**
     * Set the current text segment to be the one supplied
     *
     * @param jQueryObject     $this   The obect on which the mediaAlignedText has been instantiated
     * @param text_segment_id  integer  The id of the textSegment to be highlighted
     */
    var _setCurrentTextSegmentId = function($this, text_segment_id) {
        var data = $this.data('mediaAlignedText');

        //if it is already set than do nothing
        if (data.current_text_segment_id == text_segment_id) {
            return true;
        }
        //if current text segment not yet set then simply set it and highlight it
        else if (data.current_text_segment_id == undefined) {
            data.current_text_segment_id = text_segment_id;
            data.highlight_function($this, text_segment_id);
        }
        //must already be set, so unhiglight old one and set new one
        else {
            data.highlight_remove_function($this, data.current_text_segment_id);
            data.current_text_segment_id = text_segment_id;
            data.highlight_function($this, text_segment_id);
        }
    };

    /**
     * Highlight a particular text segment
     *
     * @param jQueryObject     $this    The obect on which the mediaAlignedText has been instantiated
     * @param text_segment_id  integer  The id of the textSegment to be highlighted
     */
    var _textSegmentHighlight = function($this, text_segment_id) {
        $('.mat_text_segment_'+text_segment_id).addClass('highlighted_text_segment');
        $('#'+$this.data('mediaAlignedText').text_viewer_id).scrollTo('.highlighted_text_segment', 250, {'axis': 'y', 'offset': -20});
    };

    /**
     * Remove the highlight on a particular text segment
     *
     * @param jQueryObject     $this   The obect on which the mediaAlignedText has been instantiated
     * @param text_segment_id  integer  The id of the textSegment to have highlighting removed
     */
    var _textSegmentRemoveHighlight = function($this, text_segment_id){
        $('.mat_text_segment_'+text_segment_id).removeClass('highlighted_text_segment');
    };

})( jQuery );<commit_msg>added playTextSegment and refreshSegments to public methods<commit_after>/**
 * jQuery.MediaAlignedText
 * Copyright (c) 2012 J. Reuben Wetherbee - jreubenwetherbee(at)gmail(dot)com
 * Licensed under MIT
 *
 * @projectDescription Handles the playback of MediaFiles along with aligned text
 *
 * @todo more documentation needed
 */

(function( $ ) {

    /**
     * base JQuery function to handle public method calls
     */
    $.fn.mediaAlignedText = function( method ) {

        //call specific method and pass along additional arguments
        if(public_methods[method]) {
            return public_methods[method].apply(this, Array.prototype.slice.call( arguments, 1));
        }
        //default to init method if no method specified
        if ( typeof method === 'object' || ! method ) {

            return public_methods.init.apply( this, arguments );
        }
        //method not recognized
        else {
            $.error( 'Method ' +  method + ' does not exist in jQuery.mediaAlignedText' );
        }
    };

    /**
     * Define the following public methods
     * - init              Initialize the MediaAlignedText
     * - charGroupClicked  Handle clicking the CharGroup
     */
    var public_methods = {
        //initialize the MediaAlignedText playback
        init : function(options){

            //get default options
            var options = $.extend({
                'json_alignment'            : {},                    //json alignment object
                'jplayer_controls_id'       : 'mat_jplayer_controls',//id of the div where jplayer controls reside
                'text_viewer_id'            : 'mat_text_viewer',     //id of the div where the text is displayed
                'jplayer_options'           : {},                    //additional jplayer options to initiate
                'jplayer_control_options'   : {},                    //options to send to the jplayer control generator
                'generate_jplayer_controls' : true,                  //flag indicating if controls should be generated or not
                'highlight_function'        : _textSegmentHighlight, //the function to use to highlight - requires object and text_segment_id as arguments
                'highlight_remove_function' : _textSegmentRemoveHighlight  //function to remove highligh - requires object and text_segment_id as arguments
            }, options);

            //save options to the objects namespaced data holder
            var $this = $(this);
            var data = $this.data('mediaAlignedText');

            if(!data) {
                $(this).data('mediaAlignedText', options);
            }

            //initialized jplayer controls
            if(options.generate_jplayer_controls) {
                options.jplayer_control_options.title = options.json_alignment.media_files[0].title;
                $('#'+options.jplayer_controls_id).html(_getJplayerContainerHtml(options.jplayer_control_options));
            }

            //set the initial media file for the jplayer
            options.jplayer_options.ready = function() {
                $(this).jPlayer("setMedia", {
                    mp3: options.json_alignment.media_files[0].url
                  });
            };

            //initialize all the mappings and components
            _initTextCharGroupSegmentIdMap($this);
            _initTextSegmentOrder($this);
            _initJplayer($this, options.jplayer_options);
            _initText($this, options.text_viewer_id, options.json_alignment);

        },

        //handles advancing to the aligned time of media when charGroup div clicked
        'charGroupClicked' : function(char_group_div_id) {
            var $this = $(this);
            var data = $this.data('mediaAlignedText');

            //strip the char_group_ off of the div id to get the text and char group order
            var text_char_group_order = char_group_div_id.replace('char_group_','');

            //get the text_segment to which this charGroup belongs
            var text_segment_id = data.text_char_group_segment_id_map[text_char_group_order];

            if( text_segment_id ) {
                var text_segment = data.json_alignment.text_segments[text_segment_id];
                //go to the place in the media file
                if($this.data('jPlayer').status.paused) { //if player paused just advance
                    $this.jPlayer('pause', text_segment.time_start);
                    _setCurrentTextSegmentId($this, text_segment_id);
                }
                else { // if player not paused then go to
                    $this.jPlayer('play', text_segment.time_start);
                }

            }
        },
        /**
         * play the media file for just the text segment
         * @param integer  text_segment_id   Id of the text_segment to be played
         */
        'playTextSegment' : function(text_segment_id) {
            var $this = $(this);
            var text_segment = $this.data('mediaAlignedText').json_alignment.text_segments[text_segment_id];
            $this.jPlayer('play', text_segment.time_start);

            var t = setTimeout("$('#jquery_jplayer_1').jPlayer('pause')", 1000*(text_segment.time_end - text_segment.time_start));
        },

        'refreshSegments' : function() {
            var $this = $(this);
            var data = $this.data('mediaAlignedText');
            //initialize all the mappings and components
            _initTextCharGroupSegmentIdMap($this);
            _initTextSegmentOrder($this);
            _initText($this, data.text_viewer_id, data.json_alignment);

        }
    };

    var _checkTimeChange = function($this){
        var data = $this.data('mediaAlignedText');
        var current_time = parseFloat($this.data("jPlayer").status.currentTime);
        var current_text_segment_invalid = false;

        var current_text_segment = data.current_text_segment;

        //get start/end times for the current_text_segment
        if(current_text_segment == undefined) {
            current_text_segment_invalid = true;
        }
        else {
            var current_segment_start = parseFloat(current_text_segment.time_start);
            var current_segment_end = parseFloat(current_text_segment.time_end);
            if(current_time < current_segment_start || current_time > current_segment_end) {

                //unset the current_text_segment if necessary
                data.current_text_segment = undefined;
                current_text_segment_invalid = true;

                //unset the current text segment to remove highlight
                if(data.current_text_segment_id) data.highlight_remove_function($this, data.current_text_segment_id);
            }
        }

        //try to find a new matching media segment
        if(current_text_segment_invalid) {
            //search for new text_segment
            //this needs to be optimized!!!!  shouldn't try to scan whole array each time
            for(var text_segment_id in data.json_alignment.text_segments) {

                //set the text_segment var for convenience
                var text_segment = data.json_alignment.text_segments[text_segment_id];

                //
                if(text_segment.time_start < current_time && text_segment.time_end > current_time) {

                    data.current_text_segment = text_segment;
                    _setCurrentTextSegmentId($this, text_segment_id);

                }
            }
        }
        //reset the data
        $this.data('mediaAlignedText', data);
    };

    //initialize the Jplayer
    var _initJplayer = function ($this, options) {

        var options = $.extend({
              swfPath: 'js',
              supplied: 'mp3',
              timeupdate: function() {_checkTimeChange($(this))}
        }, options);

        $this.jPlayer(options);
    };

    /**
     * Initialize the text in the text_viewer
     *
     * @todo clean up the html generation - different char_group_types need some thought
     *
     * @param JqueryObject  $this          The jquery object which the mediaAlignedText has been
     * @param String        text_viewer_id
     * @param Object        json_alignment
     */
    var _initText = function ($this, text_viewer_id, json_alignment) {
        var html = '';
        var char_group = null;
        var breakTag = '
';

        for(var text_order in json_alignment.texts) {
            //enter the text title
            html = html+'
'+json_alignment.texts[text_order].title+'
';

            //loop through all the characater groups for this text and add to the html
            for(var char_group_order in json_alignment.texts[text_order].character_groups) {
                char_group = json_alignment.texts[text_order].character_groups[char_group_order];

                var text_char_group_order = text_order+'_'+char_group_order;
                var text_segment_id = $this.data('mediaAlignedText').text_char_group_segment_id_map[text_char_group_order];
                var text_segment_class = (text_segment_id ? 'mat_text_segment_'+text_segment_id : '');
                var char_group_id = text_order + '_' + char_group_order;

                //for word type characater groups wrap the character in a span tag
                if(char_group.type == 'WORD') {

                    html = html+''
                        + char_group.chars + '';
                }
                //for non-word characater_groups make sure to put in line breaks
                else if(char_group.type == 'NON_WORD') {
                    html = html+''
                        + (char_group.chars + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2')
                        + '';
                }

                //for tag character groups, just ouptut the tag
                else if(char_group.type == 'TAG') {
                    html = html+char_group.chars;
                }
            }
        }
        //populate the text in the text viewer
        $('#'+text_viewer_id).html(html);

        //add the click function to the words
        $('a.mat_char_group_word').click(function() {
            $this.mediaAlignedText('charGroupClicked', $(this).attr('id'));
        });
    };

    /**
     * initialize the mapping between char groups and text segments
     */
    var _initTextCharGroupSegmentIdMap = function($this){
        var data = $this.data('mediaAlignedText');
        var text_segment = null;
        var text_char_group_segment_id_map = {};

        //loop through all text segments to look for matches on child char groups
        for(var text_segment_key in data.json_alignment.text_segments) {
            //set the text_segment
            text_segment = data.json_alignment.text_segments[text_segment_key];
            for(i = text_segment.character_group_start; i <= text_segment.character_group_end; i++) {
                text_char_group_segment_id_map[text_segment.text_order+'_'+i] = text_segment.id;
            }
        }

        //add the text_char_group map to data object
        data.text_char_group_segment_id_map = text_char_group_segment_id_map;

        //reset updated data object
        $this.data('mediaAlignedText', data);
    };

    /**
     * initialize an ordered index of text segments
     * @todo it is assumed the text segments are listed in time order - should be checked
     */
    var _initTextSegmentOrder = function($this) {
        var data = $this.data('mediaAlignedText');
        data.text_segment_order = new Array();

        //loop through and index the media_file_segments
        for(var id in data.json_alignment.text_segments) {
            data.text_segment_order.push(id);
        }

        //write back to the data object
        $this.data('mediaAlignedText', data);
    }

    /**
     * get the default html for the jplayer media player
     *
     * @param Object   options  The options that can be used to initialize the Jplayer Controller including the following
     * - jp_container_id:  The id of the container
     * - title:            The media file title to include in the player
     * -
     */
    var _getJplayerContainerHtml = function (options) {

            var options = $.extend({
                'jp_container_id' : 'jp_container_1',  //the id for the container for the controls
                'title'           : '',  //the title of the media file
                'media_type'      : 'audio'  //the media type for the container
            }, options);

            return '
\

\

\

\

play
\

pause
\

stop
\

mute
\

unmute
\

max volume
\

\

\

\

\

\

\

\

\

\

\

\

\

\

repeat
\

repeat off
\

\

\

\

\

\

'+options.title+'
\

\

\

\
              Update Required\
              To play the media you will need to either update your browser to a recent version or update your Flash plugin.\

\

\

';
    };

    /**
     * Set the current text segment to be the one supplied
     *
     * @param jQueryObject     $this   The obect on which the mediaAlignedText has been instantiated
     * @param text_segment_id  integer  The id of the textSegment to be highlighted
     */
    var _setCurrentTextSegmentId = function($this, text_segment_id) {
        var data = $this.data('mediaAlignedText');

        //if it is already set than do nothing
        if (data.current_text_segment_id == text_segment_id) {
            return true;
        }
        //if current text segment not yet set then simply set it and highlight it
        else if (data.current_text_segment_id == undefined) {
            data.current_text_segment_id = text_segment_id;
            data.highlight_function($this, text_segment_id);
        }
        //must already be set, so unhiglight old one and set new one
        else {
            data.highlight_remove_function($this, data.current_text_segment_id);
            data.current_text_segment_id = text_segment_id;
            data.highlight_function($this, text_segment_id);
        }
    };

    /**
     * Highlight a particular text segment
     *
     * @param jQueryObject     $this    The obect on which the mediaAlignedText has been instantiated
     * @param text_segment_id  integer  The id of the textSegment to be highlighted
     */
    var _textSegmentHighlight = function($this, text_segment_id) {
        $('.mat_text_segment_'+text_segment_id).addClass('highlighted_text_segment');
        $('#'+$this.data('mediaAlignedText').text_viewer_id).scrollTo('.highlighted_text_segment', 250, {'axis': 'y', 'offset': -20});
    };

    /**
     * Remove the highlight on a particular text segment
     *
     * @param jQueryObject     $this   The obect on which the mediaAlignedText has been instantiated
     * @param text_segment_id  integer  The id of the textSegment to have highlighting removed
     */
    var _textSegmentRemoveHighlight = function($this, text_segment_id){
        $('.mat_text_segment_'+text_segment_id).removeClass('highlighted_text_segment');
    };

})( jQuery );<|endoftext|>


<commit_before>var debug = require('debug')('rascal:Vhost')
var format = require('util').format
var inherits = require('util').inherits
var EventEmitter = require('events').EventEmitter
var async = require('async')
var tasks = require('./tasks')

module.exports = {
    create: function(config, next) {
        new Vhost(config).init(next)
    }
}

inherits(Vhost, EventEmitter)

function Vhost(config) {

    var self = this
    var connection
    var channelAllocator = async.queue(createChannel, 1)

    var init = async.compose(tasks.closeChannel, tasks.applyBindings, tasks.purgeQueues, tasks.checkQueues, tasks.assertQueues, tasks.checkExchanges, tasks.assertExchanges, tasks.createChannel, tasks.createConnection)
    var bounce = async.compose(init, tasks.closeConnection)
    var purge = async.compose(tasks.closeConnection, tasks.closeChannel, tasks.purgeQueues, tasks.createChannel, tasks.createConnection)
    var nuke = async.compose(tasks.closeConnection, tasks.closeChannel, tasks.deleteQueues, tasks.deleteExchanges, tasks.createChannel, tasks.createConnection)

    this.init = function(next) {
        debug(format('Initialising vhost: %s', config.name))
        channelAllocator.pause()
        init(config, {}, function(err, config, ctx) {
            if (err) return next(err)
            // TODO its possible a connection error has already triggered an init cycle, so may need to disconnect again
            ctx.connection.removeAllListeners('error')
            ctx.connection.once('error', handleConnectionError.bind(null, config))
            connection = ctx.connection
            channelAllocator.resume()
            return next(null, self)
        })
        return self
    }

    this.nuke = function(next) {
        debug(format('Nuking vhost: %s', config.name))
        channelAllocator.pause()
        nuke(config, {}, function(err, config, ctx) {
            if (err) return next(err)
            connection = undefined
            debug(format('Finished nuking vhost: %s', config.name))
            setImmediate(next)
        })
    }

    this.purge = function(next) {
        debug(format('Purging vhost: %s', config.name))
        purge(config, { purge: true }, function(err, config, ctx) {
            if (err) return next(err)
            debug(format('Finished purging vhost: %s', config.name))
            setImmediate(next)
        })
    }

    this.bounce = function(next) {
        debug(format('Bouncing vhost: %s', config.name))
        channelAllocator.pause()
        bounce(config, {}, function() {
            setImmediate(next)
        })
    }

    this.disconnect = function(next) {
        debug(format('Disconnecting vhost: %s', config.name))
        channelAllocator.pause()
        if (!connection) return next()
        connection.removeAllListeners()
        connection.on('error', function(err) {
            debug(format('Error disconnecting from %s. Original error was: %s', config.connection.loggableUrl, err.message))
        })
        connection.close(next)
    }

    this.getChannel = function(next) {
        channelAllocator.push({ confirm: false }, next)
        debug(format('Requested channel. Outstanding channel requests: %d', channelAllocator.length()))
    }

    this.getConfirmChannel = function(next) {
        channelAllocator.push({ confirm: true }, next)
        debug(format('Requested confirm channel. Outstanding channel requests: %d', channelAllocator.length()))
    }

    function createChannel(options, next) {
        options.confirm ? connection.createConfirmChannel(callback) : connection.createChannel(callback)

        function callback(err, channel) {
            if (err) return next(err)
            next(null, channel)
        }
    }

    function handleConnectionError(config, err) {
        debug(format('Handling connection error: %s from %s', err.message, config.connection.loggableUrl))
        channelAllocator.pause()
        connection = undefined
        self.emit('error', err)
        config.connection.retry && self.init(function(err) {
            if (err) return setTimeout(handleConnectionError.bind(null, config, err), config.connection.retry.delay)
        })
    }
}

<commit_msg>vhost reflects connection blocked and unblocked events<commit_after>var debug = require('debug')('rascal:Vhost')
var format = require('util').format
var inherits = require('util').inherits
var EventEmitter = require('events').EventEmitter
var async = require('async')
var forwardEvents = require('forward-emitter')
var tasks = require('./tasks')

module.exports = {
    create: function(config, next) {
        new Vhost(config).init(next)
    }
}

inherits(Vhost, EventEmitter)

function Vhost(config) {

    var self = this
    var connection
    var channelAllocator = async.queue(createChannel, 1)

    var init = async.compose(tasks.closeChannel, tasks.applyBindings, tasks.purgeQueues, tasks.checkQueues, tasks.assertQueues, tasks.checkExchanges, tasks.assertExchanges, tasks.createChannel, tasks.createConnection)
    var bounce = async.compose(init, tasks.closeConnection)
    var purge = async.compose(tasks.closeConnection, tasks.closeChannel, tasks.purgeQueues, tasks.createChannel, tasks.createConnection)
    var nuke = async.compose(tasks.closeConnection, tasks.closeChannel, tasks.deleteQueues, tasks.deleteExchanges, tasks.createChannel, tasks.createConnection)

    this.init = function(next) {
        debug(format('Initialising vhost: %s', config.name))
        channelAllocator.pause()
        init(config, {}, function(err, config, ctx) {
            if (err) return next(err)
            // TODO its possible a connection error has already triggered an init cycle, so may need to disconnect again
            ctx.connection.removeAllListeners('error')
            ctx.connection.once('error', handleConnectionError.bind(null, config))
            forwardEvents(ctx.connection, self, function(eventName) {
                return eventName === 'blocked' || eventName === 'unblocked';
            })
            connection = ctx.connection
            channelAllocator.resume()
            return next(null, self)
        })
        return self
    }

    this.nuke = function(next) {
        debug(format('Nuking vhost: %s', config.name))
        channelAllocator.pause()
        nuke(config, {}, function(err, config, ctx) {
            if (err) return next(err)
            connection = undefined
            debug(format('Finished nuking vhost: %s', config.name))
            setImmediate(next)
        })
    }

    this.purge = function(next) {
        debug(format('Purging vhost: %s', config.name))
        purge(config, { purge: true }, function(err, config, ctx) {
            if (err) return next(err)
            debug(format('Finished purging vhost: %s', config.name))
            setImmediate(next)
        })
    }

    this.bounce = function(next) {
        debug(format('Bouncing vhost: %s', config.name))
        channelAllocator.pause()
        bounce(config, {}, function() {
            setImmediate(next)
        })
    }

    this.disconnect = function(next) {
        debug(format('Disconnecting vhost: %s', config.name))
        channelAllocator.pause()
        if (!connection) return next()
        connection.removeAllListeners()
        connection.on('error', function(err) {
            debug(format('Error disconnecting from %s. Original error was: %s', config.connection.loggableUrl, err.message))
        })
        connection.close(next)
    }

    this.getChannel = function(next) {
        channelAllocator.push({ confirm: false }, next)
        debug(format('Requested channel. Outstanding channel requests: %d', channelAllocator.length()))
    }

    this.getConfirmChannel = function(next) {
        channelAllocator.push({ confirm: true }, next)
        debug(format('Requested confirm channel. Outstanding channel requests: %d', channelAllocator.length()))
    }

    function createChannel(options, next) {
        options.confirm ? connection.createConfirmChannel(callback) : connection.createChannel(callback)

        function callback(err, channel) {
            if (err) return next(err)
            next(null, channel)
        }
    }

    function handleConnectionError(config, err) {
        debug(format('Handling connection error: %s from %s', err.message, config.connection.loggableUrl))
        channelAllocator.pause()
        connection = undefined
        self.emit('error', err)
        config.connection.retry && self.init(function(err) {
            if (err) return setTimeout(handleConnectionError.bind(null, config, err), config.connection.retry.delay)
        })
    }
}

<|endoftext|>


<commit_before>var express = require('express'),
    pg = require('../store/pg'),
		sql = require('sql'),
    app = express();

// define model for node-sql (https://github.com/brianc/node-sql)
var npiQueryableColumns = ['npi','provider_business_practice_location_address_postal_code','provider_last_name_legal_name']
var npi = sql.define({
	name: 'npis',
	columns: npiQueryableColumns
});

app.use('/', express.static(__dirname + '/../../www'));

app.get('/api/search', function (req, res) {
	var sqlQuery = npi.where(npi.npi.isNotNull()); // default scope

	// if req.query.limit is not specified, set to 100
  var sqlLimit = ((req.query.limit === undefined) ? 100 : req.query.limit);
  sqlQuery = sqlQuery.limit(sqlLimit)

  // if req.query.offset is not specified, set to 0
  var sqlOffset = ((req.query.offset === undefined) ?  0 : req.query.offset);
  sqlQuery = sqlQuery.offset(sqlOffset)

  // loop through query parameters and add conditions to SQL query as appropriate
	for(var key in req.query) {
		value = req.query[key];

		if(npiQueryableColumns.indexOf(key) != -1 && value != '') {
			switch(key){
				case 'npi':
					sqlQuery = sqlQuery.where(npi.npi.equal(value));
					break;
				case 'provider_business_practice_location_address_postal_code':
					sqlQuery = sqlQuery.where(npi.provider_business_practice_location_address_postal_code.like(value+'%'))
					break;
				case 'provider_last_name_legal_name':
					sqlQuery = sqlQuery.where(npi.provider_last_name_legal_name.equal(value))
					break;
			}
	  } else {
			// do nothing with this query parameter, either:
			// - user is not allowed to query on the specified column
			// - the value of the parameter an empty string ('')
		}
	}

	sqlQuery = sqlQuery.toQuery()
	pg.query(sqlQuery.text, sqlQuery.values, function (err, result) {
    result.rows.forEach(function (row) {
      for(var k in row) {
        if (row[k] === null) delete row[k];
      }
    });
    res.json({
      meta: {
        rowCount: result.rowCount,
        sqlText: sqlQuery.text,
        sqlValues: sqlQuery.values,
        limit: sqlLimit,
        offset: sqlOffset
      },
      result:result.rows,
    });
  });
});

app.listen(3000);
console.log('Listening on port 3000');
<commit_msg>transforming npi metadata before returning for search<commit_after>var express = require('express'),
    pg = require('../store/pg'),
		sql = require('sql'),
    app = express(),
    npiFields = require('../store/npiFields');

// define model for node-sql (https://github.com/brianc/node-sql)
var npiQueryableColumns = ['npi','provider_business_practice_location_address_postal_code','provider_last_name_legal_name']
var npi = sql.define({
	name: 'npis',
	columns: npiQueryableColumns
});

app.use('/', express.static(__dirname + '/../../www'));

app.get('/api/search', function (req, res) {
	var sqlQuery = npi.where(npi.npi.isNotNull()); // default scope

	// if req.query.limit is not specified, set to 100
  var sqlLimit = ((req.query.limit === undefined) ? 100 : req.query.limit);
  sqlQuery = sqlQuery.limit(sqlLimit)

  // if req.query.offset is not specified, set to 0
  var sqlOffset = ((req.query.offset === undefined) ?  0 : req.query.offset);
  sqlQuery = sqlQuery.offset(sqlOffset)

  // loop through query parameters and add conditions to SQL query as appropriate
	for(var key in req.query) {
		value = req.query[key];

		if(npiQueryableColumns.indexOf(key) != -1 && value != '') {
			switch(key){
				case 'npi':
					sqlQuery = sqlQuery.where(npi.npi.equal(value));
					break;
				case 'provider_business_practice_location_address_postal_code':
					sqlQuery = sqlQuery.where(npi.provider_business_practice_location_address_postal_code.like(value+'%'))
					break;
				case 'provider_last_name_legal_name':
					sqlQuery = sqlQuery.where(npi.provider_last_name_legal_name.equal(value))
					break;
			}
	  } else {
			// do nothing with this query parameter, either:
			// - user is not allowed to query on the specified column
			// - the value of the parameter an empty string ('')
		}
	}

	sqlQuery = sqlQuery.toQuery()
	pg.query(sqlQuery.text, sqlQuery.values, function (err, result) {
    result.rows.forEach(function (row) {
      for(var k in row) {
        if (row[k] === null) delete row[k];
      }
    });

    npiFields.process(result.rows).then(function (transformed) {
      res.json({
        meta: {
          rowCount: result.rowCount,
          sqlText: sqlQuery.text,
          sqlValues: sqlQuery.values,
          limit: sqlLimit,
          offset: sqlOffset
        },
        result:transformed
      });
    });
  });
});

app.listen(3000);
console.log('Listening on port 3000');
<|endoftext|>


<commit_before>angular.module('sgApp', [
  'ui.router',
  'ngAnimate',
  'colorpicker.module',
  'hljs',
  'LocalStorageModule'
])
  .config(function($stateProvider, $urlRouterProvider, $locationProvider, localStorageServiceProvider) {
    $stateProvider
      .state('index', {
        controller: 'MainCtrl',
        templateUrl: 'views/main.html'
      })
      .state('index.overview', {
        url: '/overview',
        templateUrl: 'overview.html',
        controller: function($rootScope) {
          $rootScope.currentSection = 'overview';
        }
      })
      .state('index.section', {
        url: '/:section',
        templateUrl: 'views/sections.html',
        controller: 'SectionsCtrl'
      })
      .state('fullscreen', {
        url: '/:section/:element/fullscreen',
        templateUrl: 'views/element-fullscreen.html'

      });

    $locationProvider.html5Mode(true);

    localStorageServiceProvider.setPrefix('sgLs');
  })
  // Trust modifier markup to be safe html
  .filter('unsafe', function($sce) {
    return function(val) {
      return $sce.trustAsHtml(val);
    };
  })
  // Replaces modifier markup's {$modifiers} with modifier's modifierClass
  .filter('setModifierClass', function() {
    return function(items, modifierClass) {
      items = items.replace(/\{\$modifiers\}/, modifierClass);
      return items;
    };
  })
  //
  .filter('setVariables', function() {
    return function(item, variables) {
      for (var variable in variables) {
        var re = new RegExp('(\\w+?):\\s*\\$' + variable),
          match = item.match(re);
        if (match) {
          item = item.slice(0, match.index) + match[1] + ':' + variables[variable] + ';' + item.slice(match.index, item.length);
        }
      }
      return item;
    };
  })
  .filter('decodeHtml', function() {
    return function(string) {
      var map = {
        '&': '&',
        '>': '>',
        '<': '<',
        '"': '"',
        ''': '\'',
        ''': '\''
      };

      for (var m in map) {
        string = string.replace(new RegExp(m, 'gim'), map[m]);
      }

      return string;
    };
  });
<commit_msg>Prevent error when filtering undefined fields<commit_after>angular.module('sgApp', [
  'ui.router',
  'ngAnimate',
  'colorpicker.module',
  'hljs',
  'LocalStorageModule'
])
  .config(function($stateProvider, $urlRouterProvider, $locationProvider, localStorageServiceProvider) {
    $stateProvider
      .state('index', {
        controller: 'MainCtrl',
        templateUrl: 'views/main.html'
      })
      .state('index.overview', {
        url: '/overview',
        templateUrl: 'overview.html',
        controller: function($rootScope) {
          $rootScope.currentSection = 'overview';
        }
      })
      .state('index.section', {
        url: '/:section',
        templateUrl: 'views/sections.html',
        controller: 'SectionsCtrl'
      })
      .state('fullscreen', {
        url: '/:section/:element/fullscreen',
        templateUrl: 'views/element-fullscreen.html'

      });

    $locationProvider.html5Mode(true);

    localStorageServiceProvider.setPrefix('sgLs');
  })
  // Trust modifier markup to be safe html
  .filter('unsafe', function($sce) {
    return function(val) {
      return $sce.trustAsHtml(val);
    };
  })
  // Replaces modifier markup's {$modifiers} with modifier's modifierClass
  .filter('setModifierClass', function() {
    return function(items, modifierClass) {
      items = items.replace(/\{\$modifiers\}/, modifierClass);
      return items;
    };
  })
  //
  .filter('setVariables', function() {
    return function(item, variables) {
      for (var variable in variables) {
        var re = new RegExp('(\\w+?):\\s*\\$' + variable),
          match = item.match(re);
        if (match) {
          item = item.slice(0, match.index) + match[1] + ':' + variables[variable] + ';' + item.slice(match.index, item.length);
        }
      }
      return item;
    };
  })
  .filter('decodeHtml', function() {
    return function(string) {

      string = string || '';

      var map = {
        '&': '&',
        '>': '>',
        '<': '<',
        '"': '"',
        ''': '\'',
        ''': '\''
      };

      for (var m in map) {
        string = string.replace(new RegExp(m, 'gim'), map[m]);
      }

      return string;
    };
  });
<|endoftext|>


<commit_before>//
// Module: assemblies
// ==================
//
'use strict';

var Assemblies;
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

module.exports = Assemblies = (function () {

  //
  //
  // Constructor
  // -----------
  //
  // #### Code
  function Assemblies (opts, uri) {
    /* checking the required arguments */
    ['key', 'secret'].forEach(function (item) {
      if (opts[item] == null)
        throw new Error('There\'s a required argument missing: ' + item);
    });

    this.opts = opts;
    this.uri = uri;

    /* bindings */
    this.post = __bind(this.post, this);
  }

  //
  //
  // Public: send an assembly to Transloadit API
  // -------------------------------------------
  //
  // #### Parameters
  //
  // + `files` - `File Object` JSON (it may have several files)
  // + `params`
  // + `callback` - `Callback Function`
  //
  // #### Returns
  //
  // A `Callback` function with `(err, res, body)` from `request` directly.
  //
  // #### Code
  Assemblies.prototype.post = function (files, params, callback) {
    var self = this;
    var _ = require('lodash');
    var fs = require('fs');
    var request = require('request');
    var r = request.post(self.uri.base + self.uri.assemblies, function(err, response, body) {
      if (err)
        return callback(err);

      console.log(body);
      return callback(null, body);
    });

    var SignatureLib = require('./signature');
    var signature = new SignatureLib(self.opts);

    var form = r.form();
    var x;

    x = signature.create(params);

    _.each(files, function(file) {
      form.append(file.name, fs.createReadStream(file.path) );
    });

    form.append('signature', x.signature);
    form.append('params', JSON.stringify(x.params));
  };

  return Assemblies;
})();
<commit_msg>cleaning lib/assemblies<commit_after>//
// Module: assemblies
// ==================
//
'use strict';

var Assemblies;
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

module.exports = Assemblies = (function () {

  //
  //
  // Constructor
  // -----------
  //
  // #### Code
  function Assemblies (opts, uri) {
    /* checking the required arguments */
    ['key', 'secret'].forEach(function (item) {
      if (opts[item] == null)
        throw new Error('There\'s a required argument missing: ' + item);
    });

    this.opts = opts;
    this.uri = uri;

    /* bindings */
    this.post = __bind(this.post, this);
  }

  //
  //
  // Public: send an assembly to Transloadit API
  // -------------------------------------------
  //
  // #### Parameters
  //
  // + `files` - `File Object` JSON (it may have several files)
  // + `params`
  // + `callback` - `Callback Function`
  //
  // #### Returns
  //
  // A `Callback` function with `(err, res, body)` from `request` directly.
  //
  // #### Code
  Assemblies.prototype.post = function (files, params, callback) {
    var self = this;
    var _ = require('lodash');
    var fs = require('fs');
    var request = require('request');
    var r = request.post(self.uri.base + self.uri.assemblies, function(err, response, body) {
      /* Here's the callback, we clean up the `response` and only return `body` */
      if (err)
        return callback(err);

      return callback(null, body);
    });

    var SignatureLib = require('./signature');
    var signature = new SignatureLib(self.opts);

    var form = r.form();
    var x;

    x = signature.create(params);

    _.each(files, function(file) {
      form.append(file.name, fs.createReadStream(file.path) );
    });

    form.append('signature', x.signature);
    form.append('params', JSON.stringify(x.params));
  };

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


<commit_before>const JSDOM = require('jsdom').JSDOM;
const Text = require('./Text');

class Xml extends Text {
  get parseTree() {
    if (!this._parseTree) {
      this._jsdom = new JSDOM(this.text, {
        url: this.url, // So that errors get reported with the url (awaiting https://github.com/jsdom/jsdom/pull/2630)
        contentType: 'application/xhtml+xml'
      });
      this._parseTree = this._jsdom.window.document;
    }
    return this._parseTree;
  }

  set parseTree(parseTree) {
    this.unload();
    this._parseTree = parseTree;
    this._lastKnownByteLength = undefined;
    if (this.assetGraph) {
      this.populate();
    }
    this.markDirty();
  }

  get text() {
    if (typeof this._text !== 'string') {
      if (this._parseTree) {
        this._text = `<?xml version="1.0" encoding="UTF-8"?>\n${this._jsdom.serialize()}\n`;
      } else {
        this._text = this._getTextFromRawSrc();
      }
    }
    return this._text;
  }

  set text(text) {
    super.text = text;
  }

  unload() {
    super.unload();
    if (this._jsdom) {
      this._jsdom.window.close();
      this._jsdom = undefined;
    }
  }

  findOutgoingRelationsInParseTree() {
    const outgoingRelations = super.findOutgoingRelationsInParseTree();
    if (!this.isLoaded) {
      return outgoingRelations;
    }
    const queue = [this.parseTree];
    while (queue.length > 0) {
      const node = queue.shift();
      if (node.childNodes) {
        for (let i = node.childNodes.length - 1; i >= 0; i -= 1) {
          queue.unshift(node.childNodes[i]);
        }
      }
      if (node.nodeType === 7) {
        // PROCESSING_INSTRUCTION_NODE
        if (node.nodeName === 'xml-stylesheet') {
          const matchData = node.data.match(/href="([^"]*)"/);
          if (matchData) {
            outgoingRelations.push({
              type: 'XmlStylesheet',
              node,
              href: matchData[1].replace(/"/, '"').replace(/&/, '&')
            });
          }
        }
      }
    }
    return outgoingRelations;
  }

  minify() {
    const queue = [this.parseTree];
    while (queue.length > 0) {
      const element = queue.shift();
      // Whitespace-only text node?
      if (element.nodeType === 3 && /^[\r\n\s\t]*$/.test(element.nodeValue)) {
        element.parentNode.removeChild(element);
      }
    }
    this.isPretty = false;
    return this;
  }

  prettyPrint() {
    this.isPretty = true;
    // eslint-disable-next-line no-unused-expressions
    this.parseTree; // So markDirty removes this._text
    this.markDirty();
    return this;
  }
}

Object.assign(Xml.prototype, {
  contentType: 'text/xml',

  supportedExtensions: ['.xml'],

  isPretty: false
});

module.exports = Xml;
<commit_msg>Don't pass url:null to JSDOM<commit_after>const JSDOM = require('jsdom').JSDOM;
const Text = require('./Text');

class Xml extends Text {
  get parseTree() {
    if (!this._parseTree) {
      this._jsdom = new JSDOM(this.text, {
        url: this.url ? this.url : undefined, // So that errors get reported with the url (awaiting https://github.com/jsdom/jsdom/pull/2630)
        contentType: 'application/xhtml+xml'
      });
      this._parseTree = this._jsdom.window.document;
    }
    return this._parseTree;
  }

  set parseTree(parseTree) {
    this.unload();
    this._parseTree = parseTree;
    this._lastKnownByteLength = undefined;
    if (this.assetGraph) {
      this.populate();
    }
    this.markDirty();
  }

  get text() {
    if (typeof this._text !== 'string') {
      if (this._parseTree) {
        this._text = `<?xml version="1.0" encoding="UTF-8"?>\n${this._jsdom.serialize()}\n`;
      } else {
        this._text = this._getTextFromRawSrc();
      }
    }
    return this._text;
  }

  set text(text) {
    super.text = text;
  }

  unload() {
    super.unload();
    if (this._jsdom) {
      this._jsdom.window.close();
      this._jsdom = undefined;
    }
  }

  findOutgoingRelationsInParseTree() {
    const outgoingRelations = super.findOutgoingRelationsInParseTree();
    if (!this.isLoaded) {
      return outgoingRelations;
    }
    const queue = [this.parseTree];
    while (queue.length > 0) {
      const node = queue.shift();
      if (node.childNodes) {
        for (let i = node.childNodes.length - 1; i >= 0; i -= 1) {
          queue.unshift(node.childNodes[i]);
        }
      }
      if (node.nodeType === 7) {
        // PROCESSING_INSTRUCTION_NODE
        if (node.nodeName === 'xml-stylesheet') {
          const matchData = node.data.match(/href="([^"]*)"/);
          if (matchData) {
            outgoingRelations.push({
              type: 'XmlStylesheet',
              node,
              href: matchData[1].replace(/"/, '"').replace(/&/, '&')
            });
          }
        }
      }
    }
    return outgoingRelations;
  }

  minify() {
    const queue = [this.parseTree];
    while (queue.length > 0) {
      const element = queue.shift();
      // Whitespace-only text node?
      if (element.nodeType === 3 && /^[\r\n\s\t]*$/.test(element.nodeValue)) {
        element.parentNode.removeChild(element);
      }
    }
    this.isPretty = false;
    return this;
  }

  prettyPrint() {
    this.isPretty = true;
    // eslint-disable-next-line no-unused-expressions
    this.parseTree; // So markDirty removes this._text
    this.markDirty();
    return this;
  }
}

Object.assign(Xml.prototype, {
  contentType: 'text/xml',

  supportedExtensions: ['.xml'],

  isPretty: false
});

module.exports = Xml;
<|endoftext|>


<commit_before>'use strict'; // eslint-disable-line strict, lines-around-directive

// Require this module to use code in the /src dir prior to transpilation.

const plugins = (...items) => items.concat([
  'syntax-flow',
  'syntax-trailing-function-commas',
  'transform-async-to-generator',
  'transform-class-properties',
  'transform-es2015-destructuring',
  'transform-es2015-parameters',
  'transform-es2015-spread',
  'transform-exponentiation-operator',
  'transform-flow-strip-types',
  'transform-object-rest-spread',
  'transform-es2015-modules-commonjs'
]);

// eslint-disable-next-line import/no-extraneous-dependencies
require('babel-core/register')({
  babelrc: false,
  plugins: plugins(),
  env: {
    test: {
      sourceMaps: 'inline',
      plugins: plugins(['istanbul', {
        include: [
          'src/**/*.js'
        ],
        exclude: [
          '**/test',
          '**/errors',
          '**/interfaces.js'
        ]
      }])
    }
  }
});
<commit_msg>fix: remove unused plugins in lib/babel-hook (#444)<commit_after>'use strict'; // eslint-disable-line strict, lines-around-directive

// Require this module to use code in the /src dir prior to transpilation.

const plugins = (...items) => items.concat([
  'transform-async-to-generator',
  'transform-class-properties',
  'transform-es2015-destructuring',
  'transform-es2015-parameters',
  'transform-es2015-spread',
  'transform-exponentiation-operator',
  'transform-flow-strip-types',
  'transform-object-rest-spread',
  'transform-es2015-modules-commonjs'
]);

// eslint-disable-next-line import/no-extraneous-dependencies
require('babel-core/register')({
  babelrc: false,
  plugins: plugins(),
  env: {
    test: {
      sourceMaps: 'inline',
      plugins: plugins(['istanbul', {
        include: [
          'src/**/*.js'
        ],
        exclude: [
          '**/test',
          '**/errors',
          '**/interfaces.js'
        ]
      }])
    }
  }
});
<|endoftext|>


<commit_before>var fs = require('fs');
var zlib = require('zlib');
var mime = require('mime');
var minifyHtml = require('html-minifier').minify;
var minifyCSS =  require('clean-css');

var html_minifier_options = {
    removeComments: true,
    removeCommentsFromCDATA: true,
    removeCDATASectionsFromCDATA: true,
    removeAttributeQuotes: true,
    removeRedundantAttributes: true,
    removeEmptyAttributes: true,
    removeOptionalTags: true,
    collapseBooleanAttributes: true,
    collapseWhitespace: true
};

// save caches
var caches = {};

// this is not quaranteed to be stable!
zlib.Z_DEFAULT_COMPRESSION = 9;

module.exports = factory;

function factory (name, noCompression, dontOptimize) {

    // return existing cache
    if (caches[name]) {
        return caches[name];
    }

    // clone cache class
    var cache = Cache.clone();

    // create data container
    cache._data = {};

    // configure compression
    cache._noCompression = noCompression;

    // dont optimize html and css
    cache._dontOptimize = dontOptimize;

    // save cache
    caches[name] = cache;

    return cache;
}

// FileCache
var Cache = {

    // remove one or all item(s)
    rm: function (path) {

        // remove one item
        if (path) {
            return delete this._data[path];
        }

        // remove all items
        this._data = {};
    },

    // return one or all item(s)
    get: function (path) {

        // return one item
        if (path) {
            return this._data[path];
        }

        // return all items
        return this._data;
    },

    // set an item
    set: function (path, callback, dontWatch) {
        var self = this;

        // check if file is already in cache
        if (!dontWatch && self._data[path]) {
            return callback(null, self._data[path]);
        }

        // path must be absolute
        if (path.indexOf('../') !== -1) {
            return callback(new Error('Invalid path.'));
        }

        fs.readFile(path, function (err, data) {

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

            var mimeType = mime.lookup(path);

            // optimize html or css
            if (!self._dontOptimize) {
                switch (mimeType) {
                    case 'text/html':
                        data = minifyHtml(data.toString('utf8'), html_minifier_options);
                        break;
                    case 'text/css':
                        data = new minifyCSS({processImport: false}).minify(data.toString('utf8'));
                        break;
                }
            }

            // don't compress data
            if (self._noCompression) {
                return createCacheObject.call(self, path, data, mimeType, callback, dontWatch);
            }

            zlib.gzip(data, function (err, data) {

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

                createCacheObject.call(self, path, data, mimeType, callback, dontWatch);
            });
        });
    }
};

function createCacheObject (path, data, mimeType, callback, dontWatch) {
    var self = this;

    fs.stat(path, function (err, stats) {

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

        // watch file and update cache on change (only in dev mode? i think so..)
        if (!dontWatch) {
            fs.watch(path, function (event) {

                // update cache data on file change
                if (event === 'change') {
                    self.set(path, function () {}, true);
                }
            });
        }

        // save zipped data in cache
        self._data[path] = data = {
            data: data,

            // create http headers
            http: {
                'Cache-Control': 'public, max-age=31536000',
                'Vary': 'Accept-Encoding',
                'Last-Modified': stats.mtime,
                'Content-Encoding': 'gzip',
                'Content-Length': data.length,
                'Content-Type': mimeType,
                'Server': 'JCES'
            }
        };

        // return data
        callback(null, data);
    });
}
<commit_msg>wrap module scripts in file cache<commit_after>var fs = require('fs');
var zlib = require('zlib');
var mime = require('mime');
var minifyHtml = require('html-minifier').minify;
var minifyCSS =  require('clean-css');

var html_minifier_options = {
    removeComments: true,
    removeCommentsFromCDATA: true,
    removeCDATASectionsFromCDATA: true,
    removeAttributeQuotes: true,
    removeRedundantAttributes: true,
    removeEmptyAttributes: true,
    removeOptionalTags: true,
    collapseBooleanAttributes: true,
    collapseWhitespace: true
};

// save caches
var caches = {};

// this is not quaranteed to be stable!
zlib.Z_DEFAULT_COMPRESSION = 9;

module.exports = factory;

function factory (name, noCompression, dontOptimize) {

    // return existing cache
    if (caches[name]) {
        return caches[name];
    }

    // clone cache class
    var cache = Cache.clone();

    // create data container
    cache._data = {};

    // configure compression
    cache._noCompression = noCompression;

    // dont optimize html and css
    cache._dontOptimize = dontOptimize;

    // save cache
    caches[name] = cache;

    return cache;
}

// FileCache
var Cache = {

    // remove one or all item(s)
    rm: function (path) {

        // remove one item
        if (path) {
            return delete this._data[path];
        }

        // remove all items
        this._data = {};
    },

    // return one or all item(s)
    get: function (path) {

        // return one item
        if (path) {
            return this._data[path];
        }

        // return all items
        return this._data;
    },

    // set an item
    set: function (path, callback, dontWatch, moduleFile) {
        var self = this;

        // check if file is already in cache
        if (!dontWatch && self._data[path]) {
            return callback(null, self._data[path]);
        }

        // path must be absolute
        if (path.indexOf('../') !== -1) {
            return callback(new Error('Invalid path.'));
        }

        fs.readFile(path, function (err, data) {

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

            var mimeType = mime.lookup(path);

            // wrap module code files
            if (moduleFile) {
                data = new Buffer("Z.wrap('" + moduleFile + "',function(require,module,exports){\n" + data.toString() + "\nreturn module});");

            // optimize html or css
            } else if (!self._dontOptimize) {
                switch (mimeType) {
                    case 'text/html':
                        data = minifyHtml(data.toString('utf8'), html_minifier_options);
                        break;
                    case 'text/css':
                        data = new minifyCSS({processImport: false}).minify(data.toString('utf8'));
                        break;
                }
            }

            // don't compress data
            if (self._noCompression) {
                return createCacheObject.call(self, path, data, mimeType, callback, dontWatch);
            }

            zlib.gzip(data, function (err, data) {

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

                createCacheObject.call(self, path, data, mimeType, callback, dontWatch);
            });
        });
    }
};

function createCacheObject (path, data, mimeType, callback, dontWatch) {
    var self = this;

    fs.stat(path, function (err, stats) {

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

        // watch file and update cache on change (only in dev mode? i think so..)
        if (!dontWatch) {
            fs.watch(path, function (event) {

                // update cache data on file change
                if (event === 'change') {
                    self.set(path, function () {}, true);
                }
            });
        }

        // save zipped data in cache
        self._data[path] = data = {
            data: data,

            // create http headers
            http: {
                'Cache-Control': 'public, max-age=31536000',
                'Vary': 'Accept-Encoding',
                'Last-Modified': stats.mtime,
                'Content-Encoding': 'gzip',
                'Content-Length': data.length,
                'Content-Type': mimeType,
                'Server': 'JCES'
            }
        };

        // return data
        callback(null, data);
    });
}
<|endoftext|>


<commit_before>(function(global) {
    var rutil = (function(){

        'use strict';

        var rutil = {};

        var isArray = function(obj) {
            return Object.prototype.toString.call(obj) === '[object Array]';
        };

        var isObject = function(obj, isArray) {
            var isObject = (Object.prototype.toString.call(obj) === '[object Object]');
            if (isArray) {
                isObject = (typeof obj === 'object');
            }
            return isObject;
        };

        var merge = function(obj1, obj2){
            var obj3 = {},
            attrname;
            for (attrname in obj1) {
                obj3[attrname] = obj1[attrname];
            }
            for (attrname in obj2) {
                obj3[attrname] = obj2[attrname];
            }
            return obj3;
        };

        var serialize = function(obj, prefix) {
            var s = function(obj, prefix) {
                var str = [];
                for(var p in obj) {
                    var k = prefix ? prefix + '[' + p + ']' : p, v = obj[p];
                    if (v !== undefined && v !== null) {
                        var set;
                        if (isObject(v)) {
                            set = s(v, k);
                            str.push(set);
                        } else if (isArray(v)) {
                            v.forEach(function(n) {
                                set = encodeURIComponent(k) + '=' + encodeURIComponent(n);
                                str.push(set);
                            });
                        } else {
                            set = encodeURIComponent(k) + '=' + encodeURIComponent(v);
                            str.push(set);
                        }
                    }
                }
                return str.join('&');
            };
            return s(obj, prefix);
        };

        var createPixel = function(url, cb) {
            var postImage = document.createElement('img');
            postImage.style.visibility = 'hidden';
            postImage.style.width = '0px';
            postImage.style.height = '0px';
            postImage.src = url;
            postImage.onload = function() {
                postImage.src = '';
                cb && cb(null, url);
            };
            postImage.onerror = function(e) {
                cb && cb(e, url);
            };
            document.body.appendChild(postImage);
        };

        var getParams = function(url) {
            var params;
            try {
                var prmstr = window.location.search.substr(1);
                if (url) {
                    prmstr = url.split('?')[1];
                }
                var prmarr = prmstr.split('&');
                if (prmarr[0]) {
                    params = [];
                    for (var i = 0; i < prmarr.length; i++) {
                        var tmparr = prmarr[i].split('=');
                        params[tmparr[0]] = tmparr[1];
                    }
                }
            } catch(err) {}
            return params;
        };

        var setQueryStringParam = function(uri, key, value) {
            var regex = new RegExp('([?|&])' + key + '=.*?(&|#|$)', 'i');
            var separator = uri.indexOf('?') !== -1 ? '&' : '?';
            if (regex.test(uri)) {
                return uri.replace(regex, '$1' + key + '=' + value + '$2');
            } else {
                return uri + separator + key + '=' + value;
            }
        };

        /**
        * http://stackoverflow.com/a/2117523
        */
        var generateUUID = function() {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
                return v.toString(16);
            });
        };

        var generateRandomString = function(length, chars) {
            var str = [],
            i;
            length = length || 32;
            chars = chars || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
            for (i = 0; i < length; i++) {
                str.push(chars.charAt(Math.floor(Math.random() * chars.length)));
            }
            return str.join('');
        };

        var hexToRgb = function(hex) {
            // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
            var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
            hex = hex.replace(shorthandRegex, function(m, r, g, b) {
                return r + r + g + g + b + b;
            });

            var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
            return result ? {
                r: parseInt(result[1], 16),
                g: parseInt(result[2], 16),
                b: parseInt(result[3], 16)
            } : null;
        };

        /**
        * Returns an array of dates between the two dates
        */
        var getDatesInbetween = function(startDate, endDate) {
            var dates = [],
            currentDate = startDate,
            addDays = function(days) {
                var date = new Date(this.valueOf());
                date.setDate(date.getDate() + days);
                return date;
            };
            while (currentDate <= endDate) {
                dates.push(currentDate);
                currentDate = addDays.call(currentDate, 1);
            }
            return dates;
        };

        var isMobileDevice = function(device) {
            device = device || '';
            var regex = '';
            switch(device.toLowerCase()) {
                case 'android':
                    regex = new RegExp('Android', 'i');
                    break;
                case 'webos':
                    regex = new RegExp('webOS', 'i');
                    break;
                case 'iphone':
                    regex = new RegExp('iPhone', 'i');
                    break;
                case 'ipad':
                    regex = new RegExp('iPad', 'i');
                    break;
                case 'ios':
                    regex = new RegExp('(iPhone|iPad)', 'i');
                    break;
                case 'ios7':
                    regex = new RegExp('(iPad|iPhone);.*CPU.*OS 7_\\d', 'i');
                    break;
                case 'blackberry':
                    regex = new RegExp('BlackBerry', 'i');
                    break;
                case 'ie':
                    regex = new RegExp('IEMobile', 'i');
                    break;
                case 'opera':
                    regex = new RegExp('Opera Mini', 'i');
                    break;
                default:
                    regex = new RegExp('(Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini)', 'i');
                    break;
            }
            return regex.test(navigator.userAgent);
        };

        var sleep = function(ms) {
            var startTime = new Date().getTime();
            while (new Date().getTime() < startTime + ms);
        };

        var parseHashtag = function(str, url) {
            return str.replace(/[#]+[A-Za-z0-9-_]+/g, function(t) {
                var tmpUrl = url;
                var tag = t.replace('#','%23');
                tmpUrl = tmpUrl.replace(/\{\{\w+\}\}/g, tag);
                return t.link(tmpUrl);
            });
        };

        var parseUsername = function(str, url) {
            return str.replace(/[@]+[A-Za-z0-9-_]+/g, function(u) {
                var tmpUrl = url;
                var username = u.replace('@','');
                tmpUrl = tmpUrl.replace(/\{\{\w+\}\}/g, username);
                return u.link(tmpUrl);
            });
        };

        var parseUrl = function(str) {
            return str.replace(/[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&~\?\/.=]+/g, function(url) {
                return url.link(url);
            });
        };

        var stripTags = function(str) {
            return (str? str.replace(/(<([^>]+)>)/ig, '') : str);
        };

        var formatPhone = function(number) {
            return (number ? number.toString().replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3') : number);
        };

        var validateEmail = function(email) {
            var regex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
            return (email ? regex.test(email) : false);
        };

        var validateMinAge = function(birthDate, minAge) {
            var tmpDate = new Date(birthDate.getFullYear() + minAge, birthDate.getMonth(), birthDate.getDate()).setMonth(birthDate.getMonth() - 1);
            return (tmpDate <= new Date());
        };

        var validateZip = function(zip) {
            var regex = /(^\d{5}$)|(^\d{5}-\d{4}$)/;
            return regex.test(zip);
        };

        var validateUsername = function(username) {
            var regex = /^[a-zA-Z0-9_]+$/;
            return regex.test(username);
        };

        var validateName = function(name) {
            var regex = /^[a-zA-Z-' ]*$/;
            return regex.test(name);
        };

        var addCommas = function(n) {
            if (!n) return n;
            var parts = n.toString().split('.');
            parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
            return parts.join('.');
        };

        var toBool = function(str) {
            switch((str ? str.toLowerCase() : '')) {
                case 'true': case 'yes': case 'on': case '1': return true;
                default: return false;
            }
        };

        var prettyDate = function(date) {
            date.setMonth(date.getMonth() - 1);
            var dayNames = [
                'Sunday', 'Monday', 'Tuesday',
                'Wednesday', 'Thursday', 'Friday',
                'Saturday'
            ];
            var monthNames = [
                'January', 'February', 'March',
                'April', 'May', 'June',
                'July', 'August', 'September',
                'October', 'November', 'December'
            ];
            return dayNames[date.getDay()] + ' ' + monthNames[date.getMonth()] + ' ' + date.getDate() + ', ' + date.getFullYear();
        };

        // http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
        var shuffle = function(arr) {
            var array = [].slice.call(arr) || [];
            var currentIndex = array.length,
            temporaryValue,
            randomIndex;

            // While there remain elements to shuffle...
            while (0 !== currentIndex) {

                // Pick a remaining element...
                randomIndex = Math.floor(Math.random() * currentIndex);
                currentIndex -= 1;

                // And swap it with the current element.
                temporaryValue = array[currentIndex];
                array[currentIndex] = array[randomIndex];
                array[randomIndex] = temporaryValue;
            }

            return array;
        };

        var random = function(min, max) {
            var args = [].slice.call(arguments);
            if (args.length === 0) {
                throw new Error('Need at least one argument');
            }
            if (typeof max === 'undefined') {
                min = 0;
                max = args[0];
            }
            return Math.floor(Math.random() * (max - min + 1)) + min;
        };

        var repeat = function(str, times) {
            times = times || 2;
            return Array(times + 1).join(str);
        };

        var pad = function (num) {
            return ((num < 10 ? '0' : '') + num);
        };

        var capitalize = function(str, lower) {
            return (lower ? str.toLowerCase() : str).replace(/(?:^|\s)\S/g, function(a) {
                return a.toUpperCase();
            });
        };

        var _ = function(override) {
            var mixinObj = {};
            for (var k in rutil) {
                if (rutil.hasOwnProperty(k)) {
                    var exists = _ !== 'undefined' && _[k];
                    if (!override && exists) {
                        return;
                    }
                    mixinObj[k] = rutil[k];
                }
            }
            delete mixinObj.rutil;
            delete mixinObj.validate;
            delete mixinObj._;
            return mixinObj;
        };

        rutil.isArray = isArray;
        rutil.isObject = isObject;
        rutil.merge = merge;
        rutil.serialize = serialize;
        rutil.createPixel = createPixel;
        rutil.getParams = getParams;
        rutil.setQueryStringParam = setQueryStringParam;
        rutil.generateUUID = generateUUID;
        rutil.generateRandomString = generateRandomString;
        rutil.hexToRgb = hexToRgb;
        rutil.getDatesInbetween = getDatesInbetween;
        rutil.isMobileDevice = isMobileDevice;
        rutil.sleep = sleep;
        rutil.parseHashtag = parseHashtag;
        rutil.parseUsername = parseUsername;
        rutil.parseUrl = parseUrl;
        rutil.stripTags = stripTags;
        rutil.formatPhone = formatPhone;
        rutil.validate = {
            email: validateEmail,
            minAge: validateMinAge,
            zip: validateZip
        };
        rutil.isValidEmail = validateEmail;
        rutil.isValidMinAge = validateMinAge;
        rutil.isValidZip = validateZip;
        rutil.isValidUsername = validateUsername;
        rutil.isValidName = validateName;
        rutil.addCommas = addCommas;
        rutil.prettyDate = prettyDate;
        rutil.toBool = toBool;
        rutil.shuffle = shuffle;
        rutil.random = random;
        rutil.repeat = repeat;
        rutil.pad = pad;
        rutil.capitalize = capitalize;
        rutil._ = _;

        return rutil;

    })();

    if (typeof exports !== 'undefined') {
        if (typeof module !== 'undefined' && module.exports) {
            exports = module.exports = rutil;
        }
        exports.rutil = rutil;
    } else if (typeof define === 'function' && define.amd) {
        define([], function() {
            return rutil;
        });
    } else {
        global.rutil = rutil;
    }
})(this);
<commit_msg>true + 1<commit_after>(function(global) {
    var rutil = (function(){

        'use strict';

        var rutil = {};

        var isArray = function(obj) {
            return Object.prototype.toString.call(obj) === '[object Array]';
        };

        var isObject = function(obj, isArray) {
            var isObject = (Object.prototype.toString.call(obj) === '[object Object]');
            if (isArray) {
                isObject = (typeof obj === 'object');
            }
            return isObject;
        };

        var merge = function(obj1, obj2){
            var obj3 = {},
            attrname;
            for (attrname in obj1) {
                obj3[attrname] = obj1[attrname];
            }
            for (attrname in obj2) {
                obj3[attrname] = obj2[attrname];
            }
            return obj3;
        };

        var serialize = function(obj, prefix) {
            var s = function(obj, prefix) {
                var str = [];
                for(var p in obj) {
                    var k = prefix ? prefix + '[' + p + ']' : p, v = obj[p];
                    if (v !== undefined && v !== null) {
                        var set;
                        if (isObject(v)) {
                            set = s(v, k);
                            str.push(set);
                        } else if (isArray(v)) {
                            v.forEach(function(n) {
                                set = encodeURIComponent(k) + '=' + encodeURIComponent(n);
                                str.push(set);
                            });
                        } else {
                            set = encodeURIComponent(k) + '=' + encodeURIComponent(v);
                            str.push(set);
                        }
                    }
                }
                return str.join('&');
            };
            return s(obj, prefix);
        };

        var createPixel = function(url, cb) {
            var postImage = document.createElement('img');
            postImage.style.visibility = 'hidden';
            postImage.style.width = '0px';
            postImage.style.height = '0px';
            postImage.src = url;
            postImage.onload = function() {
                postImage.src = '';
                cb && cb(null, url);
            };
            postImage.onerror = function(e) {
                cb && cb(e, url);
            };
            document.body.appendChild(postImage);
        };

        var getParams = function(url) {
            var params;
            try {
                var prmstr = window.location.search.substr(1);
                if (url) {
                    prmstr = url.split('?')[1];
                }
                var prmarr = prmstr.split('&');
                if (prmarr[0]) {
                    params = [];
                    for (var i = 0; i < prmarr.length; i++) {
                        var tmparr = prmarr[i].split('=');
                        params[tmparr[0]] = tmparr[1];
                    }
                }
            } catch(err) {}
            return params;
        };

        var setQueryStringParam = function(uri, key, value) {
            var regex = new RegExp('([?|&])' + key + '=.*?(&|#|$)', 'i');
            var separator = uri.indexOf('?') !== -1 ? '&' : '?';
            if (regex.test(uri)) {
                return uri.replace(regex, '$1' + key + '=' + value + '$2');
            } else {
                return uri + separator + key + '=' + value;
            }
        };

        /**
        * http://stackoverflow.com/a/2117523
        */
        var generateUUID = function() {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
                return v.toString(16);
            });
        };

        var generateRandomString = function(length, chars) {
            var str = [],
            i;
            length = length || 32;
            chars = chars || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
            for (i = 0; i < length; i++) {
                str.push(chars.charAt(Math.floor(Math.random() * chars.length)));
            }
            return str.join('');
        };

        var hexToRgb = function(hex) {
            // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
            var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
            hex = hex.replace(shorthandRegex, function(m, r, g, b) {
                return r + r + g + g + b + b;
            });

            var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
            return result ? {
                r: parseInt(result[1], 16),
                g: parseInt(result[2], 16),
                b: parseInt(result[3], 16)
            } : null;
        };

        /**
        * Returns an array of dates between the two dates
        */
        var getDatesInbetween = function(startDate, endDate) {
            var dates = [],
            currentDate = startDate,
            addDays = function(days) {
                var date = new Date(this.valueOf());
                date.setDate(date.getDate() + days);
                return date;
            };
            while (currentDate <= endDate) {
                dates.push(currentDate);
                currentDate = addDays.call(currentDate, 1);
            }
            return dates;
        };

        var isMobileDevice = function(device) {
            device = device || '';
            var regex = '';
            switch(device.toLowerCase()) {
                case 'android':
                    regex = new RegExp('Android', 'i');
                    break;
                case 'webos':
                    regex = new RegExp('webOS', 'i');
                    break;
                case 'iphone':
                    regex = new RegExp('iPhone', 'i');
                    break;
                case 'ipad':
                    regex = new RegExp('iPad', 'i');
                    break;
                case 'ios':
                    regex = new RegExp('(iPhone|iPad)', 'i');
                    break;
                case 'ios7':
                    regex = new RegExp('(iPad|iPhone);.*CPU.*OS 7_\\d', 'i');
                    break;
                case 'blackberry':
                    regex = new RegExp('BlackBerry', 'i');
                    break;
                case 'ie':
                    regex = new RegExp('IEMobile', 'i');
                    break;
                case 'opera':
                    regex = new RegExp('Opera Mini', 'i');
                    break;
                default:
                    regex = new RegExp('(Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini)', 'i');
                    break;
            }
            return regex.test(navigator.userAgent);
        };

        var sleep = function(ms) {
            var startTime = new Date().getTime();
            while (new Date().getTime() < startTime + ms);
        };

        var parseHashtag = function(str, url) {
            return str.replace(/[#]+[A-Za-z0-9-_]+/g, function(t) {
                var tmpUrl = url;
                var tag = t.replace('#','%23');
                tmpUrl = tmpUrl.replace(/\{\{\w+\}\}/g, tag);
                return t.link(tmpUrl);
            });
        };

        var parseUsername = function(str, url) {
            return str.replace(/[@]+[A-Za-z0-9-_]+/g, function(u) {
                var tmpUrl = url;
                var username = u.replace('@','');
                tmpUrl = tmpUrl.replace(/\{\{\w+\}\}/g, username);
                return u.link(tmpUrl);
            });
        };

        var parseUrl = function(str) {
            return str.replace(/[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&~\?\/.=]+/g, function(url) {
                return url.link(url);
            });
        };

        var stripTags = function(str) {
            return (str? str.replace(/(<([^>]+)>)/ig, '') : str);
        };

        var formatPhone = function(number) {
            return (number ? number.toString().replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3') : number);
        };

        var validateEmail = function(email) {
            var regex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
            return (email ? regex.test(email) : false);
        };

        var validateMinAge = function(birthDate, minAge) {
            var tmpDate = new Date(birthDate.getFullYear() + minAge, birthDate.getMonth(), birthDate.getDate()).setMonth(birthDate.getMonth() - 1);
            return (tmpDate <= new Date());
        };

        var validateZip = function(zip) {
            var regex = /(^\d{5}$)|(^\d{5}-\d{4}$)/;
            return regex.test(zip);
        };

        var validateUsername = function(username) {
            var regex = /^[a-zA-Z0-9_]+$/;
            return regex.test(username);
        };

        var validateName = function(name) {
            var regex = /^[a-zA-Z-' ]*$/;
            return regex.test(name);
        };

        var addCommas = function(n) {
            if (!n) return n;
            var parts = n.toString().split('.');
            parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
            return parts.join('.');
        };

        var toBool = function(str) {
            switch((str ? str.toLowerCase() : '')) {
                case 'true': case 'yes': case 'on': case '1': return true;
                default: return false;
            }
        };

        var prettyDate = function(date) {
            date.setMonth(date.getMonth() - 1);
            var dayNames = [
                'Sunday', 'Monday', 'Tuesday',
                'Wednesday', 'Thursday', 'Friday',
                'Saturday'
            ];
            var monthNames = [
                'January', 'February', 'March',
                'April', 'May', 'June',
                'July', 'August', 'September',
                'October', 'November', 'December'
            ];
            return dayNames[date.getDay()] + ' ' + monthNames[date.getMonth()] + ' ' + date.getDate() + ', ' + date.getFullYear();
        };

        // http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
        var shuffle = function(arr) {
            var array = [].slice.call(arr) || [];
            var currentIndex = array.length,
            temporaryValue,
            randomIndex;

            // While there remain elements to shuffle...
            while (0 !== currentIndex) {

                // Pick a remaining element...
                randomIndex = Math.floor(Math.random() * currentIndex);
                currentIndex -= 1;

                // And swap it with the current element.
                temporaryValue = array[currentIndex];
                array[currentIndex] = array[randomIndex];
                array[randomIndex] = temporaryValue;
            }

            return array;
        };

        var random = function(min, max) {
            var args = [].slice.call(arguments);
            if (args.length === 0) {
                throw new Error('Need at least one argument');
            }
            if (typeof max === 'undefined') {
                min = 0;
                max = args[0];
            }
            return Math.floor(Math.random() * (max - min + 1)) + min;
        };

        var repeat = function(str, times) {
            times = times || 2;
            return Array(times + 1).join(str);
        };

        var pad = function (num) {
            return ((num < 10 ? '0' : '') + num);
        };

        var capitalize = function(str, lower) {
            return (lower ? str.toLowerCase() : str).replace(/(?:^|\s)\S/g, function(a) {
                return a.toUpperCase();
            });
        };

        /*
        //TODO
        function isTruthy(x) {
        return x;
        }

        function isFalsy(x) {
        return !istruthy(x);
        }

        function execFunc(func) {
        return _.isFunction(func) ? func() : _.noop();
        }

        function preCondition(array, success, fail) {
        if (_.every(array, truthy)) {
        execFunc(success);
        } else {
        execFunc(fail);
        }
        }

        function addEvent(element, eventName, func) {
        if (element.addEventListener) {
        return element.addEventListener(eventName, func, false);
        } else if (element.attachEvent) {
        return element.attachEvent("on" + eventName, func);
        }
        };

        var prop = function(obj) {
        return function(name) {
        return obj[name];
        };
        };

        var textNode = document.createTextNode.bind(document);

        var wrap = function(elementType) {
        return function(child) {
        var parent = document.createElement(elementType);
        parent.appendChild(child);
        return parent;
        };
        };

        var append = function(parent, child) {
        parent.appendChild(child);
        return parent;
        };
        var append = function(parent, child) {
        parent.appendChild(child);
        return parent;
        };
        ))

    function hasClass(elem, className) {
        return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' ');
    }

    function addClass(elem, className) {
        if (!hasClass(elem, className)) {
            elem.className += ' ' + className;
        }
    }

    function removeClass(elem, className) {
        var newClass = ' ' + elem.className.replace( /[\t\r\n]/g, ' ') + ' ';
        if (hasClass(elem, className)) {
            while (newClass.indexOf(' ' + className + ' ') >= 0 ) {
                newClass = newClass.replace(' ' + className + ' ', ' ');
            }
            elem.className = newClass.replace(/^\s+|\s+$/g, '');
        }
    }

        function flat(ary) {
         return [].concat.apply([], Array.isArray(ary) ? ary.map(function(item) {
           return Array.isArray(item) ? flat(item) : item;
            }) : [ary]);
            }

     function sum() {¬
      ¦   return _.reduce(flat(arguments), function (acc, n) {¬
       ¦   ¦   return acc += n;¬
        ¦   }, 0);¬
         ¬

        function int(x) {
            return parseInt(x, 10);
        }

        //Returns true if it is a DOM node
        //function isNode(o){
        //  return (
        //      typeof Node === "object" ? o instanceof Node :
        //          o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string"
        //            );
        //            }
        //
        //            //Returns true if it is a DOM element
        //            function isElement(o){
        //              return (
        //                  typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2
        //                      o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName==="string"
        //                      );
        //                      }}

    function noop() {
        return function(){};
    }

			function isDateInRange(start, stop, now) {
				return (now.valueOf() >= start.valueOf() && now.valueOf() <= stop.valueOf()) ? true : false;
			}

function compactObject(obj) {
    _.forOwn(obj, function(val, key) {
       if (_.isEmpty(val)) delete obj[key];
    });
    return obj;
}

function d3_functor(v) {
  return typeof v === "function" ? v : function() { return v; };
  }
  function d3_class(ctor, properties) {
    try {
        for (var key in properties) {
              Object.defineProperty(ctor.prototype, key, {
                      value: properties[key],
                              enumerable: false
                                    });
                                        }
                                          } catch (e) {
                                              ctor.prototype = properties;
                                                }
                                                }])
        */

        var _ = function(override) {
            var mixinObj = {};
            for (var k in rutil) {
                if (rutil.hasOwnProperty(k)) {
                    var exists = _ !== 'undefined' && _[k];
                    if (!override && exists) {
                        return;
                    }
                    mixinObj[k] = rutil[k];
                }
            }
            delete mixinObj.rutil;
            delete mixinObj.validate;
            delete mixinObj._;
            return mixinObj;
        };

        rutil.isArray = isArray;
        rutil.isObject = isObject;
        rutil.merge = merge;
        rutil.serialize = serialize;
        rutil.createPixel = createPixel;
        rutil.getParams = getParams;
        rutil.setQueryStringParam = setQueryStringParam;
        rutil.generateUUID = generateUUID;
        rutil.generateRandomString = generateRandomString;
        rutil.hexToRgb = hexToRgb;
        rutil.getDatesInbetween = getDatesInbetween;
        rutil.isMobileDevice = isMobileDevice;
        rutil.sleep = sleep;
        rutil.parseHashtag = parseHashtag;
        rutil.parseUsername = parseUsername;
        rutil.parseUrl = parseUrl;
        rutil.stripTags = stripTags;
        rutil.formatPhone = formatPhone;
        rutil.validate = {
            email: validateEmail,
            minAge: validateMinAge,
            zip: validateZip
        };
        rutil.isValidEmail = validateEmail;
        rutil.isValidMinAge = validateMinAge;
        rutil.isValidZip = validateZip;
        rutil.isValidUsername = validateUsername;
        rutil.isValidName = validateName;
        rutil.addCommas = addCommas;
        rutil.prettyDate = prettyDate;
        rutil.toBool = toBool;
        rutil.shuffle = shuffle;
        rutil.random = random;
        rutil.repeat = repeat;
        rutil.pad = pad;
        rutil.capitalize = capitalize;
        rutil._ = _;

        return rutil;

    })();

    if (typeof exports !== 'undefined') {
        if (typeof module !== 'undefined' && module.exports) {
            exports = module.exports = rutil;
        }
        exports.rutil = rutil;
    } else if (typeof define === 'function' && define.amd) {
        define([], function() {
            return rutil;
        });
    } else {
        global.rutil = rutil;
    }
})(this);
<|endoftext|>