<commit_before>import apogeeutil from "/apogeeutil/apogeeUtilLib.js";
import DataDisplay from "/apogeeview/datadisplay/DataDisplay.js";
import DATA_DISPLAY_CONSTANTS from "/apogeeview/datadisplay/dataDisplayConstants.js";
import {uiutil} from "/apogeeui/apogeeUiLib.js";
import ace from "/ext/ace/ace_1.4.3/ace.es.js";

/** Editor that uses the Ace text editor.
 *
 * @param {type} displayContainer - the display container
 * @param {type} dataSource - {updateComponent,getData,getEditOk,setData}; format for data is text
 * @param {type} aceMode - the display format, such as "ace/mode/json"
 */
export default class AceTextEditor extends DataDisplay {

    constructor(displayContainer,dataSource,aceMode,options) {
        super(displayContainer,dataSource);

        this.editorDiv = uiutil.createElement("div");

        //========================
        //this is for consistency of lines to pixels
        this.editorDiv.style.fontSize = "12px";
        this.editorDiv.style.lineHeight = "1.2";
        this.pixelsPerLine = 14;
        //=========================

        this.aceMode = aceMode;

        this.storedData = null;

        //configure the options
        if(!options) options = {};

        this.editorOptions = {};
        this.showSomeMaxLines = DEFAULT_MAX_LINES;
        if(options.displayMax) {
            this.resizeHeightMode = DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_MAX;
            this.editorOptions.maxLines = MAX_MAX_LINES;
        }
        else {
            this.resizeHeightMode = DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME;
            this.editorOptions.maxLines = this.showSomeMaxLines;
        }

        this.editorOptions.minLines = DEFAULT_MIN_LINES;

        //set variables for internal display view sizing
        this.setSupressContainerHorizontalScroll(true);
        this.setUseContainerHeightUi(true)
    }

    createEditor() {
        var editor = ace.edit(this.editorDiv);
        editor.setOptions(this.editorOptions);
        editor.renderer.setShowGutter(false);
        editor.setHighlightActiveLine(false);
        editor.setTheme("ace/theme/eclipse"); //good
        editor.getSession().setMode(this.aceMode);

        editor.$blockScrolling = Infinity;
        editor.renderer.attachToShadowRoot();

        this.editor = editor;

        if(this.storedData) {
            this.setData(this.storedData);
        }

        //enter edit mode on change to the data
        this.editor.addEventListener("input",() => this.checkStartEditMode());
    }

    getContent() {
        return this.editorDiv;
    }

    getData() {
        if(this.editor) {
            this.storedData = this.editor.getSession().getValue();
        }
        return this.storedData;
    }

    setData(text) {
        //The data source should give a text value "" if the data in invalid rather than sending
        //in a json, but we will do this check anyway.
        if(text == apogeeutil.INVALID_VALUE) {
            var errorMsg = "ERROR: Data value is not valid"
            text = "";
        }

        //check data is valid
        if(apogeeutil.getObjectType(text) != "String") {
            var errorMsg = "ERROR: Data value is not text";
            //this.setError(errorMsg);
            text = errorMsg;
        }

        //store the data
        this.storedData = text;

        //place ineditor, if it is present
        if(this.editor) {
            this.editor.getSession().setValue(text);

            //set the edit mode and background color
            if(this.editOk) {
                this.editorDiv.style.backgroundColor = "";
                this.editor.setReadOnly(false);
            }
            else {
                this.editorDiv.style.backgroundColor = DATA_DISPLAY_CONSTANTS.NO_EDIT_BACKGROUND_COLOR;
                this.editor.setReadOnly(true);
            }
        }
    }

    onLoad() {
        if(!this.editor) {
            this.createEditor();
        }
        this.editor.resize();
    }

    destroy() {
        if(this.editor) {
            this.editor.destroy();
            this.editor = null;
        }
    }

    checkStartEditMode() {
        if((!this.displayContainer.isInEditMode())&&(this.editor)) {
            var activeData = this.editor.getSession().getValue();
            if(activeData != this.storedData) {
                this.onTriggerEditMode();
            }
        }
    }

    //---------------------------
    // UI State Management
    //---------------------------

    /** This method adds any data display state info to the view state json.
     * By default there is none. Note that this modifies the json state of the view,
     * rather than providing a data object that will by added to it.. */
    addUiStateData(json) {
        if(this.editorOptions.maxLines) {
            json.height = this.editorOptions.maxLines * this.pixelsPerLine;
        }
    }

    /** This method reads an data display state info from the view state json. */
    readUiStateData(json) {
        if(json.height) {
            let maxLines = Math.round(json.height / this.pixelsPerLine);
            if(maxLines >= MAX_MAX_LINES) {
                this.resizeHeightMode = DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_MAX;
                maxLines = MAX_MAX_LINES;
            }
            else {
                this.resizeHeightMode = DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME;
                if(maxLines < DEFAULT_MIN_LINES) {
                    maxLines = DEFAULT_MIN_LINES;
                }
                this.showSomeMaxLines = maxLines;
            }

            this.editorOptions.maxLines = maxLines;

            if(this.editor) {
                this.editor.setOptions(this.editorOptions);
            }
        }
    }

    //----------------------------
    // This is the View resize API
    // The display has controls for the user to resize the display. These use the
    // following API to interact with the display
    //----------------------------

    /** This method gets the resize mode. Options:
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME;
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_MAX;
     */
    getResizeHeightMode() {
        return this.resizeHeightMode;
    }

    /** This method sets the resize mode. Options:
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME;
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_MAX;
     */
    setResizeHeightMode(resizeHeightMode) {
        if(resizeHeightMode == DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME) {
            this.resizeHeightMode = DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME;
            this.editorOptions.maxLines = this.showSomeMaxLines;
        }
        else if(resizeHeightMode == DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_MAX) {
            this.resizeHeightMode = DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_MAX;
            this.editorOptions.maxLines = MAX_MAX_LINES;
        }
        else {
            //ignore unknown value
            return;
        }

        if(this.editor) {
            this.editor.setOptions(this.editorOptions);
        }
    }

    /** This method adjusts the size when the resize mode is DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME. Options:
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MORE;
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_LESS;
    */
    adjustHeight(adjustment) {
        if(this.resizeHeightMode == DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME) {
            if(this.editor) {
                let newMaxLines;
                if(adjustment == DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_LESS) {
                    //decrease size by 1 line - except if our size is
                    //larger than the current doc, then shrink it to
                    //one line smaller than current doc.
                    let docLines = this.editor.getSession().getLength();
                    if(docLines < this.showSomeMaxLines) {
                        this.showSomeMaxLines = docLines;
                    }
                    newMaxLines = this.showSomeMaxLines - 1;
                    if(newMaxLines <  DEFAULT_MIN_LINES) {
                        newMaxLines = DEFAULT_MIN_LINES;
                    }
                }
                else if(adjustment == DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MORE) {
                    //just grow size by 1 line
                    newMaxLines = this.showSomeMaxLines + 1;
                    if(newMaxLines >  MAX_MAX_LINES) {
                        newMaxLines = MAX_MAX_LINES;
                    }
                }
                else {
                    //ignore an unknown command
                    return;
                }

                //update the lines options
                this.showSomeMaxLines = newMaxLines;
                this.editorOptions.maxLines = this.showSomeMaxLines;
                this.editor.setOptions(this.editorOptions);
            }
        }
    }

    /** This method returns the possible resize options, for use in the mode DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME. Flags:
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_LESS = 1;
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MORE = 2;
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_NONE = 0;
     * These flags should be or'ed togethder to give the allowed options.
    */
    getHeightAdjustFlags() {
        //We won't dynamically figufre out if we can add or remove lines based on current content. If
        //we add this we will have to track if it changes.
        //So they user may push these buttons and nothing will happen.
        //We will set the flags based on our absolute limits.
        let flags = 0;
        if(this.showSomeMaxLines < MAX_MAX_LINES) {
            flags = flags | DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MORE;
        }
        if(this.showSomeMaxLines > DEFAULT_MIN_LINES) {
            flags = flags | DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_LESS;
        }
        return flags;
    }
}

//options for displaying all or some lines
AceTextEditor.OPTION_SET_DISPLAY_MAX = { "displayMax":true};
AceTextEditor.OPTION_SET_DISPLAY_SOME = { "displayMax":false};

//configuration constants
let MAX_MAX_LINES = 500;
let DEFAULT_MAX_LINES = 20;
let DEFAULT_MIN_LINES = 2;
<commit_msg>put line numbers/fold widgets back in ace text editor<commit_after>import apogeeutil from "/apogeeutil/apogeeUtilLib.js";
import DataDisplay from "/apogeeview/datadisplay/DataDisplay.js";
import DATA_DISPLAY_CONSTANTS from "/apogeeview/datadisplay/dataDisplayConstants.js";
import {uiutil} from "/apogeeui/apogeeUiLib.js";
import ace from "/ext/ace/ace_1.4.3/ace.es.js";

/** Editor that uses the Ace text editor.
 *
 * @param {type} displayContainer - the display container
 * @param {type} dataSource - {updateComponent,getData,getEditOk,setData}; format for data is text
 * @param {type} aceMode - the display format, such as "ace/mode/json"
 */
export default class AceTextEditor extends DataDisplay {

    constructor(displayContainer,dataSource,aceMode,options) {
        super(displayContainer,dataSource);

        this.editorDiv = uiutil.createElement("div");

        //========================
        //this is for consistency of lines to pixels
        this.editorDiv.style.fontSize = "12px";
        this.editorDiv.style.lineHeight = "1.2";
        this.pixelsPerLine = 14;
        //=========================

        this.aceMode = aceMode;

        this.storedData = null;

        //configure the options
        if(!options) options = {};

        this.editorOptions = {};
        this.showSomeMaxLines = DEFAULT_MAX_LINES;
        if(options.displayMax) {
            this.resizeHeightMode = DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_MAX;
            this.editorOptions.maxLines = MAX_MAX_LINES;
        }
        else {
            this.resizeHeightMode = DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME;
            this.editorOptions.maxLines = this.showSomeMaxLines;
        }

        this.editorOptions.minLines = DEFAULT_MIN_LINES;

        //set variables for internal display view sizing
        this.setSupressContainerHorizontalScroll(true);
        this.setUseContainerHeightUi(true)
    }

