<commit_before>Ext.namespace('Gemma');
Ext.BLANK_IMAGE_URL = '/Gemma/images/default/s.gif';
/**
 *
 * Used as one tab of the EE page - the "Admin" tab.
 *
 * pass in the ee details obj as experimentDetails
 *
 * @class Gemma.ExpressionExperimentDetails
 * @extends Ext.Panel
 * version $Id$
 *
 */
Gemma.ExpressionExperimentTools = Ext.extend(Ext.Panel, {
    experimentDetails: null,
    border: false,
    tbar: new Ext.Toolbar(),
	defaultType:'box',
    defaults:{
		border:false
	},
	padding:10,
    initComponent: function(){
        Gemma.ExpressionExperimentTools.superclass.initComponent.call(this);
        var manager = new Gemma.EEManager({
            editable: this.editable
        });
        manager.on('reportUpdated', function(){
        	this.fireEvent('reloadNeeded');
        },this);
        var refreshButton = new Ext.Button({
            text: 'Refresh',
            icon: '/Gemma/images/icons/arrow_refresh_small.png',
            tooltip: 'Refresh statistics (not including the differential expression ones)',
            handler: function(){
                manager.updateEEReport(this.experimentDetails.id);
            },
            scope: this

        });

        this.getTopToolbar().addButton(refreshButton);
        this.add({
            html: '
Analyses:

'
        });

		var missingValueInfo = this.missingValueAnalysisPanelRenderer(this.experimentDetails, manager);
		this.add(missingValueInfo);
		var processedVectorInfo = this.processedVectorCreatePanelRenderer(this.experimentDetails, manager);
		this.add(processedVectorInfo);
		var differentialAnalysisInfo = this.differentialAnalysisPanelRenderer(this.experimentDetails, manager);
		this.add(differentialAnalysisInfo);
		var linkAnalysisInfo = this.linkAnalysisPanelRenderer(this.experimentDetails, manager);
		this.add(linkAnalysisInfo);

    },

    linkAnalysisPanelRenderer: function(ee, manager){
		var panel = new Ext.Panel({
			layout: 'hbox',
			defaults: {
				border: false,
				padding:2
			},
			items: [{
				html: 'Link Analysis: '
			}]
		});
        var id = ee.id;
		var runBtn = new Ext.Button({
			icon:'/Gemma/images/icons/control_play_blue.png',
			tooltip:'missing value computation',
			handler: manager.doLinks.createDelegate(this,[id]),
			scope:this,
			cls:'transparent-btn'
		});
        if (ee.dateLinkAnalysis) {
            var type = ee.linkAnalysisEventType;
            var color = "#000";
            var suggestRun = true;
            var qtip = 'ext:qtip="Analysis was OK"';
            if (type == 'FailedLinkAnalysisEventImpl') {
                color = 'red';
                qtip = 'ext:qtip="Analysis failed"';
            }
            else
                if (type == 'TooSmallDatasetLinkAnalysisEventImpl') {
                    color = '#CCC';
                    qtip = 'ext:qtip="Analysis was too small"';
                    suggestRun = false;
                }
            panel.add({
				html: '' +
				Ext.util.Format.date(ee.dateLinkAnalysis, 'y/M/d')
			});
			if(suggestRun){
				panel.add(runBtn);
			}
			return panel;
        }
        else {
			panel.add({html:'Needed '});
			panel.add(runBtn);
            return panel;
        }

    },
    missingValueAnalysisPanelRenderer: function(ee, manager){
		var panel = new Ext.Panel({
			layout: 'hbox',
			defaults: {
				border: false,
				padding:2
			},
			items: [{
				html: 'Missing values: '
			}]
		});
        var id = ee.id;
		var runBtn = new Ext.Button({
			icon:'/Gemma/images/icons/control_play_blue.png',
			tooltip:'missing value computation',
			handler: manager.doMissingValues.createDelegate(this,[id]),
			scope:this,
			cls:'transparent-btn'
		});
        /*
         * Offer missing value analysis if it's possible (this might need
         * tweaking).
         */
        if (ee.technologyType != 'ONECOLOR' && ee.hasEitherIntensity) {

            if (ee.dateMissingValueAnalysis) {
                var type = ee.missingValueAnalysisEventType;
                var color = "#000";
                var suggestRun = true;
                var qtip = 'ext:qtip="OK"';
                if (type == 'FailedMissingValueAnalysisEventImpl') {
                    color = 'red';
                    qtip = 'ext:qtip="Failed"';
                }

                //return '' +
                //Ext.util.Format.date(ee.dateMissingValueAnalysis, 'y/M/d') +
                //' ' +
                //(suggestRun ? runurl : '');
				panel.add({ html: '' +
					Ext.util.Format.date(ee.dateMissingValueAnalysis, 'y/M/d') +
					' '});
					if(suggestRun){
						panel.add(runBtn);
					}
				return panel;
            }
            else {
				panel.add({
					html: 'Needed '
				});
				panel.add(runBtn);
                return panel;
            }

        }
        else {

				panel.add({
					html: 'NA'
				});
                return panel;
        }
    },

    processedVectorCreatePanelRenderer: function(ee, manager){
        var panel = new Ext.Panel({
			layout: 'hbox',
			defaults: {
				border: false,
				padding:2
			},
			items: [{
				html: 'Proccessed Vector Computation: '
			}]
		});
        var id = ee.id;
		var runBtn = new Ext.Button({
			icon:'/Gemma/images/icons/control_play_blue.png',
			tooltip:'processed vector computation',
			handler: manager.doProcessedVectors.createDelegate(this,[id]),
			scope:this,
			cls:'transparent-btn'
		});
        if (ee.dateProcessedDataVectorComputation) {
            var type = ee.processedDataVectorComputationEventType;
            var color = "#000";

            var suggestRun = true;
            var qtip = 'ext:qtip="OK"';
            if (type == 'FailedProcessedVectorComputationEventImpl') { // note:
                // no
                // such
                // thing.
                color = 'red';
                qtip = 'ext:qtip="Failed"';
            }
            panel.add({html:'' +
            Ext.util.Format.date(ee.dateProcessedDataVectorComputation, 'y/M/d') +
            ' '});
			if(suggestRun){
				panel.add(runBtn);
			}
            return panel;
        }
        else {
			panel.add({html:'Needed '});
			panel.add(runBtn);
            return panel;
        }
    },

    differentialAnalysisPanelRenderer: function(ee, manager){
        var panel = new Ext.Panel({
			layout: 'hbox',
			defaults: {
				border: false,
				padding:2
			},
			items: [{
				html: 'Differential Expression Analysis: '
			}]
		});
        var id = ee.id;
		var runBtn = new Ext.Button({
			icon:'/Gemma/images/icons/control_play_blue.png',
			tooltip:'differential expression analysis',
			handler: manager.doDifferential.createDelegate(this,[id]),
			scope:this,
			cls:'transparent-btn'
		});
        if (ee.numPopulatedFactors > 0) {
            if (ee.dateDifferentialAnalysis) {
                var type = ee.differentialAnalysisEventType;

                var color = "#000";
                var suggestRun = true;
                var qtip = 'ext:qtip="OK"';
                if (type == 'FailedDifferentialExpressionAnalysisEventImpl') { // note:
                    // no
                    // such
                    // thing.
                    color = 'red';
                    qtip = 'ext:qtip="Failed"';
                }
                panel.add({html:'' +
                Ext.util.Format.date(ee.dateDifferentialAnalysis, 'y/M/d') +
                ' '});
				if(suggestRun){
					panel.add(runBtn);
				}
                return panel;
            }
            else {

                panel.add({html:'Needed '});
				panel.add(runBtn);
                return panel;
            }
        }
        else {

            panel.add({html:'NA'});
            return panel;
        }
    },
    renderProcessedExpressionVectorCount: function(e){
        return e.processedExpressionVectorCount ? e.processedExpressionVectorCount : ' [count not available] ';
    }
});

<commit_msg>Run buttons and dates for Batch Information and PCA are added under the Admin tab of experiment details<commit_after>Ext.namespace('Gemma');
Ext.BLANK_IMAGE_URL = '/Gemma/images/default/s.gif';
/**
 *
 * Used as one tab of the EE page - the "Admin" tab.
 *
 * pass in the ee details obj as experimentDetails
 *
 * @class Gemma.ExpressionExperimentDetails
 * @extends Ext.Panel
 * version $Id$
 *
 */