    createEditor() {
        var editor = ace.edit(this.editorDiv);
        editor.setOptions(this.editorOptions);
        //editor.renderer.setShowGutter(false);
        editor.setHighlightActiveLine(false);
        editor.setTheme("ace/theme/eclipse");
        editor.getSession().setMode(this.aceMode);
        //below lets us change the line numbers
        // editor.getSession().gutterRenderer =  {
        //     getWidth: function(session, lastLineNumber, config) {
        //         return lastLineNumber.toString().length * config.characterWidth;
        //     },
        //     getText: function(session, row) {
        //         return row+20;
        //     }
        // };
        editor.$blockScrolling = Infinity;
        editor.renderer.attachToShadowRoot();

        this.editor = editor;

        if(this.storedData) {
            this.setData(this.storedData);
        }

        //enter edit mode on change to the data
        this.editor.addEventListener("input",() => this.checkStartEditMode());
    }

    getContent() {
        return this.editorDiv;
    }

    getData() {
        if(this.editor) {
            this.storedData = this.editor.getSession().getValue();
        }
        return this.storedData;
    }

    setData(text) {
        //The data source should give a text value "" if the data in invalid rather than sending
        //in a json, but we will do this check anyway.
        if(text == apogeeutil.INVALID_VALUE) {
            var errorMsg = "ERROR: Data value is not valid"
            text = "";
        }

        //check data is valid
        if(apogeeutil.getObjectType(text) != "String") {
            var errorMsg = "ERROR: Data value is not text";
            //this.setError(errorMsg);
            text = errorMsg;
        }

        //store the data
        this.storedData = text;

        //place ineditor, if it is present
        if(this.editor) {
            this.editor.getSession().setValue(text);

            //set the edit mode and background color
            if(this.editOk) {
                this.editorDiv.style.backgroundColor = "";
                this.editor.setReadOnly(false);
            }
            else {
                this.editorDiv.style.backgroundColor = DATA_DISPLAY_CONSTANTS.NO_EDIT_BACKGROUND_COLOR;
                this.editor.setReadOnly(true);
            }
        }
    }

    onLoad() {
        if(!this.editor) {
            this.createEditor();
        }
        this.editor.resize();
    }

    destroy() {
        if(this.editor) {
            this.editor.destroy();
            this.editor = null;
        }
    }

    checkStartEditMode() {
        if((!this.displayContainer.isInEditMode())&&(this.editor)) {
            var activeData = this.editor.getSession().getValue();
            if(activeData != this.storedData) {
                this.onTriggerEditMode();
            }
        }
    }

    //---------------------------
    // UI State Management
    //---------------------------

    /** This method adds any data display state info to the view state json.
     * By default there is none. Note that this modifies the json state of the view,
     * rather than providing a data object that will by added to it.. */
    addUiStateData(json) {
        if(this.editorOptions.maxLines) {
            json.height = this.editorOptions.maxLines * this.pixelsPerLine;
        }
    }

    /** This method reads an data display state info from the view state json. */
    readUiStateData(json) {
        if(json.height) {
            let maxLines = Math.round(json.height / this.pixelsPerLine);
            if(maxLines >= MAX_MAX_LINES) {
                this.resizeHeightMode = DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_MAX;
                maxLines = MAX_MAX_LINES;
            }
            else {
                this.resizeHeightMode = DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME;
                if(maxLines < DEFAULT_MIN_LINES) {
                    maxLines = DEFAULT_MIN_LINES;
                }
                this.showSomeMaxLines = maxLines;
            }

            this.editorOptions.maxLines = maxLines;

            if(this.editor) {
                this.editor.setOptions(this.editorOptions);
            }
        }
    }

    //----------------------------
    // This is the View resize API
    // The display has controls for the user to resize the display. These use the
    // following API to interact with the display
    //----------------------------

    /** This method gets the resize mode. Options:
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME;
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_MAX;
     */
    getResizeHeightMode() {
        return this.resizeHeightMode;
    }

    /** This method sets the resize mode. Options:
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME;
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_MAX;
     */
    setResizeHeightMode(resizeHeightMode) {
        if(resizeHeightMode == DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME) {
            this.resizeHeightMode = DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME;
            this.editorOptions.maxLines = this.showSomeMaxLines;
        }
        else if(resizeHeightMode == DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_MAX) {
            this.resizeHeightMode = DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_MAX;
            this.editorOptions.maxLines = MAX_MAX_LINES;
        }
        else {
            //ignore unknown value
            return;
        }

        if(this.editor) {
            this.editor.setOptions(this.editorOptions);
        }
    }

    /** This method adjusts the size when the resize mode is DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME. Options:
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MORE;
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_LESS;
    */
    adjustHeight(adjustment) {
        if(this.resizeHeightMode == DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME) {
            if(this.editor) {
                let newMaxLines;
                if(adjustment == DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_LESS) {
                    //decrease size by 1 line - except if our size is
                    //larger than the current doc, then shrink it to
                    //one line smaller than current doc.
                    let docLines = this.editor.getSession().getLength();
                    if(docLines < this.showSomeMaxLines) {
                        this.showSomeMaxLines = docLines;
                    }
                    newMaxLines = this.showSomeMaxLines - 1;
                    if(newMaxLines <  DEFAULT_MIN_LINES) {
                        newMaxLines = DEFAULT_MIN_LINES;
                    }
                }
                else if(adjustment == DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MORE) {
                    //just grow size by 1 line
                    newMaxLines = this.showSomeMaxLines + 1;
                    if(newMaxLines >  MAX_MAX_LINES) {
                        newMaxLines = MAX_MAX_LINES;
                    }
                }
                else {
                    //ignore an unknown command
                    return;
                }

                //update the lines options
                this.showSomeMaxLines = newMaxLines;
                this.editorOptions.maxLines = this.showSomeMaxLines;
                this.editor.setOptions(this.editorOptions);
            }
        }
    }

    /** This method returns the possible resize options, for use in the mode DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MODE_SOME. Flags:
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_LESS = 1;
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MORE = 2;
     * - DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_NONE = 0;
     * These flags should be or'ed togethder to give the allowed options.
    */
    getHeightAdjustFlags() {
        //We won't dynamically figufre out if we can add or remove lines based on current content. If
        //we add this we will have to track if it changes.
        //So they user may push these buttons and nothing will happen.
        //We will set the flags based on our absolute limits.
        let flags = 0;
        if(this.showSomeMaxLines < MAX_MAX_LINES) {
            flags = flags | DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_MORE;
        }
        if(this.showSomeMaxLines > DEFAULT_MIN_LINES) {
            flags = flags | DATA_DISPLAY_CONSTANTS.RESIZE_HEIGHT_LESS;
        }
        return flags;
    }
}

//options for displaying all or some lines
AceTextEditor.OPTION_SET_DISPLAY_MAX = { "displayMax":true};
AceTextEditor.OPTION_SET_DISPLAY_SOME = { "displayMax":false};

//configuration constants
let MAX_MAX_LINES = 500;
let DEFAULT_MAX_LINES = 20;
let DEFAULT_MIN_LINES = 2;
<|endoftext|>


<commit_before>/* ========================================================================
 * DOM-based Routing
 * Based on http://goo.gl/EUTi53 by Paul Irish
 *
 * Only fires on body classes that match. If a body class contains a dash,
 * replace the dash with an underscore when adding it to the object below.
 *
 * .noConflict()
 * The routing is enclosed within an anonymous function so that you can
 * always reference jQuery with $, even when in .noConflict() mode.
 *
 * Google CDN, Latest jQuery
 * To use the default WordPress version of jQuery, go to lib/config.php and
 * remove or comment out: add_theme_support('jquery-cdn');
 * ======================================================================== */

(function($) {

  // Use this variable to set up the common and page specific functions. If you
  // rename this variable, you will also need to rename the namespace below.
  var Sage = {
    // All pages
    'common': {
      init: function() {
        // JavaScript to be fired on all pages

        //smoothscrol
        $("a[href='#top']").click(function() {
          var speed = 750;
          $("html, body").animate({ scrollTop: 0 }, speed);
          return false;
        });

        $( '.submenu-link.active' ).removeClass( 'collapsed');
        $( '.submenu .active' ).parent().parent().addClass( 'in');

      },
      finalize: function() {
        // JavaScript to be fired on all pages, after page specific JS is fired

        var url = 'http://' + $(location).attr('host');

        //svg map
        $('#map').vectorMap({
            map: 'france_fr',
            hoverOpacity: 0.8,
            hoverColor: "#a0171e",
            backgroundColor: "transparent",
            color: "#736f80",
            selectedColor: '#a0171e',
            borderColor: "#fff",
            enableZoom: false,
            showTooltip: true,
            onRegionClick: function(element, code, region) {
              location.href= url + '/regions/' + region + '/';
            }
        });

      }
    },
    // Home page
    'home': {
      init: function() {
        // JavaScript to be fired on the home page
         $('.owl-carousel').owlCarousel({
            items:1,
            autoHeight:true
        });
      },
      finalize: function() {
        // JavaScript to be fired on the home page, after the init JS
      }
    },
    // About us page, note the change from about-us to about_us.
    'about_us': {
      init: function() {
        // JavaScript to be fired on the about us page
      }
    }
  };

  // The routing fires all common scripts, followed by the page specific scripts.
  // Add additional events for more control over timing e.g. a finalize event
  var UTIL = {
    fire: function(func, funcname, args) {
      var fire;
      var namespace = Sage;
      funcname = (funcname === undefined) ? 'init' : funcname;
      fire = func !== '';
      fire = fire && namespace[func];
      fire = fire && typeof namespace[func][funcname] === 'function';

      if (fire) {
        namespace[func][funcname](args);
      }
    },
    loadEvents: function() {
      // Fire common init JS
      UTIL.fire('common');

      // Fire page-specific init JS, and then finalize JS
      $.each(document.body.className.replace(/-/g, '_').split(/\s+/), function(i, classnm) {
        UTIL.fire(classnm);
        UTIL.fire(classnm, 'finalize');
      });

      // Fire common finalize JS
      UTIL.fire('common', 'finalize');
    }
  };

  // Load Events
  $(document).ready(UTIL.loadEvents);

})(jQuery); // Fully reference jQuery after this point.
<commit_msg>correction collapsed classes<commit_after>/* ========================================================================
 * DOM-based Routing
 * Based on http://goo.gl/EUTi53 by Paul Irish
 *
 * Only fires on body classes that match. If a body class contains a dash,
 * replace the dash with an underscore when adding it to the object below.
 *
 * .noConflict()
 * The routing is enclosed within an anonymous function so that you can
 * always reference jQuery with $, even when in .noConflict() mode.
 *
 * Google CDN, Latest jQuery
 * To use the default WordPress version of jQuery, go to lib/config.php and
 * remove or comment out: add_theme_support('jquery-cdn');
 * ======================================================================== */

(function($) {

  // Use this variable to set up the common and page specific functions. If you
  // rename this variable, you will also need to rename the namespace below.
  var Sage = {
    // All pages
    'common': {
      init: function() {
        // JavaScript to be fired on all pages

        //smoothscrol
        $("a[href='#top']").click(function() {
          var speed = 750;
          $("html, body").animate({ scrollTop: 0 }, speed);
          return false;
        });

        $( '.submenu .active' ).parents('.panel').find('.submenu-link').removeClass( 'collapsed');
        $( '.submenu .active' ).parents('.submenu').addClass( 'in');

      },
      finalize: function() {
        // JavaScript to be fired on all pages, after page specific JS is fired

        var url = 'http://' + $(location).attr('host');

        //svg map
        $('#map').vectorMap({
            map: 'france_fr',
            hoverOpacity: 0.8,
            hoverColor: "#a0171e",
            backgroundColor: "transparent",
            color: "#736f80",
            selectedColor: '#a0171e',
            borderColor: "#fff",
            enableZoom: false,
            showTooltip: true,
            onRegionClick: function(element, code, region) {
              location.href= url + '/regions/' + region + '/';
            }
        });

      }
    },
    // Home page
    'home': {
      init: function() {
        // JavaScript to be fired on the home page
         $('.owl-carousel').owlCarousel({
            items:1,
            autoHeight:true
        });
      },
      finalize: function() {
        // JavaScript to be fired on the home page, after the init JS
      }
    },
    // About us page, note the change from about-us to about_us.
    'about_us': {
      init: function() {
        // JavaScript to be fired on the about us page
      }
    }
  };

  // The routing fires all common scripts, followed by the page specific scripts.
  // Add additional events for more control over timing e.g. a finalize event
  var UTIL = {
    fire: function(func, funcname, args) {
      var fire;
      var namespace = Sage;
      funcname = (funcname === undefined) ? 'init' : funcname;
      fire = func !== '';
      fire = fire && namespace[func];
      fire = fire && typeof namespace[func][funcname] === 'function';

      if (fire) {
        namespace[func][funcname](args);
      }
    },
    loadEvents: function() {
      // Fire common init JS
      UTIL.fire('common');

      // Fire page-specific init JS, and then finalize JS
      $.each(document.body.className.replace(/-/g, '_').split(/\s+/), function(i, classnm) {
        UTIL.fire(classnm);
        UTIL.fire(classnm, 'finalize');
      });

      // Fire common finalize JS
      UTIL.fire('common', 'finalize');
    }
  };

  // Load Events
  $(document).ready(UTIL.loadEvents);

})(jQuery); // Fully reference jQuery after this point.
<|endoftext|>


<commit_before>import React               from 'react';
import SearchAppDispatcher from '../dispatcher/SearchAppDispatcher';
import ActionTypes         from '../constants/ActionTypes';
import TranscriptSearchAPI from '../utils/TranscriptSearchAPI';
import TranscriptStore     from '../stores/TranscriptStore';
import keymaster           from 'keymaster';

var Header        = React.createFactory(require('./Header'));
var SearchForm    = React.createFactory(require('./SearchForm'));
var Timeline      = React.createFactory(require('./Timeline'));
var ResultDetails = React.createFactory(require('./ResultDetails'));
var SpeechModal   = React.createFactory(require('./SpeechModal'));
var DevPanel      = React.createFactory(require('./DevPanel'));

var {div} = React.DOM;

// really not sure if this belongs here
SearchAppDispatcher.register(function (payload) {
    switch (payload.action.type) {
        case ActionTypes.SEARCH:
            TranscriptSearchAPI.search(payload.action.query, payload.action.interval);
            var searchPath = `/search/${encodeURIComponent(payload.action.query)}`;

            if (window.location.pathname !== searchPath) {
                window.history.pushState(
                    payload.action,
                    payload.action.query,
                    searchPath
                );
            }

            break;
        case ActionTypes.SPEECH_CONTEXT:
            TranscriptSearchAPI.speechContext(payload.action.transcript, payload.action.start, payload.action.end);
            break;
        case ActionTypes.RESET:
            window.history.pushState(null, null, '/');
            break;
        default:
        // nothing
    }
});

class SearchApp extends React.Component {
    constructor(props) {
        super(props);

        this.state             = this.fetchStateFromStore();
        this.state.unit        = 'pct';
        this.state.devPanel    = { visible: true };
        this.state.orientation = 'horizontal';
        this.state.interval    = '24w';
    }

    componentDidMount() {
        TranscriptStore.addChangeListener(this.handleChange.bind(this));
        window.addEventListener('popstate', this.handleStateChange.bind(this));

        // TODO: use keymaster to provide some instructions on '?'

        keymaster('ctrl+`', () => {
            this.setState({devPanel: {visible: !this.state.devPanel.visible}});
        });

        SearchAppDispatcher.handleViewAction({
            type: ActionTypes.SEARCH,
            query: this.initialQuery(),
            interval: this.state.interval
        });
    }

    componentWillUnmount() {
        TranscriptStore.removeChangeListener(this.handleChange.bind(this));
    }

    handleChange() {
        this.setState(this.fetchStateFromStore());
    }

    handleUnitChange(event) {
        this.setState({
            unit: event.target.value === '%' ? 'pct' : 'count'
        });
    }

    handleStateChange(event) {
        if (event.state) {
            SearchAppDispatcher.handleViewAction({
                type: ActionTypes.SEARCH,
                query: event.state.query,
                interval: event.state.interval
            });
        }
    }

    fetchStateFromStore() {
        return {
            query: TranscriptStore.getQuery(),
            result: TranscriptStore.getResult()
        };
    }

    initialQuery() {
        let match = window.location.pathname.match(/search\/(.+?)(\/|$)/);
        return match ? decodeURIComponent(match[1]) : 'skatt';
    }

    render() {
        return div({},
            Header(),
            div({className: 'container'},
                SearchForm({
                    interval: this.state.interval
                }),
                Timeline({
                    unit: this.state.unit,
                    query: this.state.query,
                    result: this.state.result,
                    onUnitChange: this.handleUnitChange.bind(this)
                }),
                ResultDetails({
                    unit: this.state.unit,
                    query: this.state.query,
                    result: this.state.result,
                    orientation: this.state.orientation
                }),
                SpeechModal(),
                DevPanel({
                    visible: this.state.devPanel.visible,
                    orientation: this.state.orientation,
                    interval: this.state.interval,
                    onOrientationChange: this.handleOrientationChange.bind(this),
                    onIntervalChange: this.handleIntervalChange.bind(this)
                })
            )
        );
    }

    handleOrientationChange(event) {
        this.setState({
            orientation: event.target.value
        });
    }

    handleIntervalChange(event) {
        this.setState({
            interval: event.target.value
        });
    }
}

module.exports = SearchApp;

<commit_msg>Hide dev panel by default.<commit_after>import React               from 'react';
import SearchAppDispatcher from '../dispatcher/SearchAppDispatcher';
import ActionTypes         from '../constants/ActionTypes';
import TranscriptSearchAPI from '../utils/TranscriptSearchAPI';
import TranscriptStore     from '../stores/TranscriptStore';
import keymaster           from 'keymaster';

var Header        = React.createFactory(require('./Header'));
var SearchForm    = React.createFactory(require('./SearchForm'));
var Timeline      = React.createFactory(require('./Timeline'));
var ResultDetails = React.createFactory(require('./ResultDetails'));
var SpeechModal   = React.createFactory(require('./SpeechModal'));
var DevPanel      = React.createFactory(require('./DevPanel'));

var {div} = React.DOM;

// really not sure if this belongs here
SearchAppDispatcher.register(function (payload) {
    switch (payload.action.type) {
        case ActionTypes.SEARCH:
            TranscriptSearchAPI.search(payload.action.query, payload.action.interval);
            var searchPath = `/search/${encodeURIComponent(payload.action.query)}`;

            if (window.location.pathname !== searchPath) {
                window.history.pushState(
                    payload.action,
                    payload.action.query,
                    searchPath
                );
            }

            break;
        case ActionTypes.SPEECH_CONTEXT:
            TranscriptSearchAPI.speechContext(payload.action.transcript, payload.action.start, payload.action.end);
            break;
        case ActionTypes.RESET:
            window.history.pushState(null, null, '/');
            break;
        default:
        // nothing
    }
});

class SearchApp extends React.Component {
    constructor(props) {
        super(props);

        this.state             = this.fetchStateFromStore();
        this.state.unit        = 'pct';
        this.state.devPanel    = { visible: false };
        this.state.orientation = 'horizontal';
        this.state.interval    = '24w';
    }

    componentDidMount() {
        TranscriptStore.addChangeListener(this.handleChange.bind(this));
        window.addEventListener('popstate', this.handleStateChange.bind(this));

        // TODO: use keymaster to provide some instructions on '?'

        keymaster('ctrl+`', () => {
            this.setState({devPanel: {visible: !this.state.devPanel.visible}});
        });

        SearchAppDispatcher.handleViewAction({
            type: ActionTypes.SEARCH,
            query: this.initialQuery(),
            interval: this.state.interval
        });
    }

    componentWillUnmount() {
        TranscriptStore.removeChangeListener(this.handleChange.bind(this));
    }

    handleChange() {
        this.setState(this.fetchStateFromStore());
    }

    handleUnitChange(event) {
        this.setState({
            unit: event.target.value === '%' ? 'pct' : 'count'
        });
    }

    handleStateChange(event) {
        if (event.state) {
            SearchAppDispatcher.handleViewAction({
                type: ActionTypes.SEARCH,
                query: event.state.query,
                interval: event.state.interval
            });
        }
    }

    fetchStateFromStore() {
        return {
            query: TranscriptStore.getQuery(),
            result: TranscriptStore.getResult()
        };
    }

    initialQuery() {
        let match = window.location.pathname.match(/search\/(.+?)(\/|$)/);
        return match ? decodeURIComponent(match[1]) : 'skatt';
    }