Gemma.ExpressionExperimentTools = Ext.extend(Ext.Panel, {
    experimentDetails: null,
    border: false,
    tbar: new Ext.Toolbar(),
	defaultType:'box',
    defaults:{
		border:false
	},
	padding:10,
    initComponent: function(){
        Gemma.ExpressionExperimentTools.superclass.initComponent.call(this);
        var manager = new Gemma.EEManager({
            editable: this.editable
        });
        manager.on('reportUpdated', function(){
        	this.fireEvent('reloadNeeded');
        },this);
        var refreshButton = new Ext.Button({
            text: 'Refresh',
            icon: '/Gemma/images/icons/arrow_refresh_small.png',
            tooltip: 'Refresh statistics (not including the differential expression ones)',
            handler: function(){
                manager.updateEEReport(this.experimentDetails.id);
            },
            scope: this

        });

        this.getTopToolbar().addButton(refreshButton);

        this.add({
            html: '
Preprocessing:

'
        });
		var missingValueInfo = this.missingValueAnalysisPanelRenderer(this.experimentDetails, manager);
		this.add(missingValueInfo);
		var processedVectorInfo = this.processedVectorCreatePanelRenderer(this.experimentDetails, manager);
		this.add(processedVectorInfo);
		// PCA analysis
		var pcaInfo = this.pcaPanelRenderer(this.experimentDetails, manager);
		this.add(pcaInfo);
		// Batch information
		var batchInfo = this.batchPanelRenderer(this.experimentDetails, manager);
		this.add(batchInfo);

		this.add({
            html: '
Analyses:

'
        });
		var differentialAnalysisInfo = this.differentialAnalysisPanelRenderer(this.experimentDetails, manager);
		this.add(differentialAnalysisInfo);
		var linkAnalysisInfo = this.linkAnalysisPanelRenderer(this.experimentDetails, manager);
		this.add(linkAnalysisInfo);

    },

    linkAnalysisPanelRenderer: function(ee, manager){
		var panel = new Ext.Panel({
			layout: 'hbox',
			defaults: {
				border: false,
				padding:2
			},
			items: [{
				html: 'Link Analysis: '
			}]
		});
        var id = ee.id;
		var runBtn = new Ext.Button({
			icon:'/Gemma/images/icons/control_play_blue.png',
			tooltip:'missing value computation',
			handler: manager.doLinks.createDelegate(this,[id]),
			scope:this,
			cls:'transparent-btn'
		});
        if (ee.dateLinkAnalysis) {
            var type = ee.linkAnalysisEventType;
            var color = "#000";
            var suggestRun = true;
            var qtip = 'ext:qtip="Analysis was OK"';
            if (type == 'FailedLinkAnalysisEventImpl') {
                color = 'red';
                qtip = 'ext:qtip="Analysis failed"';
            }
            else
                if (type == 'TooSmallDatasetLinkAnalysisEventImpl') {
                    color = '#CCC';
                    qtip = 'ext:qtip="Analysis was too small"';
                    suggestRun = false;
                }
            panel.add({
				html: '' +
				Ext.util.Format.date(ee.dateLinkAnalysis, 'y/M/d')
			});
			if(suggestRun){
				panel.add(runBtn);
			}
			return panel;
        }
        else {
			panel.add({html:'Needed '});
			panel.add(runBtn);
            return panel;
        }

    },
    missingValueAnalysisPanelRenderer: function(ee, manager){
		var panel = new Ext.Panel({
			layout: 'hbox',
			defaults: {
				border: false,
				padding:2
			},
			items: [{
				html: 'Missing values: '
			}]
		});
        var id = ee.id;
		var runBtn = new Ext.Button({
			icon:'/Gemma/images/icons/control_play_blue.png',
			tooltip:'missing value computation',
			handler: manager.doMissingValues.createDelegate(this,[id]),
			scope:this,
			cls:'transparent-btn'
		});
        /*
         * Offer missing value analysis if it's possible (this might need
         * tweaking).
         */
        if (ee.technologyType != 'ONECOLOR' && ee.hasEitherIntensity) {

            if (ee.dateMissingValueAnalysis) {
                var type = ee.missingValueAnalysisEventType;
                var color = "#000";
                var suggestRun = true;
                var qtip = 'ext:qtip="OK"';
                if (type == 'FailedMissingValueAnalysisEventImpl') {
                    color = 'red';
                    qtip = 'ext:qtip="Failed"';
                }

                //return '' +
                //Ext.util.Format.date(ee.dateMissingValueAnalysis, 'y/M/d') +
                //' ' +
                //(suggestRun ? runurl : '');
				panel.add({ html: '' +
					Ext.util.Format.date(ee.dateMissingValueAnalysis, 'y/M/d') +
					' '});
					if(suggestRun){
						panel.add(runBtn);
					}
				return panel;
            }
            else {
				panel.add({
					html: 'Needed '
				});
				panel.add(runBtn);
                return panel;
            }

        }
        else {

				panel.add({
					html: 'NA'
				});
                return panel;
        }
    },

    processedVectorCreatePanelRenderer: function(ee, manager){
        var panel = new Ext.Panel({
			layout: 'hbox',
			defaults: {
				border: false,
				padding:2
			},
			items: [{
				html: 'Processed Vector Computation: '
			}]
		});
        var id = ee.id;
		var runBtn = new Ext.Button({
			icon:'/Gemma/images/icons/control_play_blue.png',
			tooltip:'processed vector computation',
			handler: manager.doProcessedVectors.createDelegate(this,[id]),
			scope:this,
			cls:'transparent-btn'
		});
        if (ee.dateProcessedDataVectorComputation) {
            var type = ee.processedDataVectorComputationEventType;
            var color = "#000";

            var suggestRun = true;
            var qtip = 'ext:qtip="OK"';
            if (type == 'FailedProcessedVectorComputationEventImpl') { // note:
                // no
                // such
                // thing.
                color = 'red';
                qtip = 'ext:qtip="Failed"';
            }
            panel.add({html:'' +
            Ext.util.Format.date(ee.dateProcessedDataVectorComputation, 'y/M/d') +
            ' '});
			if(suggestRun){
				panel.add(runBtn);
			}
            return panel;
        }
        else {
			panel.add({html:'Needed '});
			panel.add(runBtn);
            return panel;
        }
    },

    differentialAnalysisPanelRenderer: function(ee, manager){
        var panel = new Ext.Panel({
			layout: 'hbox',
			defaults: {
				border: false,
				padding:2
			},
			items: [{
				html: 'Differential Expression Analysis: '
			}]
		});
        var id = ee.id;
		var runBtn = new Ext.Button({
			icon:'/Gemma/images/icons/control_play_blue.png',
			tooltip:'differential expression analysis',
			handler: manager.doDifferential.createDelegate(this,[id]),
			scope:this,
			cls:'transparent-btn'
		});
        if (ee.numPopulatedFactors > 0) {
            if (ee.dateDifferentialAnalysis) {
                var type = ee.differentialAnalysisEventType;

                var color = "#000";
                var suggestRun = true;
                var qtip = 'ext:qtip="OK"';
                if (type == 'FailedDifferentialExpressionAnalysisEventImpl') { // note:
                    // no
                    // such
                    // thing.
                    color = 'red';
                    qtip = 'ext:qtip="Failed"';
                }
                panel.add({html:'' +
                Ext.util.Format.date(ee.dateDifferentialAnalysis, 'y/M/d') +
                ' '});
				if(suggestRun){
					panel.add(runBtn);
				}
                return panel;
            }
            else {

                panel.add({html:'Needed '});
				panel.add(runBtn);
                return panel;
            }
        }
        else {

            panel.add({html:'NA'});
            return panel;
        }
    },

    renderProcessedExpressionVectorCount: function(e){
        return e.processedExpressionVectorCount ? e.processedExpressionVectorCount : ' [count not available] ';
    } ,

    /*
     * Get the last date PCA was run, add a button to run PCA
     */
    pcaPanelRenderer: function(ee, manager){
    	var panel = new Ext.Panel({
			layout: 'hbox',
			defaults: {
				border: false,
				padding:2
			},
			items: [{
				html: 'Principal Component Analysis: '
			}]
		});
        var id = ee.id;
		var runBtn = new Ext.Button({
			icon:'/Gemma/images/icons/control_play_blue.png',
			tooltip:'principal component analysis',
			// See EEManger.js doPca(id, hasPca)
			handler: manager.doPca.createDelegate(this,[id, true]),
			scope:this,
			cls:'transparent-btn'
		});

		// Get date and info
		if (ee.datePcaAnalysis) {
			var type = ee.pcaAnalysisEventType;

			var color = "#000";
			var qtip = 'ext:qtip="OK"';
			var suggestRun = true;

			if (type == 'FailedPCAAnalysisEventImpl') {
                color = 'red';
                qtip = 'ext:qtip="Failed"';
			}
			panel.add({html:'' +
				Ext.util.Format.date(ee.datePcaAnalysis, 'y/M/d') + ' '});
		}
		else panel.add({html:'Needed ' });

		panel.add(runBtn);
		return panel;

    } ,

    /*
     * Get the last date batch info was downloaded, add a button to download
     */
    batchPanelRenderer: function(ee, manager){
    	var panel = new Ext.Panel({
    		layout: 'hbox',
    		defaults: {
				border: false,
				padding:2
			},
			items: [{
				html: 'Batch Information: '
			}]
    	});
    	var id = ee.id;
    	var runBtn = new Ext.Button({
			icon:'/Gemma/images/icons/control_play_blue.png',
			tooltip:'batch information',
			// See EEManager.js doBatchInfoFetch(id)
			handler: manager.doBatchInfoFetch.createDelegate(this,[id]),
			scope:this,
			cls:'transparent-btn'
    	});

    	// Get date and info
		if (ee.dateBatchFetch) {
			var type = ee.batchFetchEventType;

			var color = "#000";
			var qtip = 'ext:qtip="OK"';
			var suggestRun = true;

			if (type == 'FailedBatchInformationFetchingEventImpl') {
                color = 'red';
                qtip = 'ext:qtip="Failed"';
			} else if (type == 'FailedBatchInformationMissingEventImpl') {
				color = '#CCC';
                qtip = 'ext:qtip="Raw data files not available from source"';
			}

			panel.add({html:'' +
				Ext.util.Format.date(ee.dateBatchFetch, 'y/M/d') + ' '});
		}
		else panel.add({html:'Needed ' });

    	panel.add(runBtn);
    	return panel;
    }
});

<|endoftext|>


<commit_before>/**
 * @author Geert Fokke [geert@sector22.com]
 * @www sector22.com
 */

// @formatter:off

var specialCharacterRegExp      = /[^\w-]/g;
var cameCaseRexp                = /[^\w]+(\w)/g;
var hypenateRegExp              = /([A-Z]+)|(?:[^\w]+)(\w)/g;

// @formatter:on

/**
 * Collection of useful util functions when dealing with strings
 * @namespace
 */
var stringUtils = {};

stringUtils.camelCase = function camelCase ( string ) {

    if(!string || !string.length) return '';
    string = string.replace( cameCaseRexp, camelCaseReplacer );
    string = string.charAt( 0 ).toLowerCase() + string.slice( 1 ); // force lower case on first letter
    return string;

}

stringUtils.hyphenate = function hyphenate ( string ) {

    if(!string || !string.length) return '';
    string = string.replace( hypenateRegExp, hyphenateReplacer );
    string = string.replace(/^-/, ''); // make sure we didn't place a hyphen as the first character
    return string;

}

function camelCaseReplacer ( match, group1 ) {

    return group1 ? group1.toUpperCase() : '';

}

function hyphenateReplacer ( match, group1, group2 ) {

    if(group1) {

        return '-' + group1.toLowerCase();

    } else if(group2) {

        return '-' + group2.toLowerCase();

    }

    return '';

}

if( typeof Object.freeze === 'function' ) Object.freeze( stringUtils ) // lock the object to minimize accidental changes

module.exports = stringUtils;<commit_msg>Added normalise function to stringutils<commit_after>/**
 * @author Geert Fokke [geert@sector22.com]
 * @www sector22.com
 */

// @formatter:off