    render() {
        return div({},
            Header(),
            div({className: 'container'},
                SearchForm({
                    interval: this.state.interval
                }),
                Timeline({
                    unit: this.state.unit,
                    query: this.state.query,
                    result: this.state.result,
                    onUnitChange: this.handleUnitChange.bind(this)
                }),
                ResultDetails({
                    unit: this.state.unit,
                    query: this.state.query,
                    result: this.state.result,
                    orientation: this.state.orientation
                }),
                SpeechModal(),
                DevPanel({
                    visible: this.state.devPanel.visible,
                    orientation: this.state.orientation,
                    interval: this.state.interval,
                    onOrientationChange: this.handleOrientationChange.bind(this),
                    onIntervalChange: this.handleIntervalChange.bind(this)
                })
            )
        );
    }

    handleOrientationChange(event) {
        this.setState({
            orientation: event.target.value
        });
    }

    handleIntervalChange(event) {
        this.setState({
            interval: event.target.value
        });
    }
}

module.exports = SearchApp;

<|endoftext|>


<commit_before>Application.Services.factory("mcFlow", mcFlowService);
function mcFlowService() {
    var self = this;
    self.flow = new Flow(
        {
            target: "/api/upload/chunk",
            testChunks: false
        }
    );

    function each(obj, callback, context) {
        if (!obj) {
            return ;
        }
        var key;
        // Is Array?
        if (typeof(obj.length) !== 'undefined') {
            for (key = 0; key < obj.length; key++) {
                if (callback.call(context, obj[key], key) === false) {
                    return ;
                }
            }
        } else {
            for (key in obj) {
                if (obj.hasOwnProperty(key) && callback.call(context, obj[key], key) === false) {
                    return ;
                }
            }
        }
    }

    function extend(dst, src) {
        each(arguments, function(obj) {
            if (obj !== dst) {
                each(obj, function(value, key){
                    dst[key] = value;
                });
            }
        });
        return dst;
    }

    self.service = {
        get: function() {
            return self.flow;
        }
    };

    return self.service;
}
<commit_msg>Set fileParameterName for flow to the route used by the upload service.<commit_after>Application.Services.factory("mcFlow", mcFlowService);
function mcFlowService() {
    var self = this;
    self.flow = new Flow(
        {
            target: "/api/upload/chunk",
            testChunks: false,
            fileParameterName: "chunkData"
        }
    );

    function each(obj, callback, context) {
        if (!obj) {
            return ;
        }
        var key;
        // Is Array?
        if (typeof(obj.length) !== 'undefined') {
            for (key = 0; key < obj.length; key++) {
                if (callback.call(context, obj[key], key) === false) {
                    return ;
                }
            }
        } else {
            for (key in obj) {
                if (obj.hasOwnProperty(key) && callback.call(context, obj[key], key) === false) {
                    return ;
                }
            }
        }
    }

    function extend(dst, src) {
        each(arguments, function(obj) {
            if (obj !== dst) {
                each(obj, function(value, key){
                    dst[key] = value;
                });
            }
        });
        return dst;
    }

    self.service = {
        get: function() {
            return self.flow;
        }
    };

    return self.service;
}
<|endoftext|>


<commit_before>var kafka = require('kafka-node'),
    uuid = require('uuid'),
    config = require('config-node')(),
    consumers = {},
    compression = config.kafka.compression || 0,

    getConsumerId = function (group, instanceId) {
        return group + '/' + instanceId;
    },

    createConsumerInstance = function (consumer, topic) {
        var client = new kafka.Client(config.kafka.zkConnect, 'kafka-rest-proxy');
        consumer.instance = new kafka.HighLevelConsumer(client, [{
            topic: topic
        }], {
            groupId: consumer.group,
            // Auto commit config
            autoCommit: false,
            // The max wait time is the maximum amount of time in milliseconds to block waiting if insufficient data is available at the time the request is issued, default 100ms
            fetchMaxWaitMs: 100,
            // This is the minimum number of bytes of messages that must be available to give a response, default 1 byte
            fetchMinBytes: 1,
            // The maximum bytes to include in the message set for this partition. This helps bound the size of the response.
            fetchMaxBytes: 4 * 1024 * 1024, // 4MB
            // If set true, consumer will fetch message from the given offset in the payloads
            fromOffset: false,
            // If set to 'buffer', values will be returned as raw buffer objects.
            encoding: 'utf8'
        });
        consumer.instance.on('message', function (m) {
            consumer.messages.push(m);
        });
        consumer.instance.on('error', function (e) {
            console.error(e);
            consumer.instance.close(false, function () {
                setTimeout(function () {
                    console.log('recreating consumer');
                    createConsumerInstance(consumer, topic);
                }, 1000);
            });
        });
        consumer.instance.on('offsetOutOfRange', function (e) {
            console.warn(e);
        });
    };

module.exports = function (app) {

    app.post('/consumers/:group', function (req, res) {

        var group = req.params.group,
            instanceId = uuid.v4(),
            id = getConsumerId(group, instanceId);

        var autoOffsetReset =
            typeof (req.body['auto.offset.reset']) === 'undefined'
            ? 'largest' : req.body['auto.offset.reset'];
        var autoCommitEnable =
            typeof (req.body['auto.commit.enable']) === 'undefined'
            ? true : req.body['auto.commit.enable'];

        var consumer = {
            group: group,
            id: instanceId,
            autoOffsetReset: autoOffsetReset,
            autoCommitEnable: autoCommitEnable,
            instance: undefined,
            topics: [],
            messages: []
        };
        consumers[id] = consumer;

        res.json({
            instance_id: consumer.instanceId,
            base_uri: req.protocol + '://' + req.hostname + ':' + config.port + req.path + '/instances/' + consumer.id
        });

    });

    app.get('/consumers/:group/instances/:id/topics/:topic', function (req, res) {
        var id = getConsumerId(req.params.group, req.params.id),
            consumer = consumers[id],
            topic = req.params.topic;

        if (!consumer) {
            return res.status(404).json({ error: 'Consumer not found.' });
        }

        if (consumer.topics.indexOf(topic) == -1) {

            if (!consumer.instance) {
                createConsumerInstance(consumer, topic);
            }
            else {
                //TODO: support adding topics
            }
            consumer.topics.push(req.params.topic);

            setTimeout(function () {
                res.json([]);
            }, 1000);
        }
        else {
            var messages = consumer.messages.splice(0, consumer.messages.length);
            if (messages.length == 0) {
                return res.json([]);
            }
            res.json( messages.map(function (m) {
                return {
                    topic: m.topic,
                    partition: m.partition,
                    offset: m.offset,
                    key: m.key.toString(),
                    value: m.value
                };
            }) );
            consumer.instance.commit();
        }
    });

    app.post('/consumers/:group/instances/:id/offsets', function (req, res) {
        var id = getConsumerId(req.params.group, req.params.id),
            consumer = consumers[id];

        if (!consumer) {
            return res.status(404).json({ error: 'Consumer not found.' });
        }

        consumer.instance.commit(true, function (e, data) {
            if (e) {
                return res.status(500).json({ error: e });
            }
            return res.json([]);
        });
    });

    app.delete('/consumers/:group/instances/:id', function (req, res) {

        var id = getConsumerId(req.params.group, req.params.id),
            consumer = consumers[id];

        if (!consumer) {
            return res.status(404).json({ error: 'Consumer not found.' });
        }

        consumer.instance.close(false, function () {
            delete consumers[id];

            res.json({});
        });
    });

};<commit_msg>refactor getting consumer from hash to getConsumer<commit_after>var kafka = require('kafka-node'),
    uuid = require('uuid'),
    config = require('config-node')(),
    consumers = {},
    compression = config.kafka.compression || 0,

    getConsumerId = function (group, instanceId) {
        return group + '/' + instanceId;
    },
    getConsumer = function (group, instanceId) {
        return consumers[getConsumerId(group, instanceId)];
    },

    createConsumerInstance = function (consumer, topic) {
        var client = new kafka.Client(config.kafka.zkConnect, 'kafka-rest-proxy');
        consumer.instance = new kafka.HighLevelConsumer(client, [{
            topic: topic
        }], {
            groupId: consumer.group,
            // Auto commit config
            autoCommit: false,
            // The max wait time is the maximum amount of time in milliseconds to block waiting if insufficient data is available at the time the request is issued, default 100ms
            fetchMaxWaitMs: 100,
            // This is the minimum number of bytes of messages that must be available to give a response, default 1 byte
            fetchMinBytes: 1,
            // The maximum bytes to include in the message set for this partition. This helps bound the size of the response.
            fetchMaxBytes: 4 * 1024 * 1024, // 4MB
            // If set true, consumer will fetch message from the given offset in the payloads
            fromOffset: false,
            // If set to 'buffer', values will be returned as raw buffer objects.
            encoding: 'utf8'
        });
        consumer.instance.on('message', function (m) {
            consumer.messages.push(m);
        });
        consumer.instance.on('error', function (e) {
            console.error(e);
            consumer.instance.close(false, function () {
                setTimeout(function () {
                    console.log('recreating consumer');
                    createConsumerInstance(consumer, topic);
                }, 1000);
            });
        });
        consumer.instance.on('offsetOutOfRange', function (e) {
            console.warn(e);
        });
    };

module.exports = function (app) {

    app.post('/consumers/:group', function (req, res) {

        var group = req.params.group,
            instanceId = uuid.v4(),
            id = getConsumerId(group, instanceId);

        var autoOffsetReset =
            typeof (req.body['auto.offset.reset']) === 'undefined'
            ? 'largest' : req.body['auto.offset.reset'];
        var autoCommitEnable =
            typeof (req.body['auto.commit.enable']) === 'undefined'
            ? true : req.body['auto.commit.enable'];

        var consumer = {
            group: group,
            id: instanceId,
            autoOffsetReset: autoOffsetReset,
            autoCommitEnable: autoCommitEnable,
            instance: undefined,
            topics: [],
            messages: []
        };
        consumers[id] = consumer;

        res.json({
            instance_id: consumer.instanceId,
            base_uri: req.protocol + '://' + req.hostname + ':' + config.port + req.path + '/instances/' + consumer.id
        });

    });

    app.get('/consumers/:group/instances/:id/topics/:topic', function (req, res) {
        var consumer = getConsumer(req.params.group, req.params.id),
            topic = req.params.topic;

        if (!consumer) {
            return res.status(404).json({ error: 'Consumer not found.' });
        }

        if (consumer.topics.indexOf(topic) == -1) {

            if (!consumer.instance) {
                createConsumerInstance(consumer, topic);
            }
            else {
                //TODO: support adding topics
            }
            consumer.topics.push(req.params.topic);

            setTimeout(function () {
                res.json([]);
            }, 1000);
        }
        else {
            var messages = consumer.messages.splice(0, consumer.messages.length);
            if (messages.length == 0) {
                return res.json([]);
            }
            res.json( messages.map(function (m) {
                return {
                    topic: m.topic,
                    partition: m.partition,
                    offset: m.offset,
                    key: m.key.toString(),
                    value: m.value
                };
            }) );
            consumer.instance.commit();
        }
    });

    app.post('/consumers/:group/instances/:id/offsets', function (req, res) {
        var consumer = getConsumer(req.params.group, req.params.id);

        if (!consumer) {
            return res.status(404).json({ error: 'Consumer not found.' });
        }

        consumer.instance.commit(true, function (e, data) {
            if (e) {
                return res.status(500).json({ error: e });
            }
            return res.json([]);
        });
    });

    app.delete('/consumers/:group/instances/:id', function (req, res) {

        var id = getConsumerId(req.params.group, req.params.id),
            consumer = consumers[id];

        if (!consumer) {
            return res.status(404).json({ error: 'Consumer not found.' });
        }

        consumer.instance.close(false, function () {
            delete consumers[id];

            res.json({});
        });
    });

};<|endoftext|>


<commit_before>'use strict'

//this is what I want the final JSON to look like
//var navData = {username: "Rachel", url: "/Rachel/",
// posts: [ { title: "My first blog", entry: "I created a blog!", date: "2015-10-15"}, {title: "Essential Biking Safety Gear", entry: "I created a blog!", date: "2015-10-15"},{blogName: "Rachel's blog", name: "My third blog", details: "I created a thing!", date: "2015-10-15"}]
// pages: [{title: "something", content:"Some content", url:"someurl/"}]
// };

var mongoose = require("../models/index");
var db = mongoose.connection;

var Page = require('../models/Page.js');
var Post = require('../models/Post.js');

var done = function() {
  db.close();
};

var auth = function(req, res, next){ if (!req.isAuthenticated()) res.send(401); else {return next();} };

var showPage = function(user_id) {
  Page.find({'owner': user_id})
  .exec()
  .then(function(page) {
    console.log("THIS PAGE LIST IS FOR A SINGLE USER");
    console.log(page);

  }).catch(function(error){
    console.error(error);
  })
};

var showPost = function(user_id) {
  Post.find({'owner': user_id})
  .exec()
  .then(function(post) {
    console.log("THIS POST LIST IS FOR A SINGLE USER");
    console.log(post);
  }).catch(function(error){
    console.error(error);
  }).then(done)
  .then(function(post){
    return post;
  });
};

// var promiseChain = Page.find({'owner': user_id})
//   .exec()
//   .then(function(pages){
//     return {pages: pages};
//   }).then(function(pagesObject){
//     pagesObject.posts = Post.find({'owner': user_id});
//     return pagesObject;
//   });

var Dashboard = {
  auth: auth,

  get: function(req, res, next){
    var userId = req.user._id;

    var pagesPromise = Page.find({'owner': userId})
    .exec();

    var postsPromise = Post.find({'owner': userId})
    .exec();
      Promise.all([pagesPromise, postsPromise]).then(function(pagesAndPostsResults) {
        var pages = pagesAndPostsResults[0];
        var posts = pagesAndPostsResults[1];
        var sendBack = {username: req.user.userName, userId: userId,
    pages: pages, posts: posts};

    res.json(sendBack);
      }).catch(function(error){
        next (error);
      });
  }
};

module.exports = Dashboard;
<commit_msg>Comments out refactored code<commit_after>'use strict'

//this is what I want the final JSON to look like
//var navData = {username: "Rachel", url: "/Rachel/",
// posts: [ { title: "My first blog", entry: "I created a blog!", date: "2015-10-15"}, {title: "Essential Biking Safety Gear", entry: "I created a blog!", date: "2015-10-15"},{blogName: "Rachel's blog", name: "My third blog", details: "I created a thing!", date: "2015-10-15"}]
// pages: [{title: "something", content:"Some content", url:"someurl/"}]
// };

var mongoose = require("../models/index");
var db = mongoose.connection;

var Page = require('../models/Page.js');
var Post = require('../models/Post.js');

var done = function() {
  db.close();
};

var auth = function(req, res, next){ if (!req.isAuthenticated()) res.send(401); else {return next();} };

// var showPage = function(user_id) {
//   Page.find({'owner': user_id})
//   .exec()
//   .then(function(page) {
//     console.log("THIS PAGE LIST IS FOR A SINGLE USER");
//     console.log(page);

//   }).catch(function(error){
//     console.error(error);
//   })
// };

// var showPost = function(user_id) {
//   Post.find({'owner': user_id})
//   .exec()
//   .then(function(post) {
//     console.log("THIS POST LIST IS FOR A SINGLE USER");
//     console.log(post);
//   }).catch(function(error){
//     console.error(error);
//   })
//   .then(function(post){
//     return post;
//   });
// };

// var promiseChain = Page.find({'owner': user_id})
//   .exec()
//   .then(function(pages){
//     return {pages: pages};
//   }).then(function(pagesObject){
//     pagesObject.posts = Post.find({'owner': user_id});
//     return pagesObject;
//   });

var Dashboard = {
  auth: auth,

  get: function(req, res, next){
    var userId = req.user._id;

    var pagesPromise = Page.find({'owner': userId})
    .exec();

    var postsPromise = Post.find({'owner': userId})
    .exec();
      Promise.all([pagesPromise, postsPromise]).then(function(pagesAndPostsResults) {
        var pages = pagesAndPostsResults[0];
        var posts = pagesAndPostsResults[1];
        var sendBack = {username: req.user.userName, userId: userId,
    pages: pages, posts: posts};

    res.json(sendBack);
      }).catch(function(error){
        next (error);
      });
  }
};

module.exports = Dashboard;
<|endoftext|>


<commit_before>/*jslint node: true*/

"use strict";
var fs = require('fs'),
    path = require('path'),
    util = require('util'),
    http = require('http'),
    moment = require('moment');

function asArray(a) {
    if (Array.isArray(a)) {
        return a;
    } else if (a === null || a === undefined) {
        return [];
    } else {
        return [a];
    }
}

function Client(settings) {
    this.verbose  = !!settings.verbose; // false if not set

//    this.server   = settings.server   || "win-api-acc.westtoer.be";
    this.server   = settings.server   || "api.westtoer.tdms.acc.saga.be";
    this.version  = settings.version  || "v1";
    this.clientid = settings.clientid || "westtoer";
    this.secret   = settings.secret   || "no-secret";

    this.baseURI = "http://" + this.server + "/api/" + this.version + "/";
    this.authURI = "http://" + this.server + "/oauth/v2/token?grant_type=client_credentials&client_id=" +
        encodeURIComponent(this.clientid) + "&client_secret=" + encodeURIComponent(this.secret);

    // we initialize in a stopped modus
    this.stop();
}
Client.DEFAULT_PAGE = 1;
Client.DEFAULT_SIZE = 10;

function ProductQuery(tpl) {
    // clone - constructor
    if (tpl !== undefined && tpl.constructor === ProductQuery) {
        this.format = tpl.format;
        this.types = tpl.types.slice(0);
        this.touristictypes = tpl.touristictypes.slice(0);
        this.sizeVal = tpl.sizeVal;
        this.pageNum = tpl.pageNum;
        this.channels = tpl.channels.slice(0);
        this.lastmodExpr = tpl.lastmodExpr;
        this.softDelState = tpl.softDelState;
        this.pubState = tpl.pubState;

    } else {
        this.format = 'xml';
        this.types = ['accommodation']; //default zou alle types moeten kunnen bevatten
        this.touristictypes = [];
        this.sizeVal = Client.DEFAULT_SIZE;
        this.pageNum = Client.DEFAULT_PAGE;
        this.channels = [];
    }
}
ProductQuery.prototype.clone = function () {
    return new ProductQuery(this);
};
// paging
ProductQuery.prototype.page = function (page) {
    this.pageNum = Number(page) || Client.DEFAULT_PAGE;
    return this;
};
ProductQuery.prototype.size = function (size) {
    this.sizeVal = Number(size) || 10;
    return this;
};

// qrybuilder formats
ProductQuery.prototype.asJSON_HAL = function () {
    this.format = 'json+hal';
    return this;
};
ProductQuery.prototype.asJSON = function () {
    this.format = 'json';
    return this;
};
ProductQuery.prototype.asXML = function () {
    this.format = 'xml';
    return this;
};
//qrybuilder type filter
ProductQuery.prototype.forTypes = function (newtypes) {
    this.types = asArray(newtypes);
    return this;
};
ProductQuery.prototype.andType = function (singletype) {
    return this.types.push(singletype);
};
ProductQuery.prototype.ACCOMMODATION      = "accommodation";
ProductQuery.prototype.PERMANENT_OFFERING = "permanent_offering";
ProductQuery.prototype.RECA               = "reca";
ProductQuery.prototype.TEMPORARY_OFFERING = "temporary_offering";
ProductQuery.prototype.MEETINGROOM        = "meetingroom";

//qrybuilder trouristic_type filter
ProductQuery.prototype.forTouristicTypes = function (newtypes) {
    this.touristictypes = asArray(newtypes);
    return this;
};
ProductQuery.prototype.andTouristicType = function (singletype) {
    return this.touristictypes.push(singletype);
};

//qrybuilder lastmod filter
ProductQuery.prototype.lastmod = function (expr) {
    this.lastmodExpr = expr;
    return this;
};
function dateFormat(s) {
    if (s === undefined || s === null) {
        return "*";
    }
    return moment(s).format('YYYY-MM-DD');
}
ProductQuery.prototype.lastmodBetween = function (from, to) {
    from = dateFormat(from);
    to = dateFormat(to);
    return this.lastmod("[" + from + " TO " + to + "}"); // start boundary is inclusive, end-boundary is exclusive
};

//qrybuilder delete filter
ProductQuery.prototype.removed = function () {
    this.softDelState = true;
    return this;
};
ProductQuery.prototype.active = function () {
    this.softDelState = false;
    return this;
};
ProductQuery.prototype.ignoreRemoved = function () {
    this.softDelState = undefined;
    return this;
};