var cameCaseRexp                = /[^\w]+(\w)/g;
var hypenateRegExp              = /([A-Z]+)|(?:[^\w]+)(\w)/g;
var basicKeyboardRegexp         = /^[\w\s\d§±`~!@#$%^&*()\-=+{}\[\];'\\:"|,./<>?]*$/g

var accented = {
    A: /[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g,
    AA:/[\uA732]/g,
    AE:/[\u00C6\u01FC\u01E2]/g,
    AO:/[\uA734]/g,
    AU:/[\uA736]/g,
    AV:/[\uA738\uA73A]/g,
    AY:/[\uA73C]/g,
    B: /[\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g,
    C: /[\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g,
    D: /[\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g,
    DZ:/[\u01F1\u01C4]/g,
    Dz:/[\u01F2\u01C5]/g,
    E: /[\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g,
    F: /[\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g,
    G: /[\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g,
    H: /[\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g,
    I: /[\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g,
    J: /[\u004A\u24BF\uFF2A\u0134\u0248]/g,
    K: /[\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g,
    L: /[\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g,
    LJ:/[\u01C7]/g,
    Lj:/[\u01C8]/g,
    M: /[\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g,
    N: /[\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g,
    NJ:/[\u01CA]/g,
    Nj:/[\u01CB]/g,
    O: /[\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g,
    OI:/[\u01A2]/g,
    OO:/[\uA74E]/g,
    OU:/[\u0222]/g,
    P: /[\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g,
    Q: /[\u0051\u24C6\uFF31\uA756\uA758\u024A]/g,
    R: /[\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g,
    S: /[\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g,
    T: /[\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g,
    TZ:/[\uA728]/g,
    U: /[\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g,
    V: /[\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g,
    VY:/[\uA760]/g,
    W: /[\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g,
    X: /[\u0058\u24CD\uFF38\u1E8A\u1E8C]/g,
    Y: /[\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g,
    Z: /[\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g,
    a: /[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250]/g,
    aa:/[\uA733]/g,
    ae:/[\u00E6\u01FD\u01E3]/g,
    ao:/[\uA735]/g,
    au:/[\uA737]/g,
    av:/[\uA739\uA73B]/g,
    ay:/[\uA73D]/g,
    b: /[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253]/g,
    c: /[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184]/g,
    d: /[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A]/g,
    dz:/[\u01F3\u01C6]/g,
    e: /[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD]/g,
    f: /[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C]/g,
    g: /[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F]/g,
    h: /[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265]/g,
    hv:/[\u0195]/g,
    i: /[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131]/g,
    j: /[\u006A\u24D9\uFF4A\u0135\u01F0\u0249]/g,
    k: /[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3]/g,
    l: /[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747]/g,
    lj:/[\u01C9]/g,
    m: /[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F]/g,
    n: /[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5]/g,
    nj:/[\u01CC]/g,
    o: /[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275]/g,
    oe:/[\u0153]/g,
    oi:/[\u01A3]/g,
    ou:/[\u0223]/g,
    oo:/[\uA74F]/g,
    p:/[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755]/g,
    q:/[\u0071\u24E0\uFF51\u024B\uA757\uA759]/g,
    r:/[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783]/g,
    s:/[\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B]/g,
    t:/[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787]/g,
    tz:/[\uA729]/g,
    u:/[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289]/g,
    v:/[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C]/g,
    vy:/[\uA761]/g,
    w:/[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73]/g,
    x:/[\u0078\u24E7\uFF58\u1E8B\u1E8D]/g,
    y:/[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF]/g,
    z:/[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763]/g
}

// @formatter:on

/**
 * Collection of useful util functions when dealing with strings
 * @namespace
 */
var stringUtils = {};

stringUtils.camelCase = function camelCase ( string ) {

    if( !string || !string.length ) return '';
    string = string.replace( cameCaseRexp, camelCaseReplacer );
    string = string.charAt( 0 ).toLowerCase() + string.slice( 1 ); // force lower case on first letter
    return string;

}

stringUtils.hyphenate = function hyphenate ( string ) {

    if( !string || !string.length ) return '';
    string = string.replace( hypenateRegExp, hyphenateReplacer );
    string = string.replace( /^-/, '' ); // make sure we didn't place a hyphen as the first character
    return string;

}

/**
 * Function to remove accents from a string
 * @see: http://stackoverflow.com/questions/227950/programatic-accent-reduction-in-javascript-aka-text-normalization-or-unaccentin
 * @param string {string}
 * @returns {string}
 */
stringUtils.normalize = function normalize ( string ) {

    if( !string || !string.length ) return '';

    // perform a quick test to see if the string actually contains any unusual characters
    if( basicKeyboardRegexp.test( string ) ) return string;

    for ( var char in accented ) string = string.replace( accented[ char ], char );

    return string;

}

// Helper functions

function camelCaseReplacer ( match, group1 ) {

    return group1 ? group1.toUpperCase() : '';

}

function hyphenateReplacer ( match, group1, group2 ) {

    if( group1 ) {

        return '-' + group1.toLowerCase();

    } else if( group2 ) {

        return '-' + group2.toLowerCase();

    }

    return '';

}

if( typeof Object.freeze === 'function' ) Object.freeze( stringUtils ) // lock the object to minimize accidental changes

module.exports = stringUtils;

<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc service
 * @name $animateCss
 * @kind object
 *
 * @description
 * This is the core version of `$animateCss`. By default, only when the `ngAnimate` is included,
 * then the `$animateCss` service will actually perform animations.
 *
 * Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}.
 */
var $CoreAnimateCssProvider = function() {
  this.$get = ['$$rAF', '$q', function($$rAF, $q) {

    var RAFPromise = function() {};
    RAFPromise.prototype = {
      done: function(cancel) {
        this.defer && this.defer[cancel === true ? 'reject' : 'resolve']();
      },
      end: function() {
        this.done();
      },
      cancel: function() {
        this.done(true);
      },
      getPromise: function() {
        if (!this.defer) {
          this.defer = $q.defer();
        }
        return this.defer.promise;
      },
      then: function(f1,f2) {
        return this.getPromise().then(f1,f2);
      },
      'catch': function(f1) {
        return this.getPromise().catch(f1);
      },
      'finally': function(f1) {
        return this.getPromise().finally(f1);
      }
    };

    return function(element, options) {
      if (options.from) {
        element.css(options.from);
        options.from = null;
      }

      var closed, runner = new RAFPromise();
      return {
        start: run,
        end: run
      };

      function run() {
        $$rAF(function() {
          close();
          if (!closed) {
            runner.done();
          }
          closed = true;
        });
        return runner;
      }

      function close() {
        if (options.addClass) {
          element.addClass(options.addClass);
          options.addClass = null;
        }
        if (options.removeClass) {
          element.removeClass(options.removeClass);
          options.removeClass = null;
        }
        if (options.to) {
          element.css(options.to);
          options.to = null;
        }
      }
    };
  }];
};
<commit_msg>fix($animateCss): fix parse errors on older Android WebViews<commit_after>'use strict';

/**
 * @ngdoc service
 * @name $animateCss
 * @kind object
 *
 * @description
 * This is the core version of `$animateCss`. By default, only when the `ngAnimate` is included,
 * then the `$animateCss` service will actually perform animations.
 *
 * Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}.
 */
var $CoreAnimateCssProvider = function() {
  this.$get = ['$$rAF', '$q', function($$rAF, $q) {

    var RAFPromise = function() {};
    RAFPromise.prototype = {
      done: function(cancel) {
        this.defer && this.defer[cancel === true ? 'reject' : 'resolve']();
      },
      end: function() {
        this.done();
      },
      cancel: function() {
        this.done(true);
      },
      getPromise: function() {
        if (!this.defer) {
          this.defer = $q.defer();
        }
        return this.defer.promise;
      },
      then: function(f1,f2) {
        return this.getPromise().then(f1,f2);
      },
      'catch': function(f1) {
        return this.getPromise()['catch'](f1);
      },
      'finally': function(f1) {
        return this.getPromise()['finally'](f1);
      }
    };

    return function(element, options) {
      if (options.from) {
        element.css(options.from);
        options.from = null;
      }

      var closed, runner = new RAFPromise();
      return {
        start: run,
        end: run
      };

      function run() {
        $$rAF(function() {
          close();
          if (!closed) {
            runner.done();
          }
          closed = true;
        });
        return runner;
      }

      function close() {
        if (options.addClass) {
          element.addClass(options.addClass);
          options.addClass = null;
        }
        if (options.removeClass) {
          element.removeClass(options.removeClass);
          options.removeClass = null;
        }
        if (options.to) {
          element.css(options.to);
          options.to = null;
        }
      }
    };
  }];
};
<|endoftext|>


<commit_before>import Arboreal from "arboreal";
import co from "co";
import filter from "lodash/collection/filter";
import findIndex from "lodash/array/filter";
import forEach from "lodash/collection/forEach";
import { findSatisfactoryVersion, getVersions } from "./utils";
import mapValues from "lodash/object/mapValues";
import pairs from "lodash/object/pairs";
import sortBy from "lodash/collection/sortBy";

import Package from "./package";

const mkDependencyTree = (registries=[]) =>
  class DependencyTree extends Arboreal {
    constructor (parent, root, id) {
      // Set ID
      id = (parent ? parent.id + '/' : "") +
        id || `node_modules/${ root.name }`;

      super(parent, root, id);

      // Build tree
      this.buildTree();
    }

    buildTree () {
      return co(this._buildTree.bind(this));
    }

    *_buildTree () {
      let deps = yield this._loadDependencies();
      forEach(deps, this.appendChild);
    }

    *_loadDependencies () {
      let
        {dependencies} = this.data,
        {_loadDependency} = this,

        // Make _loadDependency accept arrays
        loader = _loadDependency.apply.bind(_loadDependency, this),
        loaded = yield map(
          pairs(dependencies),
          loader
        );

      return loaded;
    }

    *_loadDependency (name, condition) {
      let
        allMatches = yield getVersions(name, registries),
        versionMap = mapValues(allMatches, Object.keys),

        candidates = filter(
          mapValues(
            allMatches, findSatisfactoryVersion.bind(null, condition)
          )
        ),

        versions = sortBy(
          pairs(candidates),
          ([registry]) => findIndex(registries, registry)
        ),

        [registry, version] = versions.length ? versions : [];

      // Load package
      if (version) {
        let
          config = allMatches[registry][version],
          pkg = yield new Package(config);

        return pkg;
      }

      else
        throw new Error(`No versions available for ${ condition }`);
    }
  };

export default mkDependencyTree;
<commit_msg>Minor changes to DependencyTree<commit_after>import assign from "lodash/object/assign";
import Arboreal from "arboreal";
import co from "co";
import { EventEmitter } from "events";
import filter from "lodash/collection/filter";
import findIndex from "lodash/array/filter";
import forEach from "lodash/collection/forEach";
import { findSatisfactoryVersion, getVersions } from "./utils";
import mapValues from "lodash/object/mapValues";
import pairs from "lodash/object/pairs";
import sortBy from "lodash/collection/sortBy";

import Package from "./package";

const mkDependencyTree = (registries=[]) => {
  class DependencyTree extends Arboreal {
    constructor (parent, root, id) {
      // Set ID
      id = (parent ? parent.id + '/' : "") +
        id || `node_modules/${ root.name }`;

      super(parent, root, id);

      // Build tree
      this.buildTree();
    }

    buildTree () {
      return co(this._buildTree.bind(this))
        .then(this.emit.bind(this, "build"));
    }

    *_buildTree () {
      let deps = yield this._loadDependencies();
      forEach(deps, this.appendChild);

      return this;
    }

    *_loadDependencies () {
      let
        {dependencies} = this.data,
        {_loadDependency} = this,

        // Make _loadDependency accept arrays
        loader = _loadDependency.apply.bind(_loadDependency, this),
        loaded = yield map(
          pairs(dependencies),
          loader
        );

      return loaded;
    }

    *_loadDependency (name, condition) {
      let
        allMatches = yield getVersions(name, registries),
        versionMap = mapValues(allMatches, Object.keys),

        candidates = filter(
          mapValues(
            allMatches, findSatisfactoryVersion.bind(null, condition)
          )
        ),

        versions = sortBy(
          pairs(candidates),
          ([registry]) => findIndex(registries, registry)
        ),

        [registry, version] = versions.length ? versions : [];

      // Load package
      if (version) {
        let
          config = allMatches[registry][version],
          pkg = yield new Package(config);

        return pkg;
      }

      else
        throw new Error(`No versions available for ${ condition }`);
    }
  };

  return assign(DependencyTree.prototype, EventEmitter.prototype);
};

export default mkDependencyTree;
<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var User = mongoose.model('usuarios');
var satelize = require('satelize');
var moment = require('moment');

exports.registro = function(req, res) {

    console.log(req.headers['x-forwarded-for']);
    console.log(req.connection.remoteAddress);
    console.log(req.socket.remoteAddress);
    //190.47.115.14

    var ip = '190.47.115.14';
    var ubicacion = satelize.satelize({ip:ip}, function(err, payload) { return payload.continent.es+','+payload.country.es+','+payload.country_code; });
    console.log(ubicacion);

    var user = new User({
        nombres:    req.body.nombres,
        correo:     req.body.correo,
        fecha:      moment().format(),
        ip:         ip,
        ubicacion:  ubicacion,
        suscripcion:true
    });

    user.save(function(err){
        return res.status(200).jsonp(user);
    });
};
<commit_msg>Se deja funcional funciones de subscripcion<commit_after>var mongoose = require('mongoose');
var User = mongoose.model('usuarios');
var satelize = require('satelize');
var moment = require('moment');
var requestIp = require('request-ip');

exports.registro = function(req, res) {

    try {
        var clientIp = requestIp.getClientIp(req);
        var ubicacion = satelize.satelize({ip:clientIp}, function(err, payload) { return payload.continent.es+','+payload.country.es+','+payload.country_code; });

        var user = new User({
            nombres:    req.body.nombres,
            correo:     req.body.correo,
            fecha:      moment().format(),
            ip:         clientIp,
            ubicacion:  ubicacion,
            suscripcion:true
        });

        user.save(function(err){
            return res.status(200).jsonp(user);
        });
    } catch (e) {
        console.log(e);
        return res.status(500).jsonp({ok:false});
    }

};
<|endoftext|>


<commit_before>var isect = require('./ray-aabb');
var Suite = require('benchmark').Suite;

var suite = new Suite();

var boxa = [
  [-1, -1, -1],
  [ 1,  1,  1]
];
var origina = [-2, 0, 0];
var dira = [1, 0, 0];
var idira = [1, Infinity, Infinity]
var neara = 0;
var fara = 10;

suite.add('raycast along x axis', function() {
  isect(origina, dira, idira, boxa, neara, fara);
})

suite.on('cycle', function(event) {
  console.log(String(event.target));
});

suite.on('complete', function() {
  console.log('Fastest is ' + this.filter('fastest').pluck('name'));
});

suite.run();
<commit_msg>update how benchmark creates rays<commit_after>var isect = require('./ray-aabb');
var Suite = require('benchmark').Suite;

var suite = new Suite();

var boxa = [
  [-1, -1, -1],
  [ 1,  1,  1]
];
var origina = [-2, 0, 0];
var dira = [1, 0, 0];
var idira = [1, Infinity, Infinity]
var neara = 0;
var fara = 10;

var ray = isect.createRay(origina, dira);
suite.add('raycast along x axis', function() {
  isect(ray, boxa);
})

suite.on('cycle', function(event) {
  console.log(String(event.target));
});

suite.on('complete', function() {
  console.log('Fastest is ' + this.filter('fastest').pluck('name'));
});

suite.run();
<|endoftext|>


<commit_before>import immutable from 'immutable'

const prefix = '\n********************\n[ImmutableJS] - feature - FromJS\n********************\n'

const defaultItemsArr = ['JohnDoe', 'Joe Belfiery', 'Some random string', 'ducks are nice', 1, 3, null, 1.23, 3.14]

const simpleFromJS = () => {
    const map = immutable.fromJS({
        name: 'John Doe',
        age: '+9000',
    })

    logOperation('map over elements and log them')
    logResult(map.get('name'), map.get('age'))
}

const createMapFromArrayAndIterateOver = () => {
    const map = immutable.fromJS(defaultItemsArr)

    logOperation('map.get el by key \'0\' (converted arr index of el)')
    logResult(map.get('0'))

    logOperation('map over elements and log them')
    map.forEach(item => logResult(item))
}

const changeMapValueUsingSet = () => {
    const map = immutable.fromJS({
        name: 'Unique data name',
        type: 'somethingElse',
        id: '9001',
        role: 'unbeknownst',
        available: false,
    })

    logOperation('display initial mapped object')
    map.forEach(item => logResult(item))
    logOperation('display modified mapped object')

    const newMap = map.set('name', 'Not so unique name, lol')
    newMap.forEach(item => logResult(item))
}

const displayFullFeatures = () => {
    log(prefix)
    log('[ simpleFromJS() ]\n')
    simpleFromJS()

    logHeaderSpace()
    log('[ createMapFromArrayAndIterateOver() ]\n')
    createMapFromArrayAndIterateOver()

    logHeaderSpace()
    log('[ createMapFromArrayAndIterateOver() ]\n')
    changeMapValueUsingSet()
}

const log = (str) => {
    console.log(str)
}

const logResult = (str) => {
    log('\t\tResult: ' + str)
}

const logOperation = (str) => {
    log('\t--> ' + str)
}

const logHeaderSpace = () => {
    log('\n\n')
}

const feature = {
    displayFullFeatures,
}

module.exports = feature<commit_msg>Add more complex example using reviver when creating immutable data fromJS()<commit_after>import immutable from 'immutable'

const prefix = '\n********************\n[ImmutableJS] - feature - FromJS\n********************\n'

const defaultItemsArr = ['JohnDoe', 'Joe Belfiery', 'Some random string', 'ducks are nice', 1, 3, null, 1.23, 3.14]

const simpleFromJS = () => {
    const map = immutable.fromJS({
        name: 'John Doe',
        age: '+9000',
    })

    logOperation('map over elements and log them')
    logResult(map.get('name'), map.get('age'))
}

const createMapFromArrayAndIterateOver = () => {
    const list = immutable.fromJS(defaultItemsArr)

    logOperation('list.get el by key \'0\' (converted arr index of el)')
    logResult(list.get('0'))

    logOperation('list over elements and log them')
    list.forEach(item => logResult(item))
}

const changeMapValueUsingSet = () => {
    /*
     * Here fromJS and .Map do the same thing,
     * since the object is a one-level-deep object
     */
    const map = immutable.Map({
        name: 'Unique data name',
        type: 'somethingElse',
        id: '9001',
        role: 'unbeknownst',
        available: false,
    })

    logOperation('display initial mapped object')
    map.forEach(item => logResult(item))
    logOperation('display modified mapped object')

    const newMap = map.set('name', 'Not so unique name, lol')
    newMap.forEach(item => logResult(item))
}

const fromJsCreatesANestedMapByDefault = () => {
    /*
     * Here fromJS and .Map don't do the same thing,
     * All of the elements on the first level of the object will
     * become maps but anything further will be plain JS Objects when using .Map
     * If we use .fromJS then immutable sees that the object is multi-level-deep and
     * creates a nested map representing the data of the original object that we
     * pass in
     */
    const nestedMap = immutable.fromJS({
        root1: {
            arr: [1, 2, 3, 4, 5],
        },
        root2: {
            node1: {
                isNode: true,
            },
            node2: {
                arr: [1, 2, 3, 4],
            },
        }
    })
    logOperation('.fromJS creating a nested map of a multi-level object')
    console.log(nestedMap)
}

const useReviverWhenCreatingFromJS = () => {
    /*
     * What is not indexed goes to a map on the current level of the Iterable immutable object
     * When we go to the list, we parse again and if the item is not indexed, we create a map, if not, we create a list
     * In the map we can create lists if value is indexed or again a map if it's not indexed. Not 100% sure, yet!
     */
    const customMapAndListAggregate = immutable.fromJS({a: {b: [10, 20, 30]}, c: {d: 40, e: {f: 'lol'} }}, (key, value) => {
        const isIndexed = immutable.Iterable.isIndexed(value)
        return isIndexed ? value.toList() : value.toOrderedMap()
    })
    logOperation('.fromJS creating a custom aggregate of nestedMaps and lists for a multi-level object using a reviver')
    console.log(customMapAndListAggregate)
}

const displayFullFeatures = () => {
    log(prefix)
    log('[ simpleFromJS() ]\n')
    simpleFromJS()

    logHeaderSpace()
    log('[ createMapFromArrayAndIterateOver() ]\n')
    createMapFromArrayAndIterateOver()

    logHeaderSpace()
    log('[ changeMapValueUsingSet() ]\n')
    changeMapValueUsingSet()

    logHeaderSpace()
    log('[ fromJsCreatesANestedMapByDefault() ]\n')
    fromJsCreatesANestedMapByDefault()

    logHeaderSpace()
    log('[ useReviverWhenCreatingFromJS() ]\n')
    useReviverWhenCreatingFromJS()
}

const log = (str) => {
    console.log(str)
}

const logResult = (str) => {
    log('\t\tResult: ' + str)
}

const logOperation = (str) => {
    log('\t--> ' + str)
}

const logHeaderSpace = () => {
    log('\n\n')
}

const feature = {
    displayFullFeatures,
}

module.exports = feature<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var path = require("path");
var MemoryFileSystem = require("memory-fs");
var mime = require("mime");

// constructor for the middleware
module.exports = function(compiler, options) {
	if(!options) options = {};
	if(typeof options.watchOptions === "undefined") options.watchOptions = {};
	if(typeof options.watchDelay !== "undefined") {
		// TODO remove this in next major version
		console.warn("options.watchDelay is deprecated: Use 'options.watchOptions.aggregateTimeout' instead");
		options.watchOptions.aggregateTimeout = options.watchDelay;
	}
	if(typeof options.watchOptions.aggregateTimeout === "undefined") options.watchOptions.aggregateTimeout = 200;
	if(typeof options.stats === "undefined") options.stats = {};
	if(!options.stats.context) options.stats.context = process.cwd();
	if(options.lazy) {
		if(typeof options.filename === "string") {
			var str = options.filename
				.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")
				.replace(/\\\[[a-z]+\\\]/ig, ".+");
			options.filename = new RegExp("^" + str + "$");
		}
	}

	// store our files in memory
	var files = {};
	var fs = compiler.outputFileSystem = new MemoryFileSystem();

	compiler.plugin("done", function(stats) {
		// We are now on valid state
		state = true;
		// Do the stuff in nextTick, because bundle may be invalidated
		//  if a change happend while compiling
		process.nextTick(function() {
			// check if still in valid state
			if(!state) return;
			// print webpack output
			var displayStats = (!options.quiet && options.stats !== false);
			if(displayStats &&
				!(stats.hasErrors() || stats.hasWarnings()) &&
				options.noInfo)
				displayStats = false;
			if(displayStats) {
				console.log(stats.toString(options.stats));
			}
			if (!options.noInfo && !options.quiet)
				console.info("webpack: bundle is now VALID.");

			// execute callback that are delayed
			var cbs = callbacks;
			callbacks = [];
			cbs.forEach(function continueBecauseBundleAvailible(cb) {
				cb();
			});
		});

		// In lazy mode, we may issue another rebuild
		if(forceRebuild) {
			forceRebuild = false;
			rebuild();
		}
	});

	// on compiling
	function invalidPlugin() {
		if(state && (!options.noInfo && !options.quiet))
			console.info("webpack: bundle is now INVALID.");
		// We are now in invalid state
		state = false;
	}
	function invalidAsyncPlugin(compiler, callback) {
		invalidPlugin();
		callback();
	}
	compiler.plugin("invalid", invalidPlugin);
	compiler.plugin("watch-run", invalidAsyncPlugin);
	compiler.plugin("run", invalidAsyncPlugin);

	// the state, false: bundle invalid, true: bundle valid
	var state = false;

	// in lazy mode, rebuild automatically
	var forceRebuild = false;

	// delayed callback
	var callbacks = [];

	// wait for bundle valid
	function ready(fn, req) {
		if(state) return fn();
		if(!options.noInfo && !options.quiet)
			console.log("webpack: wait until bundle finished: " + req.url);
		callbacks.push(fn);
	}

	// start watching
	if(!options.lazy) {
		var watching = compiler.watch(options.watchOptions, function(err) {
			if(err) throw err;
		});
	} else {
		state = true;
	}

	function rebuild() {
		if(state) {
			state = false;
			compiler.run(function(err) {
				if(err) throw err;
			});
		} else {
			forceRebuild = true;
		}
	}

	function pathJoin(a, b) {
		return a == "/" ? "/" + b : (a||"") + "/" + b
	}

	function getFilenameFromUrl(url) {
		// publicPrefix is the folder our bundle should be in
		var localPrefix = options.publicPath || "/";
		if(url.indexOf(localPrefix) !== 0) {
			if(/^(https?:)?\/\//.test(localPrefix)) {
				localPrefix = "/" + localPrefix.replace(/^(https?:)?\/\/[^\/]+\//, "");
				// fast exit if another directory requested
				if(url.indexOf(localPrefix) !== 0) return false;
			} else return false;
		}
		// get filename from request
		var filename = url.substr(localPrefix.length);
		if(filename.indexOf("?") >= 0) {
			filename = filename.substr(0, filename.indexOf("?"));
		}
		return filename ? pathJoin(compiler.outputPath, filename) : compiler.outputPath;
	}

	function trimUrl(url) {
		if(url.split('/').length > 2) return '/' + url.split('/')[-1];
		else return '/';
	}

	// The middleware function
	function webpackDevMiddleware(req, res, next) {
		var filename = getFilenameFromUrl(req.url);

		if (filename === false) return next();

		// in lazy mode, rebuild on bundle request
		if(options.lazy && (!options.filename || options.filename.test(filename)))
			rebuild();

		// delay the request until we have a vaild bundle
		ready(function() {
			var stat;
			try{
				stat = fs.statSync(filename)
			} catch(e) {
				if(req.url !== '/__webpack_hmr') filename = getFilenameFromUrl(trimUrl(req.url));
			}
			try {
				var stat = fs.statSync(filename);
				if(!stat.isFile()) {
					if (stat.isDirectory()) {
						filename = path.join(filename, "index.html");
						stat = fs.statSync(filename);
						if(!stat.isFile()) throw "next";
					} else {
						throw "next";
					}
				}
			} catch(e) {
				return next();
			}

			// server content
			var content = fs.readFileSync(filename);
			res.setHeader("Access-Control-Allow-Origin", "*"); // To support XHR, etc.
			res.setHeader("Content-Type", mime.lookup(filename));
			res.setHeader("Content-Length", content.length);
			if(options.headers) {
				for(var name in options.headers) {
					res.setHeader(name, options.headers[name]);
				}
			}
			res.end(content);
		}, req);
	}

	webpackDevMiddleware.getFilenameFromUrl = getFilenameFromUrl;

	webpackDevMiddleware.invalidate = function() {
		if(watching) watching.invalidate();
	};
	webpackDevMiddleware.close = function(callback) {
		callback = callback || function(){};
		if(watching) watching.close(callback);
		else callback();
	};

	webpackDevMiddleware.fileSystem = fs;

	return webpackDevMiddleware;
}
<commit_msg>fix url issues<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var path = require("path");
var MemoryFileSystem = require("memory-fs");
var mime = require("mime");

// constructor for the middleware
module.exports = function(compiler, options) {
	if(!options) options = {};
	if(typeof options.watchOptions === "undefined") options.watchOptions = {};
	if(typeof options.watchDelay !== "undefined") {
		// TODO remove this in next major version
		console.warn("options.watchDelay is deprecated: Use 'options.watchOptions.aggregateTimeout' instead");
		options.watchOptions.aggregateTimeout = options.watchDelay;
	}
	if(typeof options.watchOptions.aggregateTimeout === "undefined") options.watchOptions.aggregateTimeout = 200;
	if(typeof options.stats === "undefined") options.stats = {};
	if(!options.stats.context) options.stats.context = process.cwd();
	if(options.lazy) {
		if(typeof options.filename === "string") {
			var str = options.filename
				.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")
				.replace(/\\\[[a-z]+\\\]/ig, ".+");
			options.filename = new RegExp("^" + str + "$");
		}
	}

	// store our files in memory
	var files = {};
	var fs = compiler.outputFileSystem = new MemoryFileSystem();

	compiler.plugin("done", function(stats) {
		// We are now on valid state
		state = true;
		// Do the stuff in nextTick, because bundle may be invalidated
		//  if a change happend while compiling
		process.nextTick(function() {
			// check if still in valid state
			if(!state) return;
			// print webpack output
			var displayStats = (!options.quiet && options.stats !== false);
			if(displayStats &&
				!(stats.hasErrors() || stats.hasWarnings()) &&
				options.noInfo)
				displayStats = false;
			if(displayStats) {
				console.log(stats.toString(options.stats));
			}
			if (!options.noInfo && !options.quiet)
				console.info("webpack: bundle is now VALID.");

			// execute callback that are delayed
			var cbs = callbacks;
			callbacks = [];
			cbs.forEach(function continueBecauseBundleAvailible(cb) {
				cb();
			});
		});

		// In lazy mode, we may issue another rebuild
		if(forceRebuild) {
			forceRebuild = false;
			rebuild();
		}
	});

	// on compiling
	function invalidPlugin() {
		if(state && (!options.noInfo && !options.quiet))
			console.info("webpack: bundle is now INVALID.");
		// We are now in invalid state
		state = false;
	}
	function invalidAsyncPlugin(compiler, callback) {
		invalidPlugin();
		callback();
	}
	compiler.plugin("invalid", invalidPlugin);
	compiler.plugin("watch-run", invalidAsyncPlugin);
	compiler.plugin("run", invalidAsyncPlugin);

	// the state, false: bundle invalid, true: bundle valid
	var state = false;

	// in lazy mode, rebuild automatically
	var forceRebuild = false;

	// delayed callback
	var callbacks = [];

	// wait for bundle valid
	function ready(fn, req) {
		if(state) return fn();
		if(!options.noInfo && !options.quiet)
			console.log("webpack: wait until bundle finished: " + req.url);
		callbacks.push(fn);
	}

	// start watching
	if(!options.lazy) {
		var watching = compiler.watch(options.watchOptions, function(err) {
			if(err) throw err;
		});
	} else {
		state = true;
	}

	function rebuild() {
		if(state) {
			state = false;
			compiler.run(function(err) {
				if(err) throw err;
			});
		} else {
			forceRebuild = true;
		}
	}

	function pathJoin(a, b) {
		return a == "/" ? "/" + b : (a||"") + "/" + b
	}

	function getFilenameFromUrl(url) {
		// publicPrefix is the folder our bundle should be in
		var localPrefix = options.publicPath || "/";
		if(url.indexOf(localPrefix) !== 0) {
			if(/^(https?:)?\/\//.test(localPrefix)) {
				localPrefix = "/" + localPrefix.replace(/^(https?:)?\/\/[^\/]+\//, "");
				// fast exit if another directory requested
				if(url.indexOf(localPrefix) !== 0) return false;
			} else return false;
		}
		// get filename from request
		var filename = url.substr(localPrefix.length);
		if(filename.indexOf("?") >= 0) {
			filename = filename.substr(0, filename.indexOf("?"));
		}
		return filename ? pathJoin(compiler.outputPath, filename) : compiler.outputPath;
	}

	function trimUrl(url) {
		if(url.split('/').length > 2) return '/' + url.split('/')[-1];
		else return '/';
	}

	// The middleware function
	function webpackDevMiddleware(req, res, next) {
		var filename = getFilenameFromUrl(req.url);

		if (filename === false) return next();

		// in lazy mode, rebuild on bundle request
		if(options.lazy && (!options.filename || options.filename.test(filename)))
			rebuild();

		// delay the request until we have a vaild bundle
		ready(function() {
			var stat;
			try{
				stat = fs.statSync(filename)
			} catch(e) {
				if(req.url !== '/__webpack_hmr' && req.url !== '/') filename = getFilenameFromUrl('/');
			}
			try {
				var stat = fs.statSync(filename);
				if(!stat.isFile()) {
					if (stat.isDirectory()) {
						filename = path.join(filename, "index.html");
						stat = fs.statSync(filename);
						if(!stat.isFile()) throw "next";
					} else {
						throw "next";
					}
				}
			} catch(e) {
				return next();
			}

			// server content
			var content = fs.readFileSync(filename);
			res.setHeader("Access-Control-Allow-Origin", "*"); // To support XHR, etc.
			res.setHeader("Content-Type", mime.lookup(filename));
			res.setHeader("Content-Length", content.length);
			if(options.headers) {
				for(var name in options.headers) {
					res.setHeader(name, options.headers[name]);
				}
			}
			res.end(content);
		}, req);
	}

	webpackDevMiddleware.getFilenameFromUrl = getFilenameFromUrl;

	webpackDevMiddleware.invalidate = function() {
		if(watching) watching.invalidate();
	};
	webpackDevMiddleware.close = function(callback) {
		callback = callback || function(){};
		if(watching) watching.close(callback);
		else callback();
	};

	webpackDevMiddleware.fileSystem = fs;

	return webpackDevMiddleware;
}
<|endoftext|>


<commit_before>"use strict";
let express = require("express");
let router = express.Router();
const logError = require("../helpers/log-error.js");
let { db, FEATURED_COLLECTION, FEATURED } = require("../helpers/db");

function shuffle(array) {
  const shuffledArray = array.slice();
  console.log("shuffledArray[0].entryUrl", shuffledArray[0].entryUrl)
  for (let i = shuffledArray.length - 1; i > 0; i--) {
    let j = Math.floor(Math.random() * (i + 1));
    [shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]];
  }
  return shuffledArray;
}

function getHeroFeature() {
  return shuffle([
    {
      imageCredit: "Housing Institute of Buenos Aires",
      imageUrl:
        "https://s3.amazonaws.com/participedia.prod/ee8da85d-d17e-4bfb-a500-0fc2e3dfd72a-In%20the%20Participatory%20Community%20Boards%20the%20plans%20presented%20by%20the%20Housing%20Institute%20are%20shaped.",
      entryTitle:
        'Participatory Slum Upgrading Process in the City of Buenos Aires: The "Villa 20" Case',
      entryUrl: "/case/5988",
    },
    {
      imageCredit: "Research Team, University of the Western Cape: Professor Laurence Piper, Robyn Pasensie and Sondre Bailey",
      imageUrl:
        "https://s3.amazonaws.com/participedia.prod/b5294e0a-e875-4ece-afe1-a242f851a5c3",
      entryTitle:
        "Decommissioning South African Social Services: Participatory Field Research in Delft",
      entryUrl: "/case/5834",
    },
    {
      imageCredit: "Max Bender",
      imageUrl:
        "https://s3.amazonaws.com/participedia.prod/d97cf067-9b0b-4d80-bc38-aee5b8553c8c",
      entryTitle: "George Floyd Protests",
      entryUrl: "/case/6590",
    },
  ])[0];
}

async function getThingStatistic() {
  const stats = {
    cases: 0,
    methods: 0,
    organizations: 0
  };
  const results = await db.any("SELECT type, COUNT(*) as total FROM things WHERE type <> 'collection' GROUP BY type");
  results.map(result => {
    let type = `${result.type}s`;
    if (stats.hasOwnProperty(type)) {
      stats[type] = parseInt(result.total);
    }
  });
  return stats;
}

async function getTotalCountries() {
  const results = await db.any("SELECT country FROM things WHERE type IN ('case', 'organization') and country <> '' GROUP BY country");
  let total = 0;
  if (results && results.length) {
    total = parseInt(results.length);
  }
  return total;
}

async function getTotalContributors() {
  const results = await db.any("SELECT user_id FROM authors GROUP BY user_id");
  let total = 0;
  if (results && results.length) {
    total = parseInt(results.length);
  }
  return total;
}

router.get("/", async function(req, res) {
  let returnType = req.query.returns;
  const language = req.cookies.locale || "en";
  const thingStatsResult = await getThingStatistic();
  const totalCounties = await getTotalCountries();
  const totalContributors = await getTotalContributors();
  const heroFeature = getHeroFeature();

  // Collect Statistics
  const stats = {
    cases: thingStatsResult.cases, // (total entries)
    methods: thingStatsResult.methods, // (total entries)
    organizations: thingStatsResult.organizations, // (total entries)
    countries: totalCounties, // (number of unique countries represented between cases and orgs)
    contributors: totalContributors, // (number of unique users who have created or edited an entry)
  };

  // Collect Featured Collections
  const featuredCollections = await db.any(FEATURED_COLLECTION, {
    language: language
  });

  // Collect Featured Things
  const featuredCasesMethodsOrgs = await db.any(FEATURED, {
    language: language,
    limit: 7,
    sortby: "post_date",
    type: "things",
    userId: req.user ? req.user.id : null,
    facets: "",
    offset: 1
  });

  // Populate response data
  const data = {
    featuredCasesMethodsOrgs: featuredCasesMethodsOrgs,
    featuredCollections: featuredCollections,
    stats: stats,
    heroFeature: heroFeature
  };

  switch (returnType) {
    case "json":
      return res.status(200).json({
        user: req.user || null,
        ...data
      });
    case "html": // fall through
    default:
      return res.status(200).render("home", {
        user: req.user || null,
        ...data,
      });
  }
});

module.exports = router;
<commit_msg>the FEATURED sql query includes results for collections, so removing the FEATURED_COLLECTION query and filtering the results from FEATURED<commit_after>"use strict";
let express = require("express");
let router = express.Router();
const logError = require("../helpers/log-error.js");
let { db, FEATURED_COLLECTION, FEATURED } = require("../helpers/db");

function shuffle(array) {
  const shuffledArray = array.slice();
  console.log("shuffledArray[0].entryUrl", shuffledArray[0].entryUrl)
  for (let i = shuffledArray.length - 1; i > 0; i--) {
    let j = Math.floor(Math.random() * (i + 1));
    [shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]];
  }
  return shuffledArray;
}

function getHeroFeature() {
  return shuffle([
    {
      imageCredit: "Housing Institute of Buenos Aires",
      imageUrl:
        "https://s3.amazonaws.com/participedia.prod/ee8da85d-d17e-4bfb-a500-0fc2e3dfd72a-In%20the%20Participatory%20Community%20Boards%20the%20plans%20presented%20by%20the%20Housing%20Institute%20are%20shaped.",
      entryTitle:
        'Participatory Slum Upgrading Process in the City of Buenos Aires: The "Villa 20" Case',
      entryUrl: "/case/5988",
    },
    {
      imageCredit: "Research Team, University of the Western Cape: Professor Laurence Piper, Robyn Pasensie and Sondre Bailey",
      imageUrl:
        "https://s3.amazonaws.com/participedia.prod/b5294e0a-e875-4ece-afe1-a242f851a5c3",
      entryTitle:
        "Decommissioning South African Social Services: Participatory Field Research in Delft",
      entryUrl: "/case/5834",
    },
    {
      imageCredit: "Max Bender",
      imageUrl:
        "https://s3.amazonaws.com/participedia.prod/d97cf067-9b0b-4d80-bc38-aee5b8553c8c",
      entryTitle: "George Floyd Protests",
      entryUrl: "/case/6590",
    },
  ])[0];
}

async function getThingStatistic() {
  const stats = {
    cases: 0,
    methods: 0,
    organizations: 0
  };
  const results = await db.any("SELECT type, COUNT(*) as total FROM things WHERE type <> 'collection' GROUP BY type");
  results.map(result => {
    let type = `${result.type}s`;
    if (stats.hasOwnProperty(type)) {
      stats[type] = parseInt(result.total);
    }
  });
  return stats;
}

async function getTotalCountries() {
  const results = await db.any("SELECT country FROM things WHERE type IN ('case', 'organization') and country <> '' GROUP BY country");
  let total = 0;
  if (results && results.length) {
    total = parseInt(results.length);
  }
  return total;
}

async function getTotalContributors() {
  const results = await db.any("SELECT user_id FROM authors GROUP BY user_id");
  let total = 0;
  if (results && results.length) {
    total = parseInt(results.length);
  }
  return total;
}

function addTextureImageIfNeeded(entries) {
  // add a texture placeholder if there are no images for an entry
  return entries.map(entry => {
    const newEntry = Object.assign(entry, {});
    if (newEntry.photos && newEntry.photos.length < 1) {
      newEntry.photos = [{ url: "/images/texture_3.svg" }];
    }
    return newEntry;
  });
}

router.get("/", async function(req, res) {
  let returnType = req.query.returns;
  const language = req.cookies.locale || "en";
  const thingStatsResult = await getThingStatistic();
  const totalCounties = await getTotalCountries();
  const totalContributors = await getTotalContributors();
  const heroFeature = getHeroFeature();

  // Collect Statistics
  const stats = {
    cases: thingStatsResult.cases, // (total entries)
    methods: thingStatsResult.methods, // (total entries)
    organizations: thingStatsResult.organizations, // (total entries)
    countries: totalCounties, // (number of unique countries represented between cases and orgs)
    contributors: totalContributors, // (number of unique users who have created or edited an entry)
  };

  // Collect Featured Things
  let featuredEntries = await db.any(FEATURED, {
    language: language,
    limit: 7,
    sortby: "post_date",
    type: "things",
    userId: req.user ? req.user.id : null,
    facets: "",
    offset: 1
  });
  featuredEntries = addTextureImageIfNeeded(featuredEntries);
  const featuredCollections = featuredEntries.filter(entry => entry.type === "collection");
  const featuredCasesMethodsOrgs = featuredEntries.filter(entry => entry.type !== "collection");

  // Populate response data
  const data = {
    featuredCasesMethodsOrgs: featuredCasesMethodsOrgs,
    featuredCollections: featuredCollections,
    stats: stats,
    heroFeature: heroFeature
  };

  switch (returnType) {
    case "json":
      return res.status(200).json({
        user: req.user || null,
        ...data
      });
    case "html": // fall through
    default:
      return res.status(200).render("home", {
        user: req.user || null,
        ...data,
      });
  }
});

module.exports = router;
<|endoftext|>


<commit_before>;
'use strict';
(function(){
	var W = window, DOC = document, proto, addSwf, alterSwf;
	var trim = /^\s*|\s*$/g;

	addSwf = (function( $detector ){
		if( $detector.browser == "ie" && $detector.browserVersion < 9 )
			return function(){
				var data = this.data, param = data.param, r, k;
				r = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width=' + data.width + ' height=' + data.height + ' style="position:absolute; margin:0px; padding:0px"><param name="movie" value=' + data.url + ' >';
				for( k in param ){ r += '<param name=' + k + ' value=' + param[ k ] + ' />'; }
				r += '</object>',
					this.conEl.innerHTML = r, this.flash = this.conEl.firstChild;
			}
		else
			return function(){
				var data = this.data, param = data.param, r, k;
				r = '<object type="application/x-shockwave-flash" data=' + data.url + ' width=' + data.width + ' height=' + data.height + ' style="position:absolute; margin:0px; padding:0px">';
				for( k in param ){ r += '<param name=' + k + ' value=' + param[ k ] + ' />'; }
				r += '</object>',
					this.conEl.innerHTML = r, this.flash = this.conEl.firstChild;
			}
	})( dk.DETECTOR ),
		alterSwf = function(){
			this.conEl.innerHTML = '';
		},
// FLASH :
		dk.cls( 'Flash', (function( $doc, $detector ){
			var factory, uuList = {}, Flash, Data, proto = {}, destroyFlash;

			destroyFlash = function( $k ){
				// todo Ʈ
				delete uuList[ $k ];
			},

				Flash = function(){
					var el = $doc.createElement( "div" ), s = el.style, conEl = $doc.createElement( "div" ), conS = conEl.style;
					this.el = el, this.style = s, el.appendChild( conEl ), this.conEl = conEl, this.conStyle = conS, this.data = new Data();
				},
				Data = function(){
					this.url = "", this.width = 0, this.height = 0, this.version = 10.1, this.param = { wmode : 'opaque', allowScriptAccess : 'always' };
				},

				Flash.prototype.S = (function(){
					var prefixCss = $detector.prefixCss, nopx = { opacity : 1, zIndex : 1, 'z-index' : 1 };
					return function(){
						var i = 0, j = arguments.length, k, v, e = this.el, s = this.style, r, t0;
						while( i < j ){
							k = arguments[ i++ ];
							if( i == j ) return proto[ k ] ? proto[ k ].call( this ) :
									k.indexOf( '@' ) > -1 ? e.getAttribute( k.replace( '@', '' ) ) :
								( r = s[ k ], t0 = parseFloat( r ), r = isNaN( t0 ) ? r : t0 );
							else  v = arguments[ i++ ],
								proto[ k ] ? proto[ k ].call( this, v ) :
										k.indexOf( '@' ) > -1 ? e.setAttribute( k.replace( '@', '' ), v ) :
									s[ k ] = s[ prefixCss + k ] = typeof v == 'number' ? nopx[ k ] ? v : v + 'px' : v
						}
						return this;
					}
				})(),
				Flash.prototype.load = (function(){
					return function(){
						var i = 0, j = arguments.length, k, v, data = this.data;
						while( i < j ){
							k = arguments[ i++ ], v = arguments[ i++ ], k in data ? data[ k ] = v : data.param[ k ] = v;
						}
						$detector.flash >= data.version ? ( addSwf.call( this ), proto.width.call( this, data.width ), proto.height.call( this, data.height ) ) : alterSwf.call( this );
						return this;
					}
				})(),

				factory = function( $k, $v ){
					if( $v === null ) return destroyFlash( $k ); //
					return uuList[ $k ] ? uuList[ $k ] : uuList[ $k ] = new Flash();
				},
				factory.fn = function(){
					var i = 0, j = arguments.length, k, v;
					while( i < j ){
						k = arguments[ i++ ];
						if( i == j ) return proto[ k ];
						else v = arguments[ i++ ], v === null ? delete proto[ k ] : proto[ k ] = v;
					}
				};

			return factory;
		})( DOC, dk.DETECTOR ) ),

		proto = (function( $detector ){
			return {
				width : function( $v ){
					this.data.width = this.style.width = this.conStyle.width = this.flash.width = typeof $v == "number" ? $v + "px" : $v;
				},
				height : function( $v ){
					this.data.height = this.style.height = this.conStyle.height = this.flash.height = typeof $v == "number" ? $v + "px" : $v;
				},
				show : function(){
					this.conStyle.visibility = "visible";
				},
				hide : function(){
					this.conStyle.visibility = "hidden";
				},
				refresh : function(){
					addSwf.call( this );
				},
				add : function(){
					this.el.appendChild( this.conEl ), addSwf.call( this );
				},
				del : function(){
					this.el.removeChild( this.conEl );
				},
				toFlash : function( $v ){
					var f, t0;
					$v = $v.replace( /(\s*)/g, "" ),
						f = ( t0 = $v.split( '(' ) )[ 0 ],
							t0[ 1 ].charAt( 0 ) == ')' ? this.flash.toFlash( f ) : this.flash.toFlash( f, t0[ 1 ].substring( 0, t0[ 1 ].length - 1 ) );
				}
			}
		})( dk.DETECTOR ),
		dk.PROTO.connect( dk.Flash.fn, dk.PROTO.css, dk.PROTO.tree, proto )

})()<commit_msg>plugin flash<commit_after>;
'use strict';
(function(){
	var W = window, DOC = document, proto, addSwf, alterSwf;
	var trim = /^\s*|\s*$/g;

	addSwf = (function( $detector ){
		if( $detector.browser == "ie" && $detector.browserVersion < 9 )
			return function(){
				var data = this.data, param = data.param, r, k;
				r = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width=' + data.width + ' height=' + data.height + ' style="position:absolute; margin:0px; padding:0px"><param name="movie" value=' + data.url + '>';
				for( k in param ){ r += '<param name=' + k + ' value=' + param[ k ] + ' />'; }
				r += '</object>',
					this.conEl.innerHTML = r, this.flash = this.conEl.firstChild;
				alert( r )
			}
		else
			return function(){
				var data = this.data, param = data.param, r, k;
				r = '<object type="application/x-shockwave-flash" data=' + data.url + ' width=' + data.width + ' height=' + data.height + ' style="position:absolute; margin:0px; padding:0px">';
				for( k in param ){ r += '<param name=' + k + ' value=' + param[ k ] + ' />'; }
				r += '</object>',
					this.conEl.innerHTML = r, this.flash = this.conEl.firstChild;
			}
	})( dk.DETECTOR ),
		alterSwf = function(){
			this.conEl.innerHTML = '';
		},
// FLASH :
		dk.cls( 'Flash', (function( $doc, $detector ){
			var factory, uuList = {}, Flash, Data, proto = {}, destroyFlash;

			destroyFlash = function( $k ){
				// todo Ʈ
				delete uuList[ $k ];
			},

				Flash = function(){
					var el = $doc.createElement( "div" ), s = el.style, conEl = $doc.createElement( "div" ), conS = conEl.style;
					this.el = el, this.style = s, el.appendChild( conEl ), this.conEl = conEl, this.conStyle = conS, this.data = new Data();
				},
				Data = function(){
					this.url = "", this.width = 0, this.height = 0, this.version = 10.1, this.param = { wmode : 'opaque', allowScriptAccess : 'always' };
				},

				Flash.prototype.S = (function(){
					var prefixCss = $detector.prefixCss, nopx = { opacity : 1, zIndex : 1, 'z-index' : 1 };
					return function(){
						var i = 0, j = arguments.length, k, v, e = this.el, s = this.style, r, t0;
						while( i < j ){
							k = arguments[ i++ ];
							if( i == j ) return proto[ k ] ? proto[ k ].call( this ) :
									k.indexOf( '@' ) > -1 ? e.getAttribute( k.replace( '@', '' ) ) :
								( r = s[ k ], t0 = parseFloat( r ), r = isNaN( t0 ) ? r : t0 );
							else  v = arguments[ i++ ],
								proto[ k ] ? proto[ k ].call( this, v ) :
										k.indexOf( '@' ) > -1 ? e.setAttribute( k.replace( '@', '' ), v ) :
									s[ k ] = s[ prefixCss + k ] = typeof v == 'number' ? nopx[ k ] ? v : v + 'px' : v
						}
						return this;
					}
				})(),
				Flash.prototype.load = (function(){
					return function(){
						var i = 0, j = arguments.length, k, v, data = this.data;
						while( i < j ){
							k = arguments[ i++ ], v = arguments[ i++ ], k in data ? data[ k ] = v : data.param[ k ] = v;
						}
						$detector.flash >= data.version ? ( addSwf.call( this ), proto.width.call( this, data.width ), proto.height.call( this, data.height ) ) : alterSwf.call( this );
						return this;
					}
				})(),

				factory = function( $k, $v ){
					if( $v === null ) return destroyFlash( $k ); //
					return uuList[ $k ] ? uuList[ $k ] : uuList[ $k ] = new Flash();
				},
				factory.fn = function(){
					var i = 0, j = arguments.length, k, v;
					while( i < j ){
						k = arguments[ i++ ];
						if( i == j ) return proto[ k ];
						else v = arguments[ i++ ], v === null ? delete proto[ k ] : proto[ k ] = v;
					}
				};

			return factory;
		})( DOC, dk.DETECTOR ) ),

		proto = (function( $detector ){
			return {
				width : function( $v ){
					this.data.width = this.style.width = this.conStyle.width = this.flash.width = typeof $v == "number" ? $v + "px" : $v;
				},
				height : function( $v ){
					this.data.height = this.style.height = this.conStyle.height = this.flash.height = typeof $v == "number" ? $v + "px" : $v;
				},
				show : function(){
					this.conStyle.visibility = "visible";
				},
				hide : function(){
					this.conStyle.visibility = "hidden";
				},
				refresh : function(){
					addSwf.call( this );
				},
				add : function(){
					this.el.appendChild( this.conEl ), addSwf.call( this );
				},
				del : function(){
					this.el.removeChild( this.conEl );
				},
				toFlash : function( $v ){
					var f, t0;
					$v = $v.replace( /(\s*)/g, "" ),
						f = ( t0 = $v.split( '(' ) )[ 0 ],
							t0[ 1 ].charAt( 0 ) == ')' ? this.flash.toFlash( f ) : this.flash.toFlash( f, t0[ 1 ].substring( 0, t0[ 1 ].length - 1 ) );
				}
			}
		})( dk.DETECTOR ),
		dk.PROTO.connect( dk.Flash.fn, dk.PROTO.css, dk.PROTO.tree, proto )

})()<|endoftext|>


<commit_before>'use strict';

// What is Controller?
// ---

// Controller helps facilitate routing via express
// by providing configuring route handlers
//
// For example, a route to `/users/:id`
// would be handled by a `UsersController` with function `findOne`
//
// It provides a way for each controller
// to setup the routes and handlers it wants to respond to
//
// Also provides a mechanism to define pre, before, and after middleware
// per controller or per route
//
// Finally, it also provides response and error handling middleware
//
// Also parses query strings for filter, limit, and sort

// Dependencies
// ---
var _ = require('lodash');
var Backbone = require('backbone');
var Model = require('./model');
var Collection = require('./collection');
var xml2js = require('xml2js');

module.exports = Backbone.Model.extend({
  debug: false,

  path: '/',

  sortParam: 'created',
  sortOrder: 'desc',
  skip: 0,
  limit: 100,

  xmlBuilder: new xml2js.Builder(),

  // Route specific middleware definitions
  // Object or Function
  middleware: function() {
    return {};
  },

  // Database query parameters/filters
  // Object or Function
  queryParams: function() {
    return {};
  },

  // Computes the base path for the controller
  // Object or Function
  basePath: function() {
    return this.path;
  },

  // Called after the constructor
  initialize: function() {
    // Routes
    this.routes = {
      get: {},
      post: {},
      put: {},
      patch: {},
      delete: {}
    };

    // Middleware(s)
    this.pre = []; // run before route middleware
    this.before = []; // run after route middleware but before route handler
    this.after = []; // run after route handler

    // Setup middleware and route handlers
    this.setupPreMiddleware();
    this.setupBeforeMiddleware();
    this.setupRoutes();
    this.setupAfterMiddleware();

    // Response/error handler middleware
    this.after.push(this.successResponse);
    this.after.push(this.errorResponse);
    this.after.push(this.finalResponse);
  },

  // Setup routes that this controller should handle
  //
  // Example:
  // this.routes.get['/test'] = {
  //   action: this.testGet,
  //   middleware: []
  // };
  setupRoutes: function() {},

  // Setup middleware that should run before the route middleware
  // Example: `this.pre.push(this.fakePreMiddleware)`
  setupPreMiddleware: function() {},

  // Setup middleware that should run before the route handler
  // Example: `this.before.push(this.fakeBeforeMiddleware)`
  setupBeforeMiddleware: function() {},

  // Setup middleware that should run after the route handler
  // Example: `this.after.push(this.fakeAfterMiddleware)`
  setupAfterMiddleware: function() {},

  // Middleware
  // ---

  // Render a model or a collection in the response
  // Used as a promise resolver in a `.then` promise handler
  // Always bind inner function to `this` original context
  render: function(req, res, next) {
    return function(modelOrCollection) {
      this.prepareResponse(modelOrCollection, req, res, next);
    }.bind(this);
  },

  // Deprecated (see `render`)
  nextThen: function(req, res, next) {
    return this.render(req, res, next);
  },

  // This method can be overridden to customize the response
  prepareResponse: function(modelOrCollection, req, res, next) {
    if (!modelOrCollection) {
      return next();
    }

    if (modelOrCollection instanceof Model) {
      // Data is a Model
      res.data = this.renderModel(modelOrCollection);
    } else if (modelOrCollection instanceof Collection) {
      // Data is a Collection
      res.data = this.renderCollection(modelOrCollection);
    } else {
      // Data is raw
      res.data = modelOrCollection;
    }

    return next();
  },

  // Default middleware for handling successful responses
  successResponse: function(req, res, next) {
    var data = res.data || null;
    var code = 200;
    if (_.isNumber(res.code)) {
      code = res.code;
    }
    var envelope = {
      meta: {
        code: code
      },
      data: data
    };

    // Optional paging meta
    if (res.paging) {
      envelope.meta.paging = res.paging;
    }

    // Set code and data
    res.code = code;
    if (res.code !== 204) {
      res.data = envelope;
    }

    return next();
  },

  // Default middleware for handling error responses
  errorResponse: function(err, req, res, next) {
    var data = err.message || 'Internal Server Error';
    var code = 500;
    if (_.isNumber(err.code)) {
      code = err.code;
    } else if (_.isNumber(res.code)) {
      code = res.code;
    }
    var error = {
      message: data,
      code: code
    };
    if (_.isString(err.type)) {
      error.type = err.type;
    }
    var envelope = {
      meta: {
        code: code,
        error: error
      },
      data: data
    };

    // TODO
    // We should log these errors somewhere remotely
    if (this.debug) {
      if (code >= 500) {
        if (err && err.stack) {
          console.error('Error: %s', JSON.stringify(err.stack));
        }
      } else {
        console.error('Error (%d): %s'.error, code, err.message);
      }
    }

    // Set code and data
    res.code = code;
    res.data = envelope;

    return next();
  },

  // Final middleware for handling all responses
  // Server actually responds to the request here
  finalResponse: function(req, res, next) {
    // If we timed out before managing to respond, don't send the response
    if (res.headersSent) {
      return;
    }

    // Look for `.json` or `.xml` extension in path
    // And override request accept header
    if (/.json$/.test(req.path)) {
      req.headers.accept = 'application/json';
    } else if (/.xml$/.test(req.path)) {
      req.headers.accept = 'application/xml';
    }

    // Use request accept header to determine response content-type
    res.format({
      json: function() {
        res.status(res.code).jsonp(res.data);
      },
      xml: function() {
        res.set('Content-Type', 'application/xml; charset=utf-8');

        var xml;
        try {
          var xmlData = JSON.parse(JSON.stringify(res.data));
          xml = this.xmlBuilder.buildObject(xmlData);
          res.status(res.code).send(xml);
        } catch (e) {
          console.error('XML building error: %s', e.stack);
          res.status(res.code);
        }
      }.bind(this)
    });
  },

  // Render
  // ---

  renderModel: function(model) {
    return model.render();
  },

  renderCollection: function(collection) {
    return collection.map(function(model) {
      return model.render();
    });
  },

  // Helpers
  // ---

  // Gets any route middleware that may have been defined
  getRouteMiddleware: function(action) {
    // Find route middleware definitions
    var middleware = _.result(this, 'middleware');
    if (_.has(middleware, action)) {
      return middleware[action];
    } else {
      return [];
    }
  },

  // For `created` and `updated` date range query string
  buildTimestampQuery: function(query) {
    var result = {};
    if (!_.isObject(query) || _.isEmpty(query)) {
      return result;
    }

    // timestamp might be in `ms` or `s`
    _.each(query, function(timestamp, operator) {
      if (!_.contains(['gt', 'gte', 'lt', 'lte', 'ne'], operator)) {
        return;
      }

      // Timestamp must be an integer
      timestamp = _.parseInt(timestamp);
      if (_.isNaN(timestamp)) {
        return;
      }

      // Convert seconds to milliseconds
      timestamp = _.isUnixTime(timestamp) ? timestamp * 1000 : timestamp;

      result['$' + operator] = timestamp;
    });

    return result;
  },

  // Parses req.query (querystring) for since/until, sort/order, skip/limit
  // Also builds a query using allowed queryParams if applicable
  parseQueryString: function(req) {
    var query = {};
    var queries = [];
    var options = {};

    // Reserved Params
    var created = req.query.created || {}; // accepts both s and ms
    var updated = req.query.updated || {}; // accepts both s and ms
    var sortBy = req.query.sort || this.sortParam; // validate sortableParams
    var orderBy = req.query.order || this.sortOrder; // validate [asc, desc] or [1, -1]
    var skip = req.query.skip || req.query.offset || this.skip;
    var limit = req.query.limit || req.query.count || this.limit;
    skip = _.parseInt(skip) || 0;
    limit = _.parseInt(limit) || 0;
    limit = Math.min(limit, this.limit); // Hard limit at 100

    // Date Range params
    var createdQuery = this.buildTimestampQuery(created);
    var updatedQuery = this.buildTimestampQuery(updated);

    if (!_.isEmpty(createdQuery)) {
      queries.push({
        created: createdQuery
      });
    }
    if (!_.isEmpty(updatedQuery)) {
      queries.push({
        updated: updatedQuery
      });
    }

    // Filter params
    var queryParams = _.extend(_.result(this, 'queryParams'), {
      'user_id': 'string'
    });
    var filterParams = _.pick(req.query, _.keys(queryParams));
    var logicalOperator = '$' + (req.query.logical || 'and').toLowerCase().replace(/[@\s]/g, '');

    _.each(filterParams, function(val, key) {
      // If value is all, ignore this param
      if (val === 'all') {
        return;
      }

      // Support `,` as `$or` for each param
      var vals = val.split(',');

      // No value, ignore this param
      if (vals.length === 0) {
        return;
      }

      // The built query filter
      var filter = {};

      // Get param type
      var type = queryParams[key];

      // Deal with different param types
      if (type === 'string') {
        // strings and objectid
        // no transformation
      } else if (type === 'regex') {
        // regex case insensitive and escaping special characters
        vals = _.map(vals, function(v) {
          return {
            '$regex': _.escapeRegExp(v),
            '$options': 'i'
          };
        });
      } else if (type === 'integer') {
        // integers
        vals = _.map(vals, function(v) {
          return _.parseInt(v);
        });
      } else if (type === 'float') {
        // floats
        vals = _.map(vals, function(v) {
          return parseFloat(v);
        });
      } else {
        // invalid or unknown type
        return;
      }

      // If there is only one val, no need to use `$or`
      if (vals.length === 1) {
        filter[key] = vals[0];
      } else {
        var orExpr = [];
        _.each(vals, function(orVal) {
          var orClause = {};
          orClause[key] = orVal;
          orExpr.push(orClause);
        });
        filter['$or'] = orExpr;
      }

      queries.push(filter);
    });

    // Combine the query
    if (queries.length > 0) {
      query[logicalOperator] = queries;
    }

    // Options
    // Sort/Order/Limit/Skip
    var sortOptions = [
      [sortBy, orderBy]
    ];

    return {
      'query': query,
      'sort': sortOptions,
      'limit': limit,
      'skip': skip
    };
  }
});
<commit_msg>A regular expression is a “prefix expression” if it starts with a caret (^) or a left anchor (\A), followed by a string of simple symbols. For example, the regex /^abc.*/ will be optimized by matching only against the values from the index that start with abc.<commit_after>'use strict';

// What is Controller?
// ---

// Controller helps facilitate routing via express
// by providing configuring route handlers
//
// For example, a route to `/users/:id`
// would be handled by a `UsersController` with function `findOne`
//
// It provides a way for each controller
// to setup the routes and handlers it wants to respond to
//
// Also provides a mechanism to define pre, before, and after middleware
// per controller or per route
//
// Finally, it also provides response and error handling middleware
//
// Also parses query strings for filter, limit, and sort

// Dependencies
// ---
var _ = require('lodash');
var Backbone = require('backbone');
var Model = require('./model');
var Collection = require('./collection');
var xml2js = require('xml2js');

module.exports = Backbone.Model.extend({
  debug: false,

  path: '/',

  sortParam: 'created',
  sortOrder: 'desc',
  skip: 0,
  limit: 100,

  xmlBuilder: new xml2js.Builder(),

  // Route specific middleware definitions
  // Object or Function
  middleware: function() {
    return {};
  },

  // Database query parameters/filters
  // Object or Function
  queryParams: function() {
    return {};
  },

  // Computes the base path for the controller
  // Object or Function
  basePath: function() {
    return this.path;
  },

  // Called after the constructor
  initialize: function() {
    // Routes
    this.routes = {
      get: {},
      post: {},
      put: {},
      patch: {},
      delete: {}
    };

    // Middleware(s)
    this.pre = []; // run before route middleware
    this.before = []; // run after route middleware but before route handler
    this.after = []; // run after route handler

    // Setup middleware and route handlers
    this.setupPreMiddleware();
    this.setupBeforeMiddleware();
    this.setupRoutes();
    this.setupAfterMiddleware();

    // Response/error handler middleware
    this.after.push(this.successResponse);
    this.after.push(this.errorResponse);
    this.after.push(this.finalResponse);
  },

  // Setup routes that this controller should handle
  //
  // Example:
  // this.routes.get['/test'] = {
  //   action: this.testGet,
  //   middleware: []
  // };
  setupRoutes: function() {},

  // Setup middleware that should run before the route middleware
  // Example: `this.pre.push(this.fakePreMiddleware)`
  setupPreMiddleware: function() {},

  // Setup middleware that should run before the route handler
  // Example: `this.before.push(this.fakeBeforeMiddleware)`
  setupBeforeMiddleware: function() {},

  // Setup middleware that should run after the route handler
  // Example: `this.after.push(this.fakeAfterMiddleware)`
  setupAfterMiddleware: function() {},

  // Middleware
  // ---

  // Render a model or a collection in the response
  // Used as a promise resolver in a `.then` promise handler
  // Always bind inner function to `this` original context
  render: function(req, res, next) {
    return function(modelOrCollection) {
      this.prepareResponse(modelOrCollection, req, res, next);
    }.bind(this);
  },

  // Deprecated (see `render`)
  nextThen: function(req, res, next) {
    return this.render(req, res, next);
  },

  // This method can be overridden to customize the response
  prepareResponse: function(modelOrCollection, req, res, next) {
    if (!modelOrCollection) {
      return next();
    }

    if (modelOrCollection instanceof Model) {
      // Data is a Model
      res.data = this.renderModel(modelOrCollection);
    } else if (modelOrCollection instanceof Collection) {
      // Data is a Collection
      res.data = this.renderCollection(modelOrCollection);
    } else {
      // Data is raw
      res.data = modelOrCollection;
    }

    return next();
  },

  // Default middleware for handling successful responses
  successResponse: function(req, res, next) {
    var data = res.data || null;
    var code = 200;
    if (_.isNumber(res.code)) {
      code = res.code;
    }
    var envelope = {
      meta: {
        code: code
      },
      data: data
    };

    // Optional paging meta
    if (res.paging) {
      envelope.meta.paging = res.paging;
    }

    // Set code and data
    res.code = code;
    if (res.code !== 204) {
      res.data = envelope;
    }

    return next();
  },

  // Default middleware for handling error responses
  errorResponse: function(err, req, res, next) {
    var data = err.message || 'Internal Server Error';
    var code = 500;
    if (_.isNumber(err.code)) {
      code = err.code;
    } else if (_.isNumber(res.code)) {
      code = res.code;
    }
    var error = {
      message: data,
      code: code
    };
    if (_.isString(err.type)) {
      error.type = err.type;
    }
    var envelope = {
      meta: {
        code: code,
        error: error
      },
      data: data
    };

    // TODO
    // We should log these errors somewhere remotely
    if (this.debug) {
      if (code >= 500) {
        if (err && err.stack) {
          console.error('Error: %s', JSON.stringify(err.stack));
        }
      } else {
        console.error('Error (%d): %s'.error, code, err.message);
      }
    }

    // Set code and data
    res.code = code;
    res.data = envelope;

    return next();
  },

  // Final middleware for handling all responses
  // Server actually responds to the request here
  finalResponse: function(req, res, next) {
    // If we timed out before managing to respond, don't send the response
    if (res.headersSent) {
      return;
    }

    // Look for `.json` or `.xml` extension in path
    // And override request accept header
    if (/.json$/.test(req.path)) {
      req.headers.accept = 'application/json';
    } else if (/.xml$/.test(req.path)) {
      req.headers.accept = 'application/xml';
    }

    // Use request accept header to determine response content-type
    res.format({
      json: function() {
        res.status(res.code).jsonp(res.data);
      },
      xml: function() {
        res.set('Content-Type', 'application/xml; charset=utf-8');

        var xml;
        try {
          var xmlData = JSON.parse(JSON.stringify(res.data));
          xml = this.xmlBuilder.buildObject(xmlData);
          res.status(res.code).send(xml);
        } catch (e) {
          console.error('XML building error: %s', e.stack);
          res.status(res.code);
        }
      }.bind(this)
    });
  },

  // Render
  // ---

  renderModel: function(model) {
    return model.render();
  },

  renderCollection: function(collection) {
    return collection.map(function(model) {
      return model.render();
    });
  },

  // Helpers
  // ---

  // Gets any route middleware that may have been defined
  getRouteMiddleware: function(action) {
    // Find route middleware definitions
    var middleware = _.result(this, 'middleware');
    if (_.has(middleware, action)) {
      return middleware[action];
    } else {
      return [];
    }
  },

  // For `created` and `updated` date range query string
  buildTimestampQuery: function(query) {
    var result = {};
    if (!_.isObject(query) || _.isEmpty(query)) {
      return result;
    }

    // timestamp might be in `ms` or `s`
    _.each(query, function(timestamp, operator) {
      if (!_.contains(['gt', 'gte', 'lt', 'lte', 'ne'], operator)) {
        return;
      }

      // Timestamp must be an integer
      timestamp = _.parseInt(timestamp);
      if (_.isNaN(timestamp)) {
        return;
      }

      // Convert seconds to milliseconds
      timestamp = _.isUnixTime(timestamp) ? timestamp * 1000 : timestamp;

      result['$' + operator] = timestamp;
    });

    return result;
  },

  // Parses req.query (querystring) for since/until, sort/order, skip/limit
  // Also builds a query using allowed queryParams if applicable
  parseQueryString: function(req) {
    var query = {};
    var queries = [];
    var options = {};

    // Reserved Params
    var created = req.query.created || {}; // accepts both s and ms
    var updated = req.query.updated || {}; // accepts both s and ms
    var sortBy = req.query.sort || this.sortParam; // validate sortableParams
    var orderBy = req.query.order || this.sortOrder; // validate [asc, desc] or [1, -1]
    var skip = req.query.skip || req.query.offset || this.skip;
    var limit = req.query.limit || req.query.count || this.limit;
    skip = _.parseInt(skip) || 0;
    limit = _.parseInt(limit) || 0;
    limit = Math.min(limit, this.limit); // Hard limit at 100

    // Date Range params
    var createdQuery = this.buildTimestampQuery(created);
    var updatedQuery = this.buildTimestampQuery(updated);

    if (!_.isEmpty(createdQuery)) {
      queries.push({
        created: createdQuery
      });
    }
    if (!_.isEmpty(updatedQuery)) {
      queries.push({
        updated: updatedQuery
      });
    }

    // Filter params
    var queryParams = _.extend(_.result(this, 'queryParams'), {
      'user_id': 'string'
    });
    var filterParams = _.pick(req.query, _.keys(queryParams));
    var logicalOperator = '$' + (req.query.logical || 'and').toLowerCase().replace(/[@\s]/g, '');

    _.each(filterParams, function(val, key) {
      // If value is all, ignore this param
      if (val === 'all') {
        return;
      }

      // Support `,` as `$or` for each param
      var vals = val.split(',');

      // No value, ignore this param
      if (vals.length === 0) {
        return;
      }

      // The built query filter
      var filter = {};

      // Get param type
      var type = queryParams[key];

      // Deal with different param types
      if (type === 'string') {
        // strings and objectid
        // no transformation
      } else if (type === 'regex') {
        // regex case insensitive and escaping special characters
        // Always add `^` to use a prefix regex for index performance
        vals = _.map(vals, function(v) {
          return {
            '$regex': '^' + _.escapeRegExp(v),
            '$options': 'i'
          };
        });
      } else if (type === 'integer') {
        // integers
        vals = _.map(vals, function(v) {
          return _.parseInt(v);
        });
      } else if (type === 'float') {
        // floats
        vals = _.map(vals, function(v) {
          return parseFloat(v);
        });
      } else {
        // invalid or unknown type
        return;
      }

      // If there is only one val, no need to use `$or`
      if (vals.length === 1) {
        filter[key] = vals[0];
      } else {
        var orExpr = [];
        _.each(vals, function(orVal) {
          var orClause = {};
          orClause[key] = orVal;
          orExpr.push(orClause);
        });
        filter['$or'] = orExpr;
      }

      queries.push(filter);
    });

    // Combine the query
    if (queries.length > 0) {
      query[logicalOperator] = queries;
    }

    // Options
    // Sort/Order/Limit/Skip
    var sortOptions = [
      [sortBy, orderBy]
    ];

    return {
      'query': query,
      'sort': sortOptions,
      'limit': limit,
      'skip': skip
    };
  }
});
<|endoftext|>