//qrybuilder pubchannel filter
ProductQuery.prototype.forChannels = function (chs) {
    this.channels = asArray(chs);
    return this;
};
ProductQuery.prototype.andChannel = function (ch) {
    return this.channels.push(ch);
};
ProductQuery.prototype.WESTTOER   = "westtoer*";
ProductQuery.prototype.BOL        = "brugse_ommeland*";
ProductQuery.prototype.WH         = "westhoek*";
ProductQuery.prototype.DEKUST     = "de_kust*";
ProductQuery.prototype.LEIESTREEK = "leiestreek*";

//qrybuilder published filter
ProductQuery.prototype.published = function () {
    this.pubState = true;
    return this;
};
ProductQuery.prototype.hidden = function () {
    this.pubState = false;
    return this;
};
ProductQuery.prototype.ignorePublished = function () {
    this.pubState = undefined;
    return this;
};

ProductQuery.addURI = function (key, value, unsetVal) {
    if (value === unsetVal) {
        return "";
    } // else
    return "&" + key + "=" + encodeURIComponent(value);
};

ProductQuery.addQueryVal = function (set, key, value) {
    if (value === undefined) {
        return;
    } // else
    return set.push("+" + key + ":" + value);
};

ProductQuery.addQueryList = function (set, key, valList) {
    if (valList === undefined || valList.length === 0) {
        return;
    } // else

    if (valList.length === 1) {
        set.push("+" + key + ":" + valList[0]);
    } else {
        set.push("+" + key + ":(" + this.channels.join(' OR ') + ")");
    }
};

ProductQuery.prototype.getURI = function (client) {
    if (this.types === undefined || this.types === null || this.types.length === 0) {
        throw "no types specified for fetch";
    }
    if (client.token === null || client.token_expires < Date.now()) {
        throw "client has no active token";
    }

    var uri = client.baseURI + this.types.join(',') +
        "?format=" + this.format +
        "&access_token=" + encodeURIComponent(client.token),
        q = [];

    uri += ProductQuery.addURI("size", this.sizeVal, Client.DEFAULT_SIZE);
    uri += ProductQuery.addURI("page", this.pageNum, Client.DEFAULT_PAGE);

    ProductQuery.addQueryVal(q, "metadata.tdms__update_date", this.lastmodExpr);
    ProductQuery.addQueryVal(q, "metadata.tdms__deleted", this.softDelState);
    ProductQuery.addQueryVal(q, "publishing_channels.tdms__published", this.pubState);

    ProductQuery.addQueryList(q, "publishing_channels.tdms__publishing_channel.@code", this.channels);
    ProductQuery.addQueryList(q, "metadata.touristic_product_type", this.touristictypes);

    if (q.length > 0) {
        uri += "&q=" + encodeURIComponent(q.join(' '));
    }

    return uri;
};

function getResponse(uri, cb, verbose) {
    verbose = verbose || false;
    if (verbose) {
        console.log("call uri [%s]", uri);
    }

    http.get(uri, function (res) {
        cb(null, res);
    }).on('error', function (e) {
        cb(e);
    });
}

function streamData(uri, sink, verbose) {
    getResponse(uri, function (e, res) {
        if (e) {
            sink.emit('error', e);
        } //else
        if (res.statusCode !== 200) {
            sink.emit('error', "error reading uri [" + uri + "] to stream - response.status == " + res.statusCode);
        } // else
        res.pipe(sink);
    }, verbose);
}

function getData(uri, cb, verbose) {
    getResponse(uri, function (e, res) {
        var data = "";
        if (e) {
            return cb(e);
        } //else
        res.on('data', function (chunk) {
            data += chunk;
        }).on('end', function () {
            cb(null, data);
        });
    }, verbose);
}

function getJSON(uri, cb, verbose) {
    getData(uri, function (e, data) {
        if (e) {
            return cb(e);
        }
        //else
        cb(null, JSON.parse(data));
    }, verbose);
}

function getXML(uri, cb, verbose) {
    //TODO parse to XML ?
    getData(uri, cb, verbose);
}

Client.prototype.stop = function () {
    clearTimeout(this.token_refresh);
    this.token = null;
    this.token_expires = Date.now();
    this.token_refresh = null;
};

Client.prototype.start = function (cb) {
    var me = this, SLACK_MILLIS = 1000;

    if (me.token_refresh !== null) { // already started...
        if (cb) {
            return cb(null); // no errors, but no token object either
        }
        return;
    }

    // else
    getJSON(this.authURI, function (e, resp) {
        if (e) {
            console.error("ERROR: %j", e);
            return cb(e);
        }

        me.token = resp.access_token;
        me.token_expires = Date.now() + resp.expires_in;
        if (resp.expires_in > SLACK_MILLIS) { // we assume at least 1s slack to operate
            me.token_refresh = setTimeout(function () {
                me.start();
            }, resp.expires_in - SLACK_MILLIS);
        }
        if (me.verbose) {
            console.log("got token %s - valid till %d", me.token, me.token_expires);
        }

        if (cb) {
            cb(e, resp);
        }
    }, this.verbose);
};

Client.prototype.fetch = function (qry, cb) {
    if (arguments.length < 2) {
        cb = qry;
        qry = new ProductQuery();
    }

    if (qry.format === 'json') {
        getJSON(qry.getURI(this), function (e, resp) {
            cb(e, resp);
        }, this.verbose);
    } else if (qry.format === 'json+hal') {
        getJSON(qry.getURI(this), function (e, resp) {
            var meta = resp, CONTENT = "_embedded";
            resp = meta[CONTENT].items;
            delete meta[CONTENT].items;
            cb(e, resp, meta);
        }, this.verbose);
    } else if (qry.format === 'xml') {
        getXML(qry.getURI(this), function (e, resp) {
            cb(e, resp);
        }, this.verbose);
    }
};

Client.prototype.stream = function (qry, sink) {
    if (arguments.length < 2) {
        sink = qry;
        qry = new ProductQuery();
    }

    streamData(qry.getURI(this), sink, this.verbose);
};

module.exports.client = function (settings) {
    return new Client(settings);
};
module.exports.query = function (service) {
    service = service || 'product';
    if (service === 'product') {
        return new ProductQuery();
    }
    throw "unknown service request";
};
<commit_msg>allow returning the respone to listen for events<commit_after>/*jslint node: true*/

"use strict";
var fs = require('fs'),
    path = require('path'),
    util = require('util'),
    http = require('http'),
    moment = require('moment');

function asArray(a) {
    if (Array.isArray(a)) {
        return a;
    } else if (a === null || a === undefined) {
        return [];
    } else {
        return [a];
    }
}

function Client(settings) {
    this.verbose  = !!settings.verbose; // false if not set

//    this.server   = settings.server   || "win-api-acc.westtoer.be";
    this.server   = settings.server   || "api.westtoer.tdms.acc.saga.be";
    this.version  = settings.version  || "v1";
    this.clientid = settings.clientid || "westtoer";
    this.secret   = settings.secret   || "no-secret";

    this.baseURI = "http://" + this.server + "/api/" + this.version + "/";
    this.authURI = "http://" + this.server + "/oauth/v2/token?grant_type=client_credentials&client_id=" +
        encodeURIComponent(this.clientid) + "&client_secret=" + encodeURIComponent(this.secret);

    // we initialize in a stopped modus
    this.stop();
}
Client.DEFAULT_PAGE = 1;
Client.DEFAULT_SIZE = 10;

function ProductQuery(tpl) {
    // clone - constructor
    if (tpl !== undefined && tpl.constructor === ProductQuery) {
        this.format = tpl.format;
        this.types = tpl.types.slice(0);
        this.touristictypes = tpl.touristictypes.slice(0);
        this.sizeVal = tpl.sizeVal;
        this.pageNum = tpl.pageNum;
        this.channels = tpl.channels.slice(0);
        this.lastmodExpr = tpl.lastmodExpr;
        this.softDelState = tpl.softDelState;
        this.pubState = tpl.pubState;

    } else {
        this.format = 'xml';
        this.types = ['accommodation']; //default zou alle types moeten kunnen bevatten
        this.touristictypes = [];
        this.sizeVal = Client.DEFAULT_SIZE;
        this.pageNum = Client.DEFAULT_PAGE;
        this.channels = [];
    }
}
ProductQuery.prototype.clone = function () {
    return new ProductQuery(this);
};
// paging
ProductQuery.prototype.page = function (page) {
    this.pageNum = Number(page) || Client.DEFAULT_PAGE;
    return this;
};
ProductQuery.prototype.size = function (size) {
    this.sizeVal = Number(size) || 10;
    return this;
};

// qrybuilder formats
ProductQuery.prototype.asJSON_HAL = function () {
    this.format = 'json+hal';
    return this;
};
ProductQuery.prototype.asJSON = function () {
    this.format = 'json';
    return this;
};
ProductQuery.prototype.asXML = function () {
    this.format = 'xml';
    return this;
};
//qrybuilder type filter
ProductQuery.prototype.forTypes = function (newtypes) {
    this.types = asArray(newtypes);
    return this;
};
ProductQuery.prototype.andType = function (singletype) {
    return this.types.push(singletype);
};
ProductQuery.prototype.ACCOMMODATION      = "accommodation";
ProductQuery.prototype.PERMANENT_OFFERING = "permanent_offering";
ProductQuery.prototype.RECA               = "reca";
ProductQuery.prototype.TEMPORARY_OFFERING = "temporary_offering";
ProductQuery.prototype.MEETINGROOM        = "meetingroom";

//qrybuilder trouristic_type filter
ProductQuery.prototype.forTouristicTypes = function (newtypes) {
    this.touristictypes = asArray(newtypes);
    return this;
};
ProductQuery.prototype.andTouristicType = function (singletype) {
    return this.touristictypes.push(singletype);
};

//qrybuilder lastmod filter
ProductQuery.prototype.lastmod = function (expr) {
    this.lastmodExpr = expr;
    return this;
};
function dateFormat(s) {
    if (s === undefined || s === null) {
        return "*";
    }
    return moment(s).format('YYYY-MM-DD');
}
ProductQuery.prototype.lastmodBetween = function (from, to) {
    from = dateFormat(from);
    to = dateFormat(to);
    return this.lastmod("[" + from + " TO " + to + "}"); // start boundary is inclusive, end-boundary is exclusive
};

//qrybuilder delete filter
ProductQuery.prototype.removed = function () {
    this.softDelState = true;
    return this;
};
ProductQuery.prototype.active = function () {
    this.softDelState = false;
    return this;
};
ProductQuery.prototype.ignoreRemoved = function () {
    this.softDelState = undefined;
    return this;
};

//qrybuilder pubchannel filter
ProductQuery.prototype.forChannels = function (chs) {
    this.channels = asArray(chs);
    return this;
};
ProductQuery.prototype.andChannel = function (ch) {
    return this.channels.push(ch);
};
ProductQuery.prototype.WESTTOER   = "westtoer*";
ProductQuery.prototype.BOL        = "brugse_ommeland*";
ProductQuery.prototype.WH         = "westhoek*";
ProductQuery.prototype.DEKUST     = "de_kust*";
ProductQuery.prototype.LEIESTREEK = "leiestreek*";

//qrybuilder published filter
ProductQuery.prototype.published = function () {
    this.pubState = true;
    return this;
};
ProductQuery.prototype.hidden = function () {
    this.pubState = false;
    return this;
};
ProductQuery.prototype.ignorePublished = function () {
    this.pubState = undefined;
    return this;
};

ProductQuery.addURI = function (key, value, unsetVal) {
    if (value === unsetVal) {
        return "";
    } // else
    return "&" + key + "=" + encodeURIComponent(value);
};

ProductQuery.addQueryVal = function (set, key, value) {
    if (value === undefined) {
        return;
    } // else
    return set.push("+" + key + ":" + value);
};

ProductQuery.addQueryList = function (set, key, valList) {
    if (valList === undefined || valList.length === 0) {
        return;
    } // else

    if (valList.length === 1) {
        set.push("+" + key + ":" + valList[0]);
    } else {
        set.push("+" + key + ":(" + this.channels.join(' OR ') + ")");
    }
};

ProductQuery.prototype.getURI = function (client) {
    if (this.types === undefined || this.types === null || this.types.length === 0) {
        throw "no types specified for fetch";
    }
    if (client.token === null || client.token_expires < Date.now()) {
        throw "client has no active token";
    }

    var uri = client.baseURI + this.types.join(',') +
        "?format=" + this.format +
        "&access_token=" + encodeURIComponent(client.token),
        q = [];

    uri += ProductQuery.addURI("size", this.sizeVal, Client.DEFAULT_SIZE);
    uri += ProductQuery.addURI("page", this.pageNum, Client.DEFAULT_PAGE);

    ProductQuery.addQueryVal(q, "metadata.tdms__update_date", this.lastmodExpr);
    ProductQuery.addQueryVal(q, "metadata.tdms__deleted", this.softDelState);
    ProductQuery.addQueryVal(q, "publishing_channels.tdms__published", this.pubState);

    ProductQuery.addQueryList(q, "publishing_channels.tdms__publishing_channel.@code", this.channels);
    ProductQuery.addQueryList(q, "metadata.touristic_product_type", this.touristictypes);

    if (q.length > 0) {
        uri += "&q=" + encodeURIComponent(q.join(' '));
    }

    return uri;
};

function getResponse(uri, cb, verbose) {
    verbose = verbose || false;
    if (verbose) {
        console.log("call uri [%s]", uri);
    }

    http.get(uri, function (res) {
        cb(null, res);
    }).on('error', function (e) {
        cb(e);
    });
}

function streamData(uri, sink, cb, verbose) {
    getResponse(uri, function (e, res) {
        if (e) {
            sink.emit('error', e);
        } //else
        if (res.statusCode !== 200) {
            sink.emit('error', "error reading uri [" + uri + "] to stream - response.status == " + res.statusCode);
        } // else
        res.pipe(sink);
        cb(res);
    }, verbose);
}

function getData(uri, cb, verbose) {
    getResponse(uri, function (e, res) {
        var data = "";
        if (e) {
            return cb(e);
        } //else
        res.on('data', function (chunk) {
            data += chunk;
        }).on('end', function () {
            cb(null, data);
        });
    }, verbose);
}

function getJSON(uri, cb, verbose) {
    getData(uri, function (e, data) {
        if (e) {
            return cb(e);
        }
        //else
        cb(null, JSON.parse(data));
    }, verbose);
}

function getXML(uri, cb, verbose) {
    //TODO parse to XML ?
    getData(uri, cb, verbose);
}

Client.prototype.stop = function () {
    clearTimeout(this.token_refresh);
    this.token = null;
    this.token_expires = Date.now();
    this.token_refresh = null;
};

Client.prototype.start = function (cb) {
    var me = this, SLACK_MILLIS = 1000;

    if (me.token_refresh !== null) { // already started...
        if (cb) {
            return cb(null); // no errors, but no token object either
        }
        return;
    }

    // else
    getJSON(this.authURI, function (e, resp) {
        if (e) {
            console.error("ERROR: %j", e);
            return cb(e);
        }

        me.token = resp.access_token;
        me.token_expires = Date.now() + resp.expires_in;
        if (resp.expires_in > SLACK_MILLIS) { // we assume at least 1s slack to operate
            me.token_refresh = setTimeout(function () {
                me.start();
            }, resp.expires_in - SLACK_MILLIS);
        }
        if (me.verbose) {
            console.log("got token %s - valid till %d", me.token, me.token_expires);
        }

        if (cb) {
            cb(e, resp);
        }
    }, this.verbose);
};

Client.prototype.fetch = function (qry, cb) {
    if (arguments.length < 2) {
        cb = qry;
        qry = new ProductQuery();
    }

    if (qry.format === 'json') {
        getJSON(qry.getURI(this), function (e, resp) {
            cb(e, resp);
        }, this.verbose);
    } else if (qry.format === 'json+hal') {
        getJSON(qry.getURI(this), function (e, resp) {
            var meta = resp, CONTENT = "_embedded";
            resp = meta[CONTENT].items;
            delete meta[CONTENT].items;
            cb(e, resp, meta);
        }, this.verbose);
    } else if (qry.format === 'xml') {
        getXML(qry.getURI(this), function (e, resp) {
            cb(e, resp);
        }, this.verbose);
    }
};

Client.prototype.stream = function (qry, sink, cb) {
    if (arguments.length < 2) {
        sink = qry;
        qry = new ProductQuery();
    }
    cb = cb || function (res) {}; // do nothing callback

    streamData(qry.getURI(this), sink, cb, this.verbose);
};

module.exports.client = function (settings) {
    return new Client(settings);
};
module.exports.query = function (service) {
    service = service || 'product';
    if (service === 'product') {
        return new ProductQuery();
    }
    throw "unknown service request";
};
<|endoftext|>


<commit_before>var sys    = require('sys');

var REQUIRED_NODE_VERSION = '0.1.99';
checkVersionNumber();

var events = require('events'),
    fs     = require('fs');

var csv = exports;

var CsvReader = csv.CsvReader = function(readStream, options) {
    var self = this;
    _setOptions(self, options);

    self.parsingStatus = {
        openRecord:    [],
        openField:     '',
        lastChar:      '',
        quotedField:   false,
        commentedLine: false
    };

    readStream.addListener('data', function(data) { self.parse(data) });
    readStream.addListener('error', function() { self.emit('error') });
    readStream.addListener('end', function() {
        if (self.parsingStatus.quotedField) {
            self.emit('error', new Error('Input stream ended but closing quotes expected'));
        } else {
            self.emit('end');
        }
    });
};
sys.inherits(CsvReader, events.EventEmitter);

CsvReader.prototype.parse = function(data) {
    var ps = this.parsingStatus;
    for (var i = 0; i < data.length; i++) {
        var c = data.charAt(i);
        switch (c) {
            // escape and separator may be the same char, typically '"'
            case this.escapechar:
            case this.quotechar:
                if (ps.commentedLine) break;
                var isEscape = false;
                if (c === this.escapechar) {
                    var nextChar = data.charAt(i + 1);
                    if (this._isEscapable(nextChar)) {
                        this._addCharacter(nextChar);
                        i++;
                        isEscape = true;
                    }
                }
                if (!isEscape && (c === this.quotechar)) {
                    if (ps.quotedField) {
                        // closing quote should be followed by separator
                        var nextChar = data.charAt(i + 1);
                        if (nextChar && nextChar != '\r' && nextChar != '\n' && nextChar !== this.separator) {
                            throw new Error("separator expected after a closing quote; found " + nextChar);
                        }
                        ps.quotedField = false;
                    } else if (ps.openField === '') {
                        ps.quotedField = true;
                    }
                }
                break;
            case this.separator:
                if (ps.commentedLine) break;
                if (ps.quotedField) {
                    this._addCharacter(c);
                } else {
                    this._addField();
                }
                break;
            case '\n':
                // handle CRLF sequence
                if (!ps.quotedField && (ps.lastChar === '\r')) {
                    break;
                }
            case '\r':
                if (ps.commentedLine) {
                    ps.commentedLine = false;
                } else if (ps.quotedField) {
                    this._addCharacter(c);
                } else {
                    this._addRecord();
                }
                break;
            case this.commentchar:
                if (ps.commentedLine) break;
                if (ps.openRecord.length === 0 && ps.openField === '' && !ps.quotedField) {
                    ps.commentedLine = true;
                } else {
                    this._addCharacter(c);
                }
            default:
                if (ps.commentedLine) break;
                this._addCharacter(c);
        }
        ps.lastChar = c;
    }
}

CsvReader.prototype._isEscapable = function(c) {
    if ((c === this.escapechar) || (c === this.quotechar)) {
        return true;
    }
    return false;
}

CsvReader.prototype._addCharacter = function(c) {
    this.parsingStatus.openField += c;
}

CsvReader.prototype._addField = function() {
    var ps = this.parsingStatus;
    ps.openRecord.push(ps.openField);
    ps.openField = '';
    ps.quotedField = false;
}

CsvReader.prototype._addRecord = function() {
    var ps = this.parsingStatus;
    this.emit('data', ps.openRecord);
    ps.openRecord = [];
    ps.openField = '';
    ps.quotedField = false;
}

csv.createCsvFileReader = function(path, options) {
    options = options || {};
    var readStream = fs.createReadStream(path, {
        'flags': 'r'
    });
    if (options.encoding) {
        readStream.setEncoding(options.encoding);
    } else {
        readStream.setEncoding('utf8');
    }
    return new CsvReader(readStream, options);
}

csv.createCsvStreamReader = function(readStream, options) {
    options = options || {};
    readStream.setEncoding(options.encoding ? options.encoding : 'utf8');
    return new CsvReader(readStream, options);
}

var CsvWriter = csv.CsvWriter = function(writeStream, options) {
    var self = this;
    self.writeStream = writeStream;
    _setOptions(self, options);

    writeStream.addListener('drain', function() { self.emit('drain') });
    writeStream.addListener('error', function() { self.emit('error') });
    writeStream.addListener('close', function() { self.emit('close') });
}
sys.inherits(CsvWriter, events.EventEmitter);

CsvWriter.prototype.writeRecord = function(rec) {
    if (!rec) return; // ignore empty records
    if (typeof(rec) !== 'object') {
        throw new Error("CsvWriter.writeRecord takes an array as an argument");
    }
    if (rec.length || rec.length === 0) { // array
        _writeArray(this, rec);
    } else {          // hash
        throw new Error("CsvWriter.writeRecord takes an array as an argument, "
                      + "hashes are not supported yet");
    }
}

function _writeArray(writer, arr) {
    var out = [];
    for (var i = 0; i < arr.length; i++) {
        if (i != 0) out.push(writer.separator);
        out.push(writer.quotechar);
        _appendField(out, writer, arr[i]);
        out.push(writer.quotechar);
    }
    out.push("\r\n");
    writer.writeStream.write(out.join(''));
}

function _appendField(outArr, writer, field) {
    for (var i = 0; i < field.length; i++) {
        if (field.charAt(i) === writer.quotechar || field.charAt(i) === writer.escapechar) {
            outArr.push(writer.escapechar);
        }
        outArr.push(field.charAt(i));
    }
}

csv.createCsvFileWriter = function(path, options) {
    options = options || {};
    var writeStream = fs.createWriteStream(path, {
        'flags': 'w'
    });
    if (options.encoding) {
        writeStream.setEncoding(options.encoding);
    } else {
        writeStream.setEncoding('utf8');
    }
    return new CsvWriter(writeStream, options);
}

csv.createCsvStreamWriter = function(writeStream, options) {
    options = options || {};
    writeStream.setEncoding(options.encoding ? options.encoding : 'utf8');
    return new CsvWriter(writeStream, options);
}

// ===============
// =   utils     =
// ===============

function _setOptions(obj, options) {
    options = options || {};
    obj.separator   = options.separator || ',';
    obj.quotechar   = options.quote     || '"';
    obj.escapechar  = options.escape    || '"';
    obj.commentchar = options.comment   || '';
}

function checkVersionNumber() {
    var supported = (function() {
        if (!process.version) return false;
        function version2fields(v) {
            var fields = v.split('.');
            return [ parseInt(fields[0]), parseInt(fields[1]), parseInt(fields[2]) ];
        }
        var r  = version2fields(REQUIRED_NODE_VERSION);
        var a  = version2fields(process.version.replace(/^v/, ''));
        if (a[0] > r[0]) {
            return true;
        } else if (a[0] === r[0]) {
            if (a[1] > r[1]) {
                return true;
            }  else if (a[1] === r[1]) {
                if (a[2] >= r[2]) return true;
            }
        }
        return false;
    })();
    if (! supported) {
        sys.debug("Unsupported Node.js version: expected "
                    + REQUIRED_NODE_VERSION + " or higher, got " + process.version);
    }
}
<commit_msg>private checkVersionMethod prefixed with _<commit_after>var sys    = require('sys');

var REQUIRED_NODE_VERSION = '0.1.99';
_checkVersionNumber();

var events = require('events'),
    fs     = require('fs');

var csv = exports;

var CsvReader = csv.CsvReader = function(readStream, options) {
    var self = this;
    _setOptions(self, options);

    self.parsingStatus = {
        openRecord:    [],
        openField:     '',
        lastChar:      '',
        quotedField:   false,
        commentedLine: false
    };

    readStream.addListener('data', function(data) { self.parse(data) });
    readStream.addListener('error', function() { self.emit('error') });
    readStream.addListener('end', function() {
        if (self.parsingStatus.quotedField) {
            self.emit('error', new Error('Input stream ended but closing quotes expected'));
        } else {
            self.emit('end');
        }
    });
};
sys.inherits(CsvReader, events.EventEmitter);

CsvReader.prototype.parse = function(data) {
    var ps = this.parsingStatus;
    for (var i = 0; i < data.length; i++) {
        var c = data.charAt(i);
        switch (c) {
            // escape and separator may be the same char, typically '"'
            case this.escapechar:
            case this.quotechar:
                if (ps.commentedLine) break;
                var isEscape = false;
                if (c === this.escapechar) {
                    var nextChar = data.charAt(i + 1);
                    if (this._isEscapable(nextChar)) {
                        this._addCharacter(nextChar);
                        i++;
                        isEscape = true;
                    }
                }
                if (!isEscape && (c === this.quotechar)) {
                    if (ps.quotedField) {
                        // closing quote should be followed by separator
                        var nextChar = data.charAt(i + 1);
                        if (nextChar && nextChar != '\r' && nextChar != '\n' && nextChar !== this.separator) {
                            throw new Error("separator expected after a closing quote; found " + nextChar);
                        }
                        ps.quotedField = false;
                    } else if (ps.openField === '') {
                        ps.quotedField = true;
                    }
                }
                break;
            case this.separator:
                if (ps.commentedLine) break;
                if (ps.quotedField) {
                    this._addCharacter(c);
                } else {
                    this._addField();
                }
                break;
            case '\n':
                // handle CRLF sequence
                if (!ps.quotedField && (ps.lastChar === '\r')) {
                    break;
                }
            case '\r':
                if (ps.commentedLine) {
                    ps.commentedLine = false;
                } else if (ps.quotedField) {
                    this._addCharacter(c);
                } else {
                    this._addRecord();
                }
                break;
            case this.commentchar:
                if (ps.commentedLine) break;
                if (ps.openRecord.length === 0 && ps.openField === '' && !ps.quotedField) {
                    ps.commentedLine = true;
                } else {
                    this._addCharacter(c);
                }
            default:
                if (ps.commentedLine) break;
                this._addCharacter(c);
        }
        ps.lastChar = c;
    }
}

CsvReader.prototype._isEscapable = function(c) {
    if ((c === this.escapechar) || (c === this.quotechar)) {
        return true;
    }
    return false;
}

CsvReader.prototype._addCharacter = function(c) {
    this.parsingStatus.openField += c;
}

CsvReader.prototype._addField = function() {
    var ps = this.parsingStatus;
    ps.openRecord.push(ps.openField);
    ps.openField = '';
    ps.quotedField = false;
}

CsvReader.prototype._addRecord = function() {
    var ps = this.parsingStatus;
    this.emit('data', ps.openRecord);
    ps.openRecord = [];
    ps.openField = '';
    ps.quotedField = false;
}

csv.createCsvFileReader = function(path, options) {
    options = options || {};
    var readStream = fs.createReadStream(path, {
        'flags': 'r'
    });
    if (options.encoding) {
        readStream.setEncoding(options.encoding);
    } else {
        readStream.setEncoding('utf8');
    }
    return new CsvReader(readStream, options);
}

csv.createCsvStreamReader = function(readStream, options) {
    options = options || {};
    readStream.setEncoding(options.encoding ? options.encoding : 'utf8');
    return new CsvReader(readStream, options);
}

var CsvWriter = csv.CsvWriter = function(writeStream, options) {
    var self = this;
    self.writeStream = writeStream;
    _setOptions(self, options);

    writeStream.addListener('drain', function() { self.emit('drain') });
    writeStream.addListener('error', function() { self.emit('error') });
    writeStream.addListener('close', function() { self.emit('close') });
}
sys.inherits(CsvWriter, events.EventEmitter);

CsvWriter.prototype.writeRecord = function(rec) {
    if (!rec) return; // ignore empty records
    if (typeof(rec) !== 'object') {
        throw new Error("CsvWriter.writeRecord takes an array as an argument");
    }
    if (rec.length || rec.length === 0) { // array
        _writeArray(this, rec);
    } else {          // hash
        throw new Error("CsvWriter.writeRecord takes an array as an argument, "
                      + "hashes are not supported yet");
    }
}

function _writeArray(writer, arr) {
    var out = [];
    for (var i = 0; i < arr.length; i++) {
        if (i != 0) out.push(writer.separator);
        out.push(writer.quotechar);
        _appendField(out, writer, arr[i]);
        out.push(writer.quotechar);
    }
    out.push("\r\n");
    writer.writeStream.write(out.join(''));
}

function _appendField(outArr, writer, field) {
    for (var i = 0; i < field.length; i++) {
        if (field.charAt(i) === writer.quotechar || field.charAt(i) === writer.escapechar) {
            outArr.push(writer.escapechar);
        }
        outArr.push(field.charAt(i));
    }
}

csv.createCsvFileWriter = function(path, options) {
    options = options || {};
    var writeStream = fs.createWriteStream(path, {
        'flags': 'w'
    });
    if (options.encoding) {
        writeStream.setEncoding(options.encoding);
    } else {
        writeStream.setEncoding('utf8');
    }
    return new CsvWriter(writeStream, options);
}

csv.createCsvStreamWriter = function(writeStream, options) {
    options = options || {};
    writeStream.setEncoding(options.encoding ? options.encoding : 'utf8');
    return new CsvWriter(writeStream, options);
}

// ===============
// =   utils     =
// ===============

function _setOptions(obj, options) {
    options = options || {};
    obj.separator   = options.separator || ',';
    obj.quotechar   = options.quote     || '"';
    obj.escapechar  = options.escape    || '"';
    obj.commentchar = options.comment   || '';
}

function _checkVersionNumber() {
    var supported = (function() {
        if (!process.version) return false;
        function version2fields(v) {
            var fields = v.split('.');
            return [ parseInt(fields[0]), parseInt(fields[1]), parseInt(fields[2]) ];
        }
        var r  = version2fields(REQUIRED_NODE_VERSION);
        var a  = version2fields(process.version.replace(/^v/, ''));
        if (a[0] > r[0]) {
            return true;
        } else if (a[0] === r[0]) {
            if (a[1] > r[1]) {
                return true;
            }  else if (a[1] === r[1]) {
                if (a[2] >= r[2]) return true;
            }
        }
        return false;
    })();
    if (! supported) {
        sys.debug("Unsupported Node.js version: expected "
                    + REQUIRED_NODE_VERSION + " or higher, got " + process.version);
    }
}
<|endoftext|